Private/Generator/Tests/Get-OpenApiGenParameterModel.Tests.ps1
|
BeforeAll { $env:TCS_CONFIG_ROOT = Join-Path -Path $TestDrive -ChildPath 'config' $env:TCS_SKIP_UPDATE_CHECK = '1' $env:TCS_TELEMETRY_OPTOUT = '1' $ModuleRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -Parent Import-Module -Name (Join-Path -Path $ModuleRoot -ChildPath 'tcs.openapi.psd1') -Force $RepoRoot = Split-Path -Path (Split-Path -Path $ModuleRoot -Parent) -Parent . (Join-Path -Path $RepoRoot -ChildPath 'tests/Helpers/New-TestOpenApiModel.ps1') } Describe 'Get-OpenApiGenParameterModel' { BeforeAll { function Get-TestModel { param($Operation, [string]$BaseNoun = '') InModuleScope tcs.openapi -Parameters @{ Operation = $Operation; BaseNoun = $BaseNoun } { param($Operation, $BaseNoun) Get-OpenApiGenParameterModel -Operation $Operation -BaseNoun $BaseNoun } } function Get-TestParameter { param($Model, [string]$Name) @($Model.Parameters | Where-Object -FilterScript { $_.Name -eq $Name })[0] } } It 'uses PascalCase names and keeps the spec name' { $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method GET -Path '/x/{user_id}' -Parameters @( (New-TestParameter -Name 'user_id' -In path), (New-TestParameter -Name 'X-Request-Id' -In header) )) $user = Get-TestParameter $model 'UserId' $user.SpecName | Should -Be 'user_id' $user.In | Should -Be 'path' $user.Mandatory | Should -BeTrue $user.Aliases | Should -Be @('user_id') (Get-TestParameter $model 'XRequestId').Aliases | Should -Be @('X-Request-Id') (Get-TestParameter $model 'XRequestId').Mandatory | Should -BeFalse } It 'orders spec parameters path, query, header, cookie and ends with -Raw' { $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method GET -Path '/x/{id}' -Parameters @( (New-TestParameter -Name 'c' -In cookie), (New-TestParameter -Name 'h' -In header), (New-TestParameter -Name 'q' -In query), (New-TestParameter -Name 'id' -In path) )) $model.Parameters.Name | Should -Be @('Id', 'Q', 'H', 'C', 'Raw') } It 'renames parameters that clash with <Name> and reports OA041' -TestCases @( @{ Name = 'debug'; In = 'query'; Expected = 'DebugQuery' } @{ Name = 'ErrorAction'; In = 'header'; Expected = 'ErrorActionHeader' } @{ Name = 'raw'; In = 'query'; Expected = 'RawQuery' } @{ Name = 'all'; In = 'query'; Expected = 'AllQuery' } @{ Name = 'body'; In = 'query'; Expected = 'BodyQuery' } @{ Name = 'content-type'; In = 'header'; Expected = 'ContentTypeHeader' } @{ Name = 'OutFile'; In = 'query'; Expected = 'OutFileQuery' } @{ Name = 'Host'; In = 'header'; Expected = 'HostHeader' } @{ Name = 'input'; In = 'query'; Expected = 'InputQuery' } @{ Name = 'whatIf'; In = 'cookie'; Expected = 'WhatIfCookie' } ) { param($Name, $In, $Expected) $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method GET -Path '/x' -Parameters @((New-TestParameter -Name $Name -In $In))) $model.Parameters[0].Name | Should -BeExactly $Expected $model.Findings.Count | Should -Be 1 $model.Findings[0].Code | Should -Be 'OA041' $model.Findings[0].Severity | Should -Be 'Warning' } It 'gives the second of two parameters with one name a suffix, then a number' { $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method GET -Path '/x' -Parameters @( (New-TestParameter -Name 'user_id' -In query), (New-TestParameter -Name 'userId' -In query), (New-TestParameter -Name 'user-id' -In query), (New-TestParameter -Name 'USER_ID' -In header) )) $model.Parameters.Name | Should -Be @('UserId', 'UserIdQuery', 'UserIdQuery2', 'UserIdHeader', 'Raw') $model.Findings.Count | Should -Be 3 } It 'does not add an alias that is taken by another name or a common parameter alias' { $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method GET -Path '/x' -Parameters @( (New-TestParameter -Name 'user_id' -In query), (New-TestParameter -Name 'userId' -In header), (New-TestParameter -Name 'ea' -In query), (New-TestParameter -Name '$filter' -In query) )) (Get-TestParameter $model 'UserIdHeader').Aliases.Count | Should -Be 0 (Get-TestParameter $model 'Ea').Aliases.Count | Should -Be 0 (Get-TestParameter $model 'Filter').Aliases.Count | Should -Be 0 } It 'adds the Id alias to the path parameter named after the noun' { $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method GET -Path '/pets/{petId}/toys/{toyId}' -Parameters @( (New-TestParameter -Name 'petId' -In path), (New-TestParameter -Name 'toyId' -In path) )) -BaseNoun 'PetToy' (Get-TestParameter $model 'PetId').Aliases | Should -Be @() (Get-TestParameter $model 'ToyId').Aliases | Should -Be @('Id') } It 'uses [switch] for an optional query boolean and [bool] for a required header boolean' { $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method GET -Path '/x' -Parameters @( (New-TestParameter -Name 'verbose_output' -In query -Schema (New-TestSchema -Type boolean)), (New-TestParameter -Name 'strict' -In header -Required -Schema (New-TestSchema -Type boolean)) )) (Get-TestParameter $model 'VerboseOutput').TypeName | Should -Be 'switch' (Get-TestParameter $model 'Strict').TypeName | Should -Be 'bool' (Get-TestParameter $model 'Strict').Mandatory | Should -BeTrue } It 'flattens a JSON object body and adds -Body in its own parameter set' { $schema = New-TestSchema -Type object -Required @('name') -Properties ([ordered]@{ id = New-TestSchema -Type integer -ReadOnly name = New-TestSchema -Type string tags = New-TestSchema -Type array -Items (New-TestSchema -Type string) meta = New-TestSchema -Type object }) $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method POST -Path '/x' -RequestBody (New-TestRequestBody -Required -Content @((New-TestMediaType -ContentType 'application/json' -Schema $schema)))) $model.BodyMode | Should -Be 'Flattened' $model.BodyRequired | Should -BeTrue $model.Parameters.Name | Should -Be @('Name', 'Tags', 'Meta', 'Body', 'Raw') (Get-TestParameter $model 'Name').Mandatory | Should -BeTrue (Get-TestParameter $model 'Name').ParameterSet | Should -Be 'Parameters' (Get-TestParameter $model 'Name').In | Should -Be 'body' (Get-TestParameter $model 'Tags').Mandatory | Should -BeFalse (Get-TestParameter $model 'Meta').TypeName | Should -Be 'hashtable' (Get-TestParameter $model 'Body').ParameterSet | Should -Be 'Body' (Get-TestParameter $model 'Body').TypeName | Should -Be 'object' (Get-TestParameter $model 'Body').Mandatory | Should -BeTrue } It 'flattens a body given as a schema stub by looking it up in the schema map' { $named = New-TestSchema -Type object -RefName 'Pet' -Properties ([ordered]@{ name = New-TestSchema -Type string }) $stub = New-TestSchema -RefName 'Pet' $operation = New-TestOperation -OperationId 'x' -Method POST -Path '/x' -RequestBody (New-TestRequestBody -Content @((New-TestMediaType -ContentType 'application/json' -Schema $stub))) $model = InModuleScope tcs.openapi -Parameters @{ Operation = $operation; Schemas = [ordered]@{ Pet = $named } } { param($Operation, $Schemas) Get-OpenApiGenParameterModel -Operation $Operation -Schemas $Schemas } $model.BodyMode | Should -Be 'Flattened' $model.Parameters.Name | Should -Be @('Name', 'Body', 'Raw') } It 'makes body properties optional when the body is optional' { $schema = New-TestSchema -Type object -Required @('name') -Properties ([ordered]@{ name = New-TestSchema -Type string }) $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method POST -Path '/x' -RequestBody (New-TestRequestBody -Content @((New-TestMediaType -ContentType 'application/json' -Schema $schema)))) (Get-TestParameter $model 'Name').Mandatory | Should -BeFalse (Get-TestParameter $model 'Body').Mandatory | Should -BeFalse } It 'gives <Kind> bodies only -Body of type <Type>' -TestCases @( @{ Kind = 'form'; ContentType = 'application/x-www-form-urlencoded'; Schema = 'object'; Type = 'hashtable' } @{ Kind = 'multipart'; ContentType = 'multipart/form-data'; Schema = 'object'; Type = 'hashtable' } @{ Kind = 'binary'; ContentType = 'application/octet-stream'; Schema = 'binary'; Type = 'object' } @{ Kind = 'array'; ContentType = 'application/json'; Schema = 'array'; Type = 'object' } @{ Kind = 'text'; ContentType = 'text/plain'; Schema = 'string'; Type = 'object' } @{ Kind = 'oneOf'; ContentType = 'application/json'; Schema = 'oneOf'; Type = 'object' } ) { param($Kind, $ContentType, $Schema, $Type) $schemaObject = switch ($Schema) { 'object' { New-TestSchema -Type object -Properties ([ordered]@{ a = New-TestSchema -Type string }) } 'binary' { New-TestSchema -Type string -Format binary } 'array' { New-TestSchema -Type array -Items (New-TestSchema -Type string) } 'string' { New-TestSchema -Type string } 'oneOf' { New-TestSchema -OneOf @((New-TestSchema -Type object -Properties ([ordered]@{ a = New-TestSchema -Type string }))) } } $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method POST -Path '/x' -RequestBody (New-TestRequestBody -Required -Content @((New-TestMediaType -ContentType $ContentType -Schema $schemaObject)))) $model.BodyMode | Should -Be 'Body' $model.Parameters.Name | Should -Be @('Body', 'Raw') (Get-TestParameter $model 'Body').TypeName | Should -Be $Type (Get-TestParameter $model 'Body').ParameterSet | Should -BeNullOrEmpty } It 'suffixes a body property that clashes with a path parameter' { $schema = New-TestSchema -Type object -Properties ([ordered]@{ petId = New-TestSchema -Type string }) $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method PATCH -Path '/pets/{petId}' -Parameters @((New-TestParameter -Name 'petId' -In path)) -RequestBody (New-TestRequestBody -Content @((New-TestMediaType -ContentType 'application/json' -Schema $schema)))) $model.Parameters.Name | Should -Be @('PetId', 'PetIdBody', 'Body', 'Raw') $model.Findings[0].Code | Should -Be 'OA041' } It 'adds -ContentType when the body has several media types' { $schema = New-TestSchema -Type object -Properties ([ordered]@{ a = New-TestSchema -Type string }) $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method POST -Path '/x' -RequestBody (New-TestRequestBody -Content @((New-TestMediaType -ContentType 'application/json' -Schema $schema), (New-TestMediaType -ContentType 'application/xml' -Schema $schema)))) $model.ContentTypes | Should -Be @('application/json', 'application/xml') (Get-TestParameter $model 'ContentType').Attributes | Should -Be @("[ValidateSet('application/json', 'application/xml')]") } It 'adds -All for pageable operations and -OutFile for binary responses' { $operation = New-TestOperation -OperationId 'x' -Method GET -Path '/x' -Paging ([ordered]@{ Kind = 'nextLink' }) -Responses @((New-TestResponse -Content @((New-TestMediaType -ContentType 'application/pdf' -Schema (New-TestSchema -Type string -Format binary))))) $model = Get-TestModel -Operation $operation $model.Parameters.Name | Should -Be @('All', 'OutFile', 'Raw') $model.Pageable | Should -BeTrue $model.BinaryResponse | Should -BeTrue (Get-TestParameter $model 'All').TypeName | Should -Be 'switch' (Get-TestParameter $model 'OutFile').TypeName | Should -Be 'string' } It 'does not add -OutFile for JSON or error-only binary responses' { $operation = New-TestOperation -OperationId 'x' -Method GET -Path '/x' -Responses @( (New-TestResponse -Content @((New-TestMediaType -ContentType 'application/json' -Schema (New-TestSchema -Type object)))), (New-TestResponse -StatusCode 'default' -Content @((New-TestMediaType -ContentType 'application/octet-stream'))) ) (Get-TestModel -Operation $operation).Parameters.Name | Should -Be @('Raw') } It 'marks spec and body parameters for pipeline input by property name only' { $schema = New-TestSchema -Type object -Properties ([ordered]@{ a = New-TestSchema -Type string }) $model = Get-TestModel -Operation (New-TestOperation -OperationId 'x' -Method POST -Path '/x/{id}' -Parameters @((New-TestParameter -Name 'id' -In path)) -RequestBody (New-TestRequestBody -Content @((New-TestMediaType -ContentType 'application/json' -Schema $schema)))) ($model.Parameters | Where-Object -FilterScript { $_.Pipeline }).Name | Should -Be @('Id', 'A') } } |