From 543264d3ccdf1b4858286cf534b53676e9d7c17c Mon Sep 17 00:00:00 2001 From: Arcturus Zhang Date: Sat, 14 Sep 2024 11:18:47 +0800 Subject: [PATCH 1/4] change responses/exceptions to an array --- .../src/example.ts | 26 +- .../src/http.ts | 16 +- .../src/interfaces.ts | 8 +- .../src/internal-utils.ts | 11 +- .../test/examples/example-types.test.ts | 372 ++++++++++-------- .../examples/http-operation-examples.test.ts | 28 +- .../test/package.test.ts | 44 +-- .../test/packages/parameters.test.ts | 29 +- .../test/packages/spread.test.ts | 10 +- 9 files changed, 298 insertions(+), 246 deletions(-) diff --git a/packages/typespec-client-generator-core/src/example.ts b/packages/typespec-client-generator-core/src/example.ts index 1689be8802..71f01166b4 100644 --- a/packages/typespec-client-generator-core/src/example.ts +++ b/packages/typespec-client-generator-core/src/example.ts @@ -9,7 +9,6 @@ import { isService, resolvePath, } from "@typespec/compiler"; -import { HttpStatusCodeRange } from "@typespec/http"; import { getOperationId } from "@typespec/openapi"; import { SdkArrayExampleValue, @@ -291,12 +290,12 @@ function handleHttpParameters( } function handleHttpResponses( - responses: Map, + responses: SdkHttpResponse[], example: any, relativePath: string -): [Map, readonly Diagnostic[]] { +): [SdkHttpResponseExampleValue[], readonly Diagnostic[]] { const diagnostics = createDiagnosticCollector(); - const responseExamples = new Map(); + const responseExamples: SdkHttpResponseExampleValue[] = []; if ( "responses" in example && typeof example.responses === "object" && @@ -305,11 +304,13 @@ function handleHttpResponses( for (const code of Object.keys(example.responses)) { const statusCode = parseInt(code, 10); let found = false; - for (const [responseCode, response] of responses.entries()) { + for (const response of responses) { + const responseCode = response.statusCodes; if (responseCode === statusCode) { - responseExamples.set( - statusCode, - diagnostics.pipe(handleHttpResponse(response, example.responses[code], relativePath)) + responseExamples.push( + diagnostics.pipe( + handleHttpResponse(response, statusCode, example.responses[code], relativePath) + ) ); found = true; break; @@ -319,9 +320,10 @@ function handleHttpResponses( responseCode.start <= statusCode && responseCode.end >= statusCode ) { - responseExamples.set( - statusCode, - diagnostics.pipe(handleHttpResponse(response, example.responses[code], relativePath)) + responseExamples.push( + diagnostics.pipe( + handleHttpResponse(response, statusCode, example.responses[code], relativePath) + ) ); found = true; break; @@ -341,12 +343,14 @@ function handleHttpResponses( function handleHttpResponse( response: SdkHttpResponse, + statusCode: number, example: any, relativePath: string ): [SdkHttpResponseExampleValue, readonly Diagnostic[]] { const diagnostics = createDiagnosticCollector(); const responseExample: SdkHttpResponseExampleValue = { response, + statusCode, headers: [], }; if (typeof example === "object" && example !== null) { diff --git a/packages/typespec-client-generator-core/src/http.ts b/packages/typespec-client-generator-core/src/http.ts index 77ecbe9cdc..08a43b2728 100644 --- a/packages/typespec-client-generator-core/src/http.ts +++ b/packages/typespec-client-generator-core/src/http.ts @@ -15,7 +15,6 @@ import { HttpOperationParameter, HttpOperationPathParameter, HttpOperationQueryParameter, - HttpStatusCodeRange, getHeaderFieldName, getHeaderFieldOptions, getPathParamName, @@ -412,14 +411,14 @@ function getSdkHttpResponseAndExceptions( httpOperation: HttpOperation ): [ { - responses: Map; - exceptions: Map; + responses: SdkHttpResponse[]; + exceptions: SdkHttpResponse[]; }, readonly Diagnostic[], ] { const diagnostics = createDiagnosticCollector(); - const responses: Map = new Map(); - const exceptions: Map = new Map(); + const responses: SdkHttpResponse[] = []; + const exceptions: SdkHttpResponse[] = []; for (const response of httpOperation.responses) { const headers: SdkServiceResponseHeader[] = []; let body: Type | undefined; @@ -471,6 +470,7 @@ function getSdkHttpResponseAndExceptions( kind: "http", type: body ? diagnostics.pipe(getClientTypeWithDiagnostics(context, body)) : undefined, headers, + statusCodes: response.statusCodes, contentTypes: contentTypes.length > 0 ? contentTypes : undefined, defaultContentType: contentTypes.includes("application/json") ? "application/json" @@ -482,10 +482,10 @@ function getSdkHttpResponseAndExceptions( ), description: response.description, }; - if (response.statusCodes === "*" || (body && isErrorModel(context.program, body))) { - exceptions.set(response.statusCodes, sdkResponse); + if (sdkResponse.statusCodes === "*" || (body && isErrorModel(context.program, body))) { + exceptions.push(sdkResponse); } else { - responses.set(response.statusCodes, sdkResponse); + responses.push(sdkResponse); } } return diagnostics.wrap({ responses, exceptions }); diff --git a/packages/typespec-client-generator-core/src/interfaces.ts b/packages/typespec-client-generator-core/src/interfaces.ts index 45b60574a0..c61c899619 100644 --- a/packages/typespec-client-generator-core/src/interfaces.ts +++ b/packages/typespec-client-generator-core/src/interfaces.ts @@ -550,6 +550,7 @@ export interface SdkHttpResponse extends SdkServiceResponse { contentTypes?: string[]; defaultContentType?: string; description?: string; + statusCodes: number | HttpStatusCodeRange | "*"; } interface SdkServiceOperationBase {} @@ -564,8 +565,8 @@ export interface SdkHttpOperation extends SdkServiceOperationBase { verb: HttpVerb; parameters: (SdkPathParameter | SdkQueryParameter | SdkHeaderParameter)[]; bodyParam?: SdkBodyParameter; - responses: Map; - exceptions: Map; + responses: SdkHttpResponse[]; + exceptions: SdkHttpResponse[]; examples?: SdkHttpOperationExample[]; } @@ -701,7 +702,7 @@ interface SdkExampleBase { export interface SdkHttpOperationExample extends SdkExampleBase { kind: "http"; parameters: SdkHttpParameterExampleValue[]; - responses: Map; + responses: SdkHttpResponseExampleValue[]; } export interface SdkHttpParameterExampleValue { @@ -711,6 +712,7 @@ export interface SdkHttpParameterExampleValue { export interface SdkHttpResponseExampleValue { response: SdkHttpResponse; + statusCode: number; headers: SdkHttpResponseHeaderExampleValue[]; bodyValue?: SdkExampleValue; } diff --git a/packages/typespec-client-generator-core/src/internal-utils.ts b/packages/typespec-client-generator-core/src/internal-utils.ts index bad7494cf1..fd708fe665 100644 --- a/packages/typespec-client-generator-core/src/internal-utils.ts +++ b/packages/typespec-client-generator-core/src/internal-utils.ts @@ -28,7 +28,6 @@ import { HttpOperationBody, HttpOperationMultipartBody, HttpOperationResponseContent, - HttpStatusCodeRange, } from "@typespec/http"; import { getAddedOnVersions, getRemovedOnVersions, getVersions } from "@typespec/versioning"; import { getParamAlias } from "./decorators.js"; @@ -397,15 +396,13 @@ export function getNullOption(type: Union): Type | undefined { return [...type.variants.values()].map((x) => x.type).filter((t) => isNullType(t))[0]; } -export function getAllResponseBodiesAndNonBodyExists( - responses: Map -): { +export function getAllResponseBodiesAndNonBodyExists(responses: SdkHttpResponse[]): { allResponseBodies: SdkType[]; nonBodyExists: boolean; } { const allResponseBodies: SdkType[] = []; let nonBodyExists = false; - for (const response of responses.values()) { + for (const response of responses) { if (response.type) { if (response.type.kind === "nullable") { nonBodyExists = true; @@ -418,9 +415,7 @@ export function getAllResponseBodiesAndNonBodyExists( return { allResponseBodies, nonBodyExists }; } -export function getAllResponseBodies( - responses: Map -): SdkType[] { +export function getAllResponseBodies(responses: SdkHttpResponse[]): SdkType[] { return getAllResponseBodiesAndNonBodyExists(responses).allResponseBodies; } diff --git a/packages/typespec-client-generator-core/test/examples/example-types.test.ts b/packages/typespec-client-generator-core/test/examples/example-types.test.ts index 7d2703493a..7dac3dbd73 100644 --- a/packages/typespec-client-generator-core/test/examples/example-types.test.ts +++ b/packages/typespec-client-generator-core/test/examples/example-types.test.ts @@ -1,13 +1,7 @@ import { expectDiagnostics } from "@typespec/compiler/testing"; import { deepStrictEqual, ok, strictEqual } from "assert"; import { beforeEach, describe, it } from "vitest"; -import { - SdkDateTimeType, - SdkDurationType, - SdkHttpOperation, - SdkNullableType, - SdkServiceMethod, -} from "../../src/interfaces.js"; +import { SdkHttpOperation, SdkServiceMethod } from "../../src/interfaces.js"; import { SdkTestRunner, createSdkTestRunner } from "../test-host.js"; describe("typespec-client-generator-core: example types", () => { @@ -37,9 +31,11 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "string"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, "test"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "string"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "string"); + strictEqual(response.bodyValue?.value, "test"); + strictEqual(response.bodyValue?.type.kind, "string"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -61,7 +57,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getStringDiagnostic.json' does not follow its definition:\n123`, @@ -85,9 +83,11 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "string"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, "test"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "constant"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "string"); + strictEqual(response.bodyValue?.value, "test"); + strictEqual(response.bodyValue?.type.kind, "constant"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -109,7 +109,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getStringFromConstantDiagnostic.json' does not follow its definition:\n123`, @@ -136,9 +138,11 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "string"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, "one"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "enum"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "string"); + strictEqual(response.bodyValue?.value, "one"); + strictEqual(response.bodyValue?.type.kind, "enum"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -163,7 +167,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getStringFromEnumDiagnostic.json' does not follow its definition:\n"four"`, @@ -190,9 +196,11 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "string"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, "one"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "enumvalue"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "string"); + strictEqual(response.bodyValue?.value, "one"); + strictEqual(response.bodyValue?.type.kind, "enumvalue"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -217,7 +225,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getStringFromEnumValueDiagnostic.json' does not follow its definition:\n"four"`, @@ -241,16 +251,12 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "string"); - strictEqual( - operation.examples[0].responses.get(200)?.bodyValue?.value, - "2022-08-26T18:38:00.000Z" - ); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "utcDateTime"); - strictEqual( - (operation.examples[0].responses.get(200)?.bodyValue?.type as SdkDateTimeType).wireType.kind, - "string" - ); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "string"); + strictEqual(response.bodyValue?.value, "2022-08-26T18:38:00.000Z"); + strictEqual(response.bodyValue?.type.kind, "utcDateTime"); + strictEqual(response.bodyValue?.type.wireType.kind, "string"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -272,13 +278,12 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "string"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, "P40D"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "duration"); - strictEqual( - (operation.examples[0].responses.get(200)?.bodyValue?.type as SdkDurationType).wireType.kind, - "string" - ); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response?.bodyValue?.kind, "string"); + strictEqual(response?.bodyValue?.value, "P40D"); + strictEqual(response?.bodyValue?.type.kind, "duration"); + strictEqual(response.bodyValue?.type.wireType.kind, "string"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -300,9 +305,11 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "number"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, 31.752); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "float32"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "number"); + strictEqual(response.bodyValue?.value, 31.752); + strictEqual(response.bodyValue?.type.kind, "float32"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -324,7 +331,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getNumberDiagnostic.json' does not follow its definition:\n"123"`, @@ -351,13 +360,12 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "number"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, 1686566864); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "utcDateTime"); - strictEqual( - (operation.examples[0].responses.get(200)?.bodyValue?.type as SdkDateTimeType).wireType.kind, - "int64" - ); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "number"); + strictEqual(response.bodyValue?.value, 1686566864); + strictEqual(response.bodyValue?.type.kind, "utcDateTime"); + strictEqual(response.bodyValue?.type.wireType.kind, "int64"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -382,13 +390,12 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "number"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, 62.525); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "duration"); - strictEqual( - (operation.examples[0].responses.get(200)?.bodyValue?.type as SdkDurationType).wireType.kind, - "float" - ); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "number"); + strictEqual(response.bodyValue?.value, 62.525); + strictEqual(response.bodyValue?.type.kind, "duration"); + strictEqual(response.bodyValue?.type.wireType.kind, "float"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -410,9 +417,11 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "boolean"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, true); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "boolean"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "boolean"); + strictEqual(response.bodyValue?.value, true); + strictEqual(response.bodyValue?.type.kind, "boolean"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -434,7 +443,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getBooleanDiagnostic.json' does not follow its definition:\n123`, @@ -458,13 +469,12 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "null"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, null); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "nullable"); - strictEqual( - (operation.examples[0].responses.get(200)?.bodyValue?.type as SdkNullableType).type.kind, - "string" - ); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "null"); + strictEqual(response.bodyValue?.value, null); + strictEqual(response.bodyValue?.type.kind, "nullable"); + strictEqual(response.bodyValue?.type.type.kind, "string"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -486,8 +496,10 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "unknown"); - deepStrictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, { test: 123 }); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "unknown"); + deepStrictEqual(response.bodyValue?.value, { test: 123 }); expectDiagnostics(runner.context.diagnostics, []); }); @@ -509,9 +521,11 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.kind, "union"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.value, "test"); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue?.type.kind, "union"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "union"); + strictEqual(response.bodyValue?.value, "test"); + strictEqual(response.bodyValue?.type.kind, "union"); }); it("SdkArrayExample", async () => { @@ -531,21 +545,21 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - const example = operation.examples[0].responses.get(200)?.bodyValue; - ok(example); - strictEqual(example.kind, "array"); - strictEqual(example.value.length, 3); - strictEqual(example.type.kind, "array"); - strictEqual(example.type.valueType.kind, "string"); - strictEqual(example.value[0].value, "a"); - strictEqual(example.value[0].kind, "string"); - strictEqual(example.value[0].type.kind, "string"); - strictEqual(example.value[1].value, "b"); - strictEqual(example.value[1].kind, "string"); - strictEqual(example.value[1].type.kind, "string"); - strictEqual(example.value[2].value, "c"); - strictEqual(example.value[2].kind, "string"); - strictEqual(example.value[2].type.kind, "string"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue?.kind, "array"); + strictEqual(response.bodyValue.value.length, 3); + strictEqual(response.bodyValue.type.kind, "array"); + strictEqual(response.bodyValue.type.valueType.kind, "string"); + strictEqual(response.bodyValue.value[0].value, "a"); + strictEqual(response.bodyValue.value[0].kind, "string"); + strictEqual(response.bodyValue.value[0].type.kind, "string"); + strictEqual(response.bodyValue.value[1].value, "b"); + strictEqual(response.bodyValue.value[1].kind, "string"); + strictEqual(response.bodyValue.value[1].type.kind, "string"); + strictEqual(response.bodyValue.value[2].value, "c"); + strictEqual(response.bodyValue.value[2].kind, "string"); + strictEqual(response.bodyValue.value[2].type.kind, "string"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -567,7 +581,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getArrayDiagnostic.json' does not follow its definition:\n"test"`, @@ -591,19 +607,21 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - const example = operation.examples[0].responses.get(200)?.bodyValue; - ok(example); - strictEqual(example.kind, "dict"); - strictEqual(Object.keys(example.value).length, 3); - strictEqual(example.value["a"].value, "a"); - strictEqual(example.value["a"].kind, "string"); - strictEqual(example.value["a"].type.kind, "string"); - strictEqual(example.value["b"].value, "b"); - strictEqual(example.value["b"].kind, "string"); - strictEqual(example.value["b"].type.kind, "string"); - strictEqual(example.value["c"].value, "c"); - strictEqual(example.value["c"].kind, "string"); - strictEqual(example.value["c"].type.kind, "string"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + const bodyValue = response.bodyValue; + ok(bodyValue); + strictEqual(bodyValue.kind, "dict"); + strictEqual(Object.keys(bodyValue.value).length, 3); + strictEqual(bodyValue.value["a"].value, "a"); + strictEqual(bodyValue.value["a"].kind, "string"); + strictEqual(bodyValue.value["a"].type.kind, "string"); + strictEqual(bodyValue.value["b"].value, "b"); + strictEqual(bodyValue.value["b"].kind, "string"); + strictEqual(bodyValue.value["b"].type.kind, "string"); + strictEqual(bodyValue.value["c"].value, "c"); + strictEqual(bodyValue.value["c"].kind, "string"); + strictEqual(bodyValue.value["c"].type.kind, "string"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -625,7 +643,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getDictionaryDiagnostic.json' does not follow its definition:\n"test"`, @@ -657,21 +677,23 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - const example = operation.examples[0].responses.get(200)?.bodyValue; - ok(example); - strictEqual(example.kind, "model"); - strictEqual(example.type.kind, "model"); - strictEqual(example.type.name, "Test"); - strictEqual(Object.keys(example.value).length, 3); - strictEqual(example.value["a"].value, "a"); - strictEqual(example.value["a"].kind, "string"); - strictEqual(example.value["a"].type.kind, "string"); - strictEqual(example.value["b"].value, 2); - strictEqual(example.value["b"].kind, "number"); - strictEqual(example.value["b"].type.kind, "int32"); - strictEqual(example.value["prop"].value, "prop"); - strictEqual(example.value["prop"].kind, "string"); - strictEqual(example.value["prop"].type.kind, "string"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + const bodyValue = response.bodyValue; + ok(bodyValue); + strictEqual(bodyValue.kind, "model"); + strictEqual(bodyValue.type.kind, "model"); + strictEqual(bodyValue.type.name, "Test"); + strictEqual(Object.keys(bodyValue.value).length, 3); + strictEqual(bodyValue.value["a"].value, "a"); + strictEqual(bodyValue.value["a"].kind, "string"); + strictEqual(bodyValue.value["a"].type.kind, "string"); + strictEqual(bodyValue.value["b"].value, 2); + strictEqual(bodyValue.value["b"].kind, "number"); + strictEqual(bodyValue.value["b"].type.kind, "int32"); + strictEqual(bodyValue.value["prop"].value, "prop"); + strictEqual(bodyValue.value["prop"].kind, "string"); + strictEqual(bodyValue.value["prop"].type.kind, "string"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -748,21 +770,23 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - const example = operation.examples[0].responses.get(200)?.bodyValue; - ok(example); - strictEqual(example.kind, "model"); - strictEqual(example.type.kind, "model"); - strictEqual(example.type.name, "SawShark"); - strictEqual(Object.keys(example.value).length, 6); - strictEqual(example.value["kind"].value, "shark"); - strictEqual(example.value["kind"].kind, "string"); - strictEqual(example.value["kind"].type.kind, "constant"); - strictEqual(example.value["sharktype"].value, "saw"); - strictEqual(example.value["sharktype"].kind, "string"); - strictEqual(example.value["sharktype"].type.kind, "constant"); - - strictEqual(example.value["friends"].kind, "array"); - const friend = example.value["friends"].value[0]; + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + const bodyValue = response.bodyValue; + ok(bodyValue); + strictEqual(bodyValue.kind, "model"); + strictEqual(bodyValue.type.kind, "model"); + strictEqual(bodyValue.type.name, "SawShark"); + strictEqual(Object.keys(bodyValue.value).length, 6); + strictEqual(bodyValue.value["kind"].value, "shark"); + strictEqual(bodyValue.value["kind"].kind, "string"); + strictEqual(bodyValue.value["kind"].type.kind, "constant"); + strictEqual(bodyValue.value["sharktype"].value, "saw"); + strictEqual(bodyValue.value["sharktype"].kind, "string"); + strictEqual(bodyValue.value["sharktype"].type.kind, "constant"); + + strictEqual(bodyValue.value["friends"].kind, "array"); + const friend = bodyValue.value["friends"].value[0]; ok(friend); strictEqual(friend.type.kind, "model"); strictEqual(friend.type.name, "GoblinShark"); @@ -774,8 +798,8 @@ describe("typespec-client-generator-core: example types", () => { strictEqual(friend.value["sharktype"].kind, "string"); strictEqual(friend.value["sharktype"].type.kind, "constant"); - strictEqual(example.value["hate"].kind, "dict"); - const hate = example.value["hate"].value["most"]; + strictEqual(bodyValue.value["hate"].kind, "dict"); + const hate = bodyValue.value["hate"].value["most"]; ok(hate); strictEqual(hate.type.kind, "model"); strictEqual(hate.type.name, "Salmon"); @@ -784,20 +808,20 @@ describe("typespec-client-generator-core: example types", () => { strictEqual(hate.value["kind"].kind, "string"); strictEqual(hate.value["kind"].type.kind, "constant"); - strictEqual(example.value["age"].value, 2); - strictEqual(example.value["age"].kind, "number"); - strictEqual(example.value["age"].type.kind, "int32"); - - strictEqual(example.value["prop"].kind, "array"); - strictEqual(example.value["prop"].value[0].value, 1); - strictEqual(example.value["prop"].value[0].kind, "number"); - strictEqual(example.value["prop"].value[0].type.kind, "int32"); - strictEqual(example.value["prop"].value[1].value, 2); - strictEqual(example.value["prop"].value[1].kind, "number"); - strictEqual(example.value["prop"].value[1].type.kind, "int32"); - strictEqual(example.value["prop"].value[2].value, 3); - strictEqual(example.value["prop"].value[2].kind, "number"); - strictEqual(example.value["prop"].value[2].type.kind, "int32"); + strictEqual(bodyValue.value["age"].value, 2); + strictEqual(bodyValue.value["age"].kind, "number"); + strictEqual(bodyValue.value["age"].type.kind, "int32"); + + strictEqual(bodyValue.value["prop"].kind, "array"); + strictEqual(bodyValue.value["prop"].value[0].value, 1); + strictEqual(bodyValue.value["prop"].value[0].kind, "number"); + strictEqual(bodyValue.value["prop"].value[0].type.kind, "int32"); + strictEqual(bodyValue.value["prop"].value[1].value, 2); + strictEqual(bodyValue.value["prop"].value[1].kind, "number"); + strictEqual(bodyValue.value["prop"].value[1].type.kind, "int32"); + strictEqual(bodyValue.value["prop"].value[2].value, 3); + strictEqual(bodyValue.value["prop"].value[2].kind, "number"); + strictEqual(bodyValue.value["prop"].value[2].type.kind, "int32"); expectDiagnostics(runner.context.diagnostics, []); }); @@ -840,7 +864,9 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - strictEqual(operation.examples[0].responses.get(200)?.bodyValue, undefined); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + strictEqual(response.bodyValue, undefined); expectDiagnostics(runner.context.diagnostics, { code: "@azure-tools/typespec-client-generator-core/example-value-no-mapping", message: `Value in example file 'getModelDiscriminatorDiagnostic.json' does not follow its definition:\n{"kind":"shark","sharktype":"test","age":2}`, @@ -871,27 +897,29 @@ describe("typespec-client-generator-core: example types", () => { ).operation; ok(operation); strictEqual(operation.examples?.length, 1); - const example = operation.examples[0].responses.get(200)?.bodyValue; - ok(example); - strictEqual(example.kind, "model"); - strictEqual(example.type.kind, "model"); - strictEqual(example.type.name, "Test"); - strictEqual(Object.keys(example.value).length, 2); - strictEqual(example.value["a"].value, "a"); - strictEqual(example.value["a"].kind, "string"); - strictEqual(example.value["a"].type.kind, "string"); - strictEqual(example.value["b"].value, 2); - strictEqual(example.value["b"].kind, "number"); - strictEqual(example.value["b"].type.kind, "int32"); - - ok(example.additionalPropertiesValue); - strictEqual(Object.keys(example.additionalPropertiesValue).length, 2); - strictEqual(example.additionalPropertiesValue["c"].value, true); - strictEqual(example.additionalPropertiesValue["c"].kind, "unknown"); - strictEqual(example.additionalPropertiesValue["c"].type.kind, "unknown"); - deepStrictEqual(example.additionalPropertiesValue["d"].value, [1, 2, 3]); - strictEqual(example.additionalPropertiesValue["d"].kind, "unknown"); - strictEqual(example.additionalPropertiesValue["d"].type.kind, "unknown"); + const response = operation.examples[0].responses.find((x) => x.statusCode === 200); + ok(response); + const bodyValue = response.bodyValue; + ok(bodyValue); + strictEqual(bodyValue.kind, "model"); + strictEqual(bodyValue.type.kind, "model"); + strictEqual(bodyValue.type.name, "Test"); + strictEqual(Object.keys(bodyValue.value).length, 2); + strictEqual(bodyValue.value["a"].value, "a"); + strictEqual(bodyValue.value["a"].kind, "string"); + strictEqual(bodyValue.value["a"].type.kind, "string"); + strictEqual(bodyValue.value["b"].value, 2); + strictEqual(bodyValue.value["b"].kind, "number"); + strictEqual(bodyValue.value["b"].type.kind, "int32"); + + ok(bodyValue.additionalPropertiesValue); + strictEqual(Object.keys(bodyValue.additionalPropertiesValue).length, 2); + strictEqual(bodyValue.additionalPropertiesValue["c"].value, true); + strictEqual(bodyValue.additionalPropertiesValue["c"].kind, "unknown"); + strictEqual(bodyValue.additionalPropertiesValue["c"].type.kind, "unknown"); + deepStrictEqual(bodyValue.additionalPropertiesValue["d"].value, [1, 2, 3]); + strictEqual(bodyValue.additionalPropertiesValue["d"].kind, "unknown"); + strictEqual(bodyValue.additionalPropertiesValue["d"].type.kind, "unknown"); expectDiagnostics(runner.context.diagnostics, []); }); diff --git a/packages/typespec-client-generator-core/test/examples/http-operation-examples.test.ts b/packages/typespec-client-generator-core/test/examples/http-operation-examples.test.ts index 21d3c84439..f4f1806629 100644 --- a/packages/typespec-client-generator-core/test/examples/http-operation-examples.test.ts +++ b/packages/typespec-client-generator-core/test/examples/http-operation-examples.test.ts @@ -204,23 +204,32 @@ describe("typespec-client-generator-core: http operation examples", () => { strictEqual(operation.examples?.length, 1); strictEqual(operation.examples[0].kind, "http"); - const okResponse = operation.examples[0].responses.get(200); + const okResponse = operation.examples[0].responses.find((x) => x.statusCode === 200); ok(okResponse); - deepStrictEqual(okResponse.response, operation.responses.get(200)); + deepStrictEqual( + okResponse.response, + operation.responses.find((x) => x.statusCodes === 200) + ); ok(okResponse.bodyValue); strictEqual(okResponse.bodyValue.kind, "string"); strictEqual(okResponse.bodyValue.value, "test"); strictEqual(okResponse.bodyValue.type.kind, "string"); - const createdResponse = operation.examples[0].responses.get(201); + const createdResponse = operation.examples[0].responses.find((x) => x.statusCode === 201); ok(createdResponse); - deepStrictEqual(createdResponse.response, operation.responses.get(201)); + deepStrictEqual( + createdResponse.response, + operation.responses.find((x) => x.statusCodes === 201) + ); strictEqual(createdResponse.bodyValue, undefined); strictEqual(createdResponse.headers.length, 1); - deepStrictEqual(createdResponse.headers[0].header, operation.responses.get(201)?.headers[0]); + deepStrictEqual( + createdResponse.headers[0].header, + operation.responses.find((x) => x.statusCodes === 201)?.headers[0] + ); strictEqual(createdResponse.headers[0].value.value, "test"); strictEqual(createdResponse.headers[0].value.kind, "string"); strictEqual(createdResponse.headers[0].value.type.kind, "string"); @@ -257,10 +266,13 @@ describe("typespec-client-generator-core: http operation examples", () => { strictEqual(operation.examples?.length, 1); strictEqual(operation.examples[0].kind, "http"); - strictEqual(operation.examples[0].responses.size, 1); - const createdResponse = operation.examples[0].responses.get(201); + strictEqual(operation.examples[0].responses.length, 1); + const createdResponse = operation.examples[0].responses.find((x) => x.statusCode === 201); ok(createdResponse); - deepStrictEqual(createdResponse.response, operation.responses.get(201)); + deepStrictEqual( + createdResponse.response, + operation.responses.find((x) => x.statusCodes === 201) + ); strictEqual(createdResponse.bodyValue, undefined); strictEqual(createdResponse.headers.length, 0); diff --git a/packages/typespec-client-generator-core/test/package.test.ts b/packages/typespec-client-generator-core/test/package.test.ts index a8398df886..447ee024c6 100644 --- a/packages/typespec-client-generator-core/test/package.test.ts +++ b/packages/typespec-client-generator-core/test/package.test.ts @@ -1023,15 +1023,15 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.models.length, 1); strictEqual(method.name, "delete"); const serviceResponses = method.operation.responses; - strictEqual(serviceResponses.size, 1); + strictEqual(serviceResponses.length, 1); - const voidResponse = serviceResponses.get(204); + const voidResponse = serviceResponses.find((x) => x.statusCodes === 204); ok(voidResponse); strictEqual(voidResponse.kind, "http"); strictEqual(voidResponse.type, undefined); strictEqual(voidResponse.headers.length, 0); - const errorResponse = method.operation.exceptions.get("*"); + const errorResponse = method.operation.exceptions.find((x) => x.statusCodes === "*"); ok(errorResponse); strictEqual(errorResponse.kind, "http"); ok(errorResponse.type); @@ -1058,15 +1058,15 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.models.length, 1); strictEqual(method.name, "delete"); const serviceResponses = method.operation.responses; - strictEqual(serviceResponses.size, 1); + strictEqual(serviceResponses.length, 1); - const voidResponse = serviceResponses.get(204); + const voidResponse = serviceResponses.find((x) => x.statusCodes === 204); ok(voidResponse); strictEqual(voidResponse.kind, "http"); strictEqual(voidResponse.type, undefined); strictEqual(voidResponse.headers.length, 0); - const errorResponse = method.operation.exceptions.get(403); + const errorResponse = method.operation.exceptions.find((x) => x.statusCodes === 403); ok(errorResponse); strictEqual(errorResponse.kind, "http"); ok(errorResponse.type); @@ -1101,9 +1101,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.models.length, 3); strictEqual(method.name, "create"); const serviceResponses = method.operation.responses; - strictEqual(serviceResponses.size, 1); + strictEqual(serviceResponses.length, 1); - const createResponse = serviceResponses.get(200); + const createResponse = serviceResponses.find((x) => x.statusCodes === 200); ok(createResponse); strictEqual(createResponse.kind, "http"); strictEqual( @@ -1112,7 +1112,7 @@ describe("typespec-client-generator-core: package", () => { ); strictEqual(createResponse.headers.length, 0); - const errorResponse = method.operation.exceptions.get("*"); + const errorResponse = method.operation.exceptions.find((x) => x.statusCodes === "*"); ok(errorResponse); strictEqual(errorResponse.kind, "http"); ok(errorResponse.type); @@ -1144,11 +1144,11 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.models.length, 1); strictEqual(method.name, "operation"); const serviceResponses = method.operation.responses; - strictEqual(serviceResponses.size, 1); + strictEqual(serviceResponses.length, 1); strictEqual(method.parameters.length, 1); - const createResponse = serviceResponses.get(200); + const createResponse = serviceResponses.find((x) => x.statusCodes === 200); ok(createResponse); strictEqual(createResponse.kind, "http"); strictEqual( @@ -1184,7 +1184,7 @@ describe("typespec-client-generator-core: package", () => { const method = getServiceMethodOfClient(sdkPackage); const serviceResponses = method.operation.responses; - const createResponse = serviceResponses.get(200); + const createResponse = serviceResponses.find((x) => x.statusCodes === 200); ok(createResponse); strictEqual(createResponse.headers[0].type.kind, "nullable"); strictEqual(createResponse.type?.kind, "nullable"); @@ -1205,10 +1205,10 @@ describe("typespec-client-generator-core: package", () => { const method = getServiceMethodOfClient(sdkPackage); const serviceResponses = method.operation.responses; - const okResponse = serviceResponses.get(200); + const okResponse = serviceResponses.find((x) => x.statusCodes === 200); ok(okResponse); - const noContentResponse = serviceResponses.get(204); + const noContentResponse = serviceResponses.find((x) => x.statusCodes === 204); ok(noContentResponse); strictEqual(noContentResponse.type, undefined); strictEqual(method.response.type?.kind, "nullable"); @@ -1230,9 +1230,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(method.name, "delete"); strictEqual(method.response.type, undefined); const serviceResponses = method.operation.responses; - strictEqual(serviceResponses.size, 1); + strictEqual(serviceResponses.length, 1); - const voidResponse = serviceResponses.get(204); + const voidResponse = serviceResponses.find((x) => x.statusCodes === 204); ok(voidResponse); strictEqual(voidResponse.kind, "http"); strictEqual(voidResponse.type, undefined); @@ -1946,14 +1946,14 @@ describe("typespec-client-generator-core: package", () => { strictEqual(serviceOperation.bodyParam.name, "resource"); strictEqual(serviceOperation.bodyParam.type, widgetModel); - strictEqual(serviceOperation.responses.size, 2); + strictEqual(serviceOperation.responses.length, 2); const responseHeaders = [ "Repeatability-Result", "ETag", "x-ms-client-request-id", "Operation-Location", ]; - const response200 = serviceOperation.responses.get(200); + const response200 = serviceOperation.responses.find((x) => x.statusCodes === 200); ok(response200); deepStrictEqual( response200.headers.map((x) => x.serializedName), @@ -1961,7 +1961,7 @@ describe("typespec-client-generator-core: package", () => { ); strictEqual(response200.type, widgetModel); - const response201 = serviceOperation.responses.get(201); + const response201 = serviceOperation.responses.find((x) => x.statusCodes === 201); ok(response201); deepStrictEqual( response201.headers.map((x) => x.serializedName), @@ -1969,7 +1969,7 @@ describe("typespec-client-generator-core: package", () => { ); strictEqual(response201.type, widgetModel); - const exception = serviceOperation.exceptions.get("*"); + const exception = serviceOperation.exceptions.find((x) => x.statusCodes === "*"); ok(exception); strictEqual(exception.kind, "http"); ok(exception.type); @@ -2077,8 +2077,8 @@ describe("typespec-client-generator-core: package", () => { strictEqual(accept.kind, "header"); strictEqual(accept.correspondingMethodParams[0], listManufacturers.parameters[1]); - strictEqual(operation.responses.size, 1); - const response200 = operation.responses.get(200); + strictEqual(operation.responses.length, 1); + const response200 = operation.responses.find((x) => x.statusCodes === 200); ok(response200); strictEqual(response200.kind, "http"); const pagingModel = response200.type; diff --git a/packages/typespec-client-generator-core/test/packages/parameters.test.ts b/packages/typespec-client-generator-core/test/packages/parameters.test.ts index 860e0bd45c..1c5d049a7c 100644 --- a/packages/typespec-client-generator-core/test/packages/parameters.test.ts +++ b/packages/typespec-client-generator-core/test/packages/parameters.test.ts @@ -42,7 +42,10 @@ describe("typespec-client-generator-core: parameters", () => { const serviceOperation = method.operation; strictEqual(serviceOperation.bodyParam, undefined); - strictEqual(serviceOperation.exceptions.get("*"), undefined); + strictEqual( + serviceOperation.exceptions.find((x) => x.statusCodes === "*"), + undefined + ); strictEqual(serviceOperation.parameters.length, 1); const pathParam = serviceOperation.parameters[0]; @@ -147,7 +150,10 @@ describe("typespec-client-generator-core: parameters", () => { const serviceOperation = method.operation; strictEqual(serviceOperation.bodyParam, undefined); - strictEqual(serviceOperation.exceptions.get("*"), undefined); + strictEqual( + serviceOperation.exceptions.find((x) => x.statusCodes === "*"), + undefined + ); strictEqual(serviceOperation.parameters.length, 1); const headerParam = serviceOperation.parameters[0]; @@ -223,7 +229,10 @@ describe("typespec-client-generator-core: parameters", () => { const serviceOperation = method.operation; strictEqual(serviceOperation.bodyParam, undefined); - strictEqual(serviceOperation.exceptions.get("*"), undefined); + strictEqual( + serviceOperation.exceptions.find((x) => x.statusCodes === "*"), + undefined + ); strictEqual(serviceOperation.parameters.length, 1); const queryParam = serviceOperation.parameters[0]; @@ -665,8 +674,8 @@ describe("typespec-client-generator-core: parameters", () => { strictEqual(serviceContentTypeParam.type.value, "application/json"); strictEqual(serviceContentTypeParam.type.valueType.kind, "string"); - strictEqual(serviceOperation.responses.size, 1); - const response = serviceOperation.responses.get(200); + strictEqual(serviceOperation.responses.length, 1); + const response = serviceOperation.responses.find((x) => x.statusCodes === 200); ok(response); strictEqual(response.kind, "http"); strictEqual(response.type, sdkPackage.models[0]); @@ -705,8 +714,8 @@ describe("typespec-client-generator-core: parameters", () => { strictEqual(serviceContentTypeParam.type.value, "image/png"); strictEqual(serviceContentTypeParam.type.valueType.kind, "string"); - strictEqual(serviceOperation.responses.size, 1); - const response = serviceOperation.responses.get(200); + strictEqual(serviceOperation.responses.length, 1); + const response = serviceOperation.responses.find((x) => x.statusCodes === 200); ok(response); strictEqual(response.kind, "http"); strictEqual(sdkPackage.models.length, 0); @@ -779,8 +788,10 @@ describe("typespec-client-generator-core: parameters", () => { strictEqual(method.parameters.length, 0); strictEqual(method.response.type, undefined); strictEqual(method.operation.parameters.length, 0); - strictEqual(method.operation.responses.get(200)?.headers.length, 0); - strictEqual(method.operation.responses.get(200)?.type, undefined); + const response = method.operation.responses.find((x) => x.statusCodes === 200); + ok(response); + strictEqual(response.headers.length, 0); + strictEqual(response.type, undefined); }); describe("uri template related", () => { diff --git a/packages/typespec-client-generator-core/test/packages/spread.test.ts b/packages/typespec-client-generator-core/test/packages/spread.test.ts index effb96b32f..fd5e57dbc9 100644 --- a/packages/typespec-client-generator-core/test/packages/spread.test.ts +++ b/packages/typespec-client-generator-core/test/packages/spread.test.ts @@ -170,13 +170,13 @@ describe("typespec-client-generator-core: spread", () => { ok(opParams.find((x) => x.kind === "path" && x.serializedName === "checkupId")); ok(opParams.find((x) => x.kind === "header" && x.serializedName === "Content-Type")); ok(opParams.find((x) => x.kind === "header" && x.serializedName === "Accept")); - strictEqual(createOrUpdate.operation.responses.size, 2); - const response200 = createOrUpdate.operation.responses.get(200); + strictEqual(createOrUpdate.operation.responses.length, 2); + const response200 = createOrUpdate.operation.responses.find((x) => x.statusCodes === 200); ok(response200); ok(response200.type); strictEqual(response200.type.kind, "model"); strictEqual(response200.type.name, "Checkup"); - const response201 = createOrUpdate.operation.responses.get(201); + const response201 = createOrUpdate.operation.responses.find((x) => x.statusCodes === 201); ok(response201); ok(response201.type); deepStrictEqual(response200.type, response201?.type); @@ -287,8 +287,8 @@ describe("typespec-client-generator-core: spread", () => { createOrReplace.operation.bodyParam.correspondingMethodParams[1], createOrReplace.parameters[2] ); - strictEqual(createOrReplace.operation.responses.size, 1); - const response200 = createOrReplace.operation.responses.get(200); + strictEqual(createOrReplace.operation.responses.length, 1); + const response200 = createOrReplace.operation.responses.find((x) => x.statusCodes === 200); ok(response200); ok(response200.type); strictEqual(response200.type.kind, "model"); From 5f4af474c0118636bedd552da9c17c148e0dd6af Mon Sep 17 00:00:00 2001 From: Arcturus Zhang Date: Sat, 14 Sep 2024 11:31:11 +0800 Subject: [PATCH 2/4] updates changelog --- .../change-response-to-be-array-2024-8-14-11-27-13.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .chronus/changes/change-response-to-be-array-2024-8-14-11-27-13.md diff --git a/.chronus/changes/change-response-to-be-array-2024-8-14-11-27-13.md b/.chronus/changes/change-response-to-be-array-2024-8-14-11-27-13.md new file mode 100644 index 0000000000..2b15deb6c8 --- /dev/null +++ b/.chronus/changes/change-response-to-be-array-2024-8-14-11-27-13.md @@ -0,0 +1,9 @@ +--- +changeKind: breaking +packages: + - "@azure-tools/typespec-client-generator-core" +--- + +1. The type of `responses` and `exceptions` in `SdkHttpOperation` changed from `Map` to array. +2. The type of `responses` in `SdkHttpOperationExample` changed from `Map` to array. +3. `SdkHttpResponse` adds a new property `statusCodes` to store its corresponding status code or status code range. From 6d760b20eff1979bad7c0c472266ebcece0c034b Mon Sep 17 00:00:00 2001 From: Arcturus Zhang Date: Sat, 14 Sep 2024 12:15:57 +0800 Subject: [PATCH 3/4] update references --- docs/howtos/Client Generation/07tcgcTypes.mdx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/howtos/Client Generation/07tcgcTypes.mdx b/docs/howtos/Client Generation/07tcgcTypes.mdx index 162558a521..2732b98dd6 100644 --- a/docs/howtos/Client Generation/07tcgcTypes.mdx +++ b/docs/howtos/Client Generation/07tcgcTypes.mdx @@ -911,8 +911,8 @@ export interface SdkHttpOperation { bodyParam: SdkBodyParameter; // mapping of status codes to SdkHttpResponse for valid responses // HttpStatusCodeRange can represent either a single status code or a range. - responses: Map; - exceptions: Map; + responses: SdkHttpResponse[]; + exceptions: SdkHttpResponse[]; examples?: SdkHttpOperationExample[]; } ``` @@ -1277,6 +1277,7 @@ interface HttpStatusCodeRange { export interface SdkHttpResponse { kind: "http"; + statusCodes: number | HttpStatusCodeRange | "*"; headers: SdkServiceResponseHeader[]; apiVersions: string[]; type?: SdkType; @@ -1518,7 +1519,7 @@ interface SdkExampleBase { export interface SdkHttpOperationExample extends SdkExampleBase { kind: "http"; parameters: SdkHttpParameterExample[]; - responses: Map; + responses: SdkHttpResponseExample[]; } export interface SdkHttpParameterExample { @@ -1528,6 +1529,7 @@ export interface SdkHttpParameterExample { export interface SdkHttpResponseExample { response: SdkHttpResponse; + statusCode: number; headers: SdkHttpResponseHeaderExample[]; bodyValue?: SdkTypeExample; } From fa2af2b4751929344d8fa1592988c907c23daff2 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Thu, 19 Sep 2024 10:50:04 +0800 Subject: [PATCH 4/4] update the changelog to include how to migrate --- ...e-response-to-be-array-2024-8-14-11-27-13.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.chronus/changes/change-response-to-be-array-2024-8-14-11-27-13.md b/.chronus/changes/change-response-to-be-array-2024-8-14-11-27-13.md index 2b15deb6c8..614be7d3d5 100644 --- a/.chronus/changes/change-response-to-be-array-2024-8-14-11-27-13.md +++ b/.chronus/changes/change-response-to-be-array-2024-8-14-11-27-13.md @@ -4,6 +4,19 @@ packages: - "@azure-tools/typespec-client-generator-core" --- -1. The type of `responses` and `exceptions` in `SdkHttpOperation` changed from `Map` to array. -2. The type of `responses` in `SdkHttpOperationExample` changed from `Map` to array. +1. The type of `responses` and `exceptions` in `SdkHttpOperation` changed from `Map` to `SdkHttpResponse[]`. +2. The type of `responses` in `SdkHttpOperationExample` changed from `Map` to `SdkHttpResponseExampleValue[]`. 3. `SdkHttpResponse` adds a new property `statusCodes` to store its corresponding status code or status code range. + +Migration hints: +The type changed from map to array, and the key of the map is moved as a new property of the value type. For example, for code like this: +``` +for (const [statusCodes, response] of operation.responses) +``` +you could do the same in this way: +``` +for (const response of operation.responses) +{ + const statusCodes = response.statusCodes; +} +```