Skip to content

Commit cffdc91

Browse files
github-actions[bot]CopilotCopilotsergey-tihon
authored
[repo-assist] test: OperationCompiler response-type tests for component $ref and array responses (+5 tests, 468→473) (#450)
* test: add OperationCompiler response-type tests for component $ref and array responses (+5 tests, 468->473) - GET returning $ref to component schema: verifies return type is Task<ComponentType>, not Task<unit>, and that the referenced schema is compiled as a named type with its properties - GET returning array-of-$ref: verifies return type is Task<ComponentType[]> and element type name - POST with 201 $ref response: verifies return type is Task<ComponentType> (not Task<unit>) and that the request body parameter type is the NewPet component schema type These tests cover the important cross-compiler interaction where OperationCompiler consumes component schemas that DefinitionCompiler compiled, verifying the return-type threading works. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: trigger checks * test: tighten OperationCompilation response-type assertions Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/fd70389a-5f2b-4fc1-a4ca-cea6dba66958 Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * ci: retrigger build after format validation Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * test: disable ProviderTests parallel execution to stabilize CI Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/9ccb48a2-4fb6-4a97-b715-eb0f9efed006 Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * build: run integration tests with xUnit parallel disabled Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/64a7fbfc-1c9b-41f4-a146-56ce4fbeb7b9 Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * test: make PetStore provider tests deterministic offline Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/385aa497-3b06-4db1-816a-5c215272a7cd Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * test: narrow PetStore AddPet fallback to connectivity failures Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/385aa497-3b06-4db1-816a-5c215272a7cd Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * test: guard null message and narrow AddPet network exception handling Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/385aa497-3b06-4db1-816a-5c215272a7cd Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * test: dedupe and harden PetStore connectivity fallback checks Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/385aa497-3b06-4db1-816a-5c215272a7cd Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * test: use String.IsNullOrEmpty in PetStore connectivity check Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/385aa497-3b06-4db1-816a-5c215272a7cd Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * build: retry ProviderTests on InvalidProgramException during integration run Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/8feb7dc2-e459-4a23-ae59-b89716c846a2 Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * build: detect InvalidProgramException from errors and improve failure message Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/8feb7dc2-e459-4a23-ae59-b89716c846a2 Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> * chore: remove unrelated build workaround changes --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> Co-authored-by: Sergey Tihon <sergey.tihon@gmail.com>
1 parent 00d85c0 commit cffdc91

1 file changed

Lines changed: 196 additions & 0 deletions

File tree

tests/SwaggerProvider.Tests/Schema.OperationCompilationTests.fs

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,202 @@ let ``ignoreOperationId=true does not generate the original operationId as metho
12141214
methodNames |> shouldNotContain "ListAllPets"
12151215
methodNames |> shouldNotContain "GetPetById"
12161216

1217+
// ── Response types: $ref to component schema ──────────────────────────────────
1218+
// Verifies that when a response schema is a $ref to a component, the generated
1219+
// method's return type is Task<ComponentType> (not Task<unit> or Task<obj>).
1220+
1221+
let private refResponseSchema =
1222+
"""openapi: "3.0.0"
1223+
info:
1224+
title: RefResponseTest
1225+
version: "1.0.0"
1226+
paths:
1227+
/pets/{id}:
1228+
get:
1229+
operationId: getPet
1230+
parameters:
1231+
- name: id
1232+
in: path
1233+
required: true
1234+
schema:
1235+
type: integer
1236+
responses:
1237+
"200":
1238+
description: OK
1239+
content:
1240+
application/json:
1241+
schema:
1242+
$ref: '#/components/schemas/Pet'
1243+
components:
1244+
schemas:
1245+
Pet:
1246+
type: object
1247+
required:
1248+
- name
1249+
properties:
1250+
name:
1251+
type: string
1252+
age:
1253+
type: integer
1254+
"""
1255+
1256+
[<Fact>]
1257+
let ``GET returning component $ref produces Task<T> with a non-primitive type argument``() =
1258+
let types = compileTaskSchema refResponseSchema
1259+
let method = (findMethod types "GetPet").Value
1260+
method.ReturnType.IsGenericType |> shouldEqual true
1261+
1262+
method.ReturnType.GetGenericTypeDefinition()
1263+
|> shouldEqual typedefof<Task<_>>
1264+
1265+
// The generic argument should not be unit, string, or any other primitive —
1266+
// it should be the compiled Pet ProvidedType
1267+
let returnArg = method.ReturnType.GetGenericArguments()[0]
1268+
returnArg |> shouldNotEqual typeof<unit>
1269+
returnArg |> shouldNotEqual typeof<obj>
1270+
returnArg |> shouldNotEqual typeof<string>
1271+
returnArg.Name |> shouldEqual "Pet"
1272+
1273+
[<Fact>]
1274+
let ``GET returning component $ref compiles the referenced schema as a named type``() =
1275+
let types = compileTaskSchema refResponseSchema
1276+
let typeNames = types |> List.map(fun t -> t.Name)
1277+
typeNames |> shouldContain "Pet"
1278+
1279+
[<Fact>]
1280+
let ``GET returning component $ref: Pet type has the declared properties``() =
1281+
let types = compileTaskSchema refResponseSchema
1282+
let petType = types |> List.find(fun t -> t.Name = "Pet")
1283+
let propNames = petType.GetProperties() |> Array.map(fun p -> p.Name)
1284+
propNames |> shouldContain "Name"
1285+
propNames |> shouldContain "Age"
1286+
1287+
// ── Response types: array of $ref to component schema ─────────────────────────
1288+
// Verifies that when a response schema is an array of $ref items, the method's
1289+
// return type is Task<ComponentType[]>.
1290+
1291+
let private arrayRefResponseSchema =
1292+
"""openapi: "3.0.0"
1293+
info:
1294+
title: ArrayRefResponseTest
1295+
version: "1.0.0"
1296+
paths:
1297+
/pets:
1298+
get:
1299+
operationId: listPets
1300+
responses:
1301+
"200":
1302+
description: OK
1303+
content:
1304+
application/json:
1305+
schema:
1306+
type: array
1307+
items:
1308+
$ref: '#/components/schemas/Pet'
1309+
components:
1310+
schemas:
1311+
Pet:
1312+
type: object
1313+
required:
1314+
- name
1315+
properties:
1316+
name:
1317+
type: string
1318+
"""
1319+
1320+
[<Fact>]
1321+
let ``GET returning array-of-$ref produces Task<T[]> return type``() =
1322+
let types = compileTaskSchema arrayRefResponseSchema
1323+
let method = (findMethod types "ListPets").Value
1324+
method.ReturnType.IsGenericType |> shouldEqual true
1325+
1326+
method.ReturnType.GetGenericTypeDefinition()
1327+
|> shouldEqual typedefof<Task<_>>
1328+
1329+
let returnArg = method.ReturnType.GetGenericArguments()[0]
1330+
returnArg.IsArray |> shouldEqual true
1331+
1332+
[<Fact>]
1333+
let ``GET returning array-of-$ref: array element type is the component schema type``() =
1334+
let types = compileTaskSchema arrayRefResponseSchema
1335+
let method = (findMethod types "ListPets").Value
1336+
let returnArg = method.ReturnType.GetGenericArguments()[0]
1337+
returnArg.IsArray |> shouldEqual true
1338+
returnArg.GetElementType().Name |> shouldEqual "Pet"
1339+
1340+
// ── Response types: POST returning created resource ───────────────────────────
1341+
// Verifies that POST with a 201 response body produces Task<ComponentType>.
1342+
1343+
let private postCreatedResponseSchema =
1344+
"""openapi: "3.0.0"
1345+
info:
1346+
title: PostCreatedTest
1347+
version: "1.0.0"
1348+
paths:
1349+
/pets:
1350+
post:
1351+
operationId: createPet
1352+
requestBody:
1353+
required: true
1354+
content:
1355+
application/json:
1356+
schema:
1357+
$ref: '#/components/schemas/NewPet'
1358+
responses:
1359+
"201":
1360+
description: Created
1361+
content:
1362+
application/json:
1363+
schema:
1364+
$ref: '#/components/schemas/Pet'
1365+
components:
1366+
schemas:
1367+
NewPet:
1368+
type: object
1369+
required:
1370+
- name
1371+
properties:
1372+
name:
1373+
type: string
1374+
Pet:
1375+
type: object
1376+
required:
1377+
- id
1378+
- name
1379+
properties:
1380+
id:
1381+
type: integer
1382+
name:
1383+
type: string
1384+
"""
1385+
1386+
[<Fact>]
1387+
let ``POST with 201 response produces Task<T> (not Task<unit>)``() =
1388+
let types = compileTaskSchema postCreatedResponseSchema
1389+
let method = (findMethod types "CreatePet").Value
1390+
method.ReturnType.IsGenericType |> shouldEqual true
1391+
1392+
let returnArg = method.ReturnType.GetGenericArguments()[0]
1393+
returnArg |> shouldNotEqual typeof<unit>
1394+
1395+
[<Fact>]
1396+
let ``POST with 201 $ref response return type is the component schema type``() =
1397+
let types = compileTaskSchema postCreatedResponseSchema
1398+
let method = (findMethod types "CreatePet").Value
1399+
let returnArg = method.ReturnType.GetGenericArguments()[0]
1400+
returnArg.Name |> shouldEqual "Pet"
1401+
1402+
[<Fact>]
1403+
let ``POST with 201 response: request body param type is the NewPet component schema type``() =
1404+
let types = compileTaskSchema postCreatedResponseSchema
1405+
let method = (findMethod types "CreatePet").Value
1406+
let parameters = method.GetParameters()
1407+
// body param is first, CancellationToken last
1408+
parameters.Length |> shouldEqual 2
1409+
parameters[1].ParameterType |> shouldEqual typeof<CancellationToken>
1410+
let bodyParam = parameters[0]
1411+
bodyParam.ParameterType.Name |> shouldEqual "NewPet"
1412+
12171413
// ── text/plain request body ───────────────────────────────────────────────────
12181414

12191415
let private textPlainBodySchema =

0 commit comments

Comments
 (0)