diff --git a/.chronus/changes/fix-http-specs-e2e-tests-2026-03-09.md b/.chronus/changes/fix-http-specs-e2e-tests-2026-03-09.md new file mode 100644 index 00000000000..d697c19650b --- /dev/null +++ b/.chronus/changes/fix-http-specs-e2e-tests-2026-03-09.md @@ -0,0 +1,8 @@ +--- +changeKind: internal +packages: + - "@typespec/http-specs" + - "@typespec/spector" +--- + +Fix e2e test failures: duration header float scenarios, multipart file upload scenarios, XML pagination content-type mismatch, and response body data mismatch validation diff --git a/packages/http-specs/package.json b/packages/http-specs/package.json index 372bb5d077b..c1a95eaf74c 100644 --- a/packages/http-specs/package.json +++ b/packages/http-specs/package.json @@ -19,7 +19,7 @@ "upload-coverage": "tsp-spector upload-coverage --generatorName @typespec/http-specs --generatorVersion 0.1.0-alpha.4 --containerName coverages --generatorMode standard --storageAccountName typespec", "validate-mock-apis": "tsp-spector validate-mock-apis ./specs", "check-scenario-coverage": "tsp-spector check-coverage ./specs", - "validate-client-server": "concurrently \"tsp-spector server start ./specs\" \"pnpm knock\"; tsp-spector server stop", + "validate-client-server": "concurrently \"tsp-spector server start ./specs\" \"pnpm knock\"; code=$?; tsp-spector server stop; exit $code", "build:smoke": "tsp compile smoke/petstore --warn-as-error --no-emit && tsp compile smoke/todoapp --warn-as-error --no-emit", "client": "pnpm knock", "knock": "tsp-spector knock ./specs", diff --git a/packages/http-specs/specs/encode/duration/mockapi.ts b/packages/http-specs/specs/encode/duration/mockapi.ts index 6a722fff8ff..c74a77d300b 100644 --- a/packages/http-specs/specs/encode/duration/mockapi.ts +++ b/packages/http-specs/specs/encode/duration/mockapi.ts @@ -295,6 +295,11 @@ function createHeaderFloatServerTests(uri: string, value: number) { return passOnSuccess({ uri, method: "get", + request: { + headers: { + duration: String(value), + }, + }, response: { status: 204, }, diff --git a/packages/http-specs/specs/payload/multipart/mockapi.ts b/packages/http-specs/specs/payload/multipart/mockapi.ts index 3ac7dbda70a..ea54b460201 100644 --- a/packages/http-specs/specs/payload/multipart/mockapi.ts +++ b/packages/http-specs/specs/payload/multipart/mockapi.ts @@ -437,9 +437,11 @@ Scenarios.Payload_MultiPart_FormData_File_uploadFileSpecificContentType = passOn uri: "/multipart/form-data/file/specific-content-type", method: "post", request: { - headers: { - "content-type": "multipart/form-data", - }, + body: multipart({ + files: [ + { fieldname: "file", originalname: "image.png", buffer: pngFile, mimetype: "image/png" }, + ], + }), }, response: { status: 204, @@ -460,9 +462,11 @@ Scenarios.Payload_MultiPart_FormData_File_uploadFileRequiredFilename = passOnSuc uri: "/multipart/form-data/file/required-filename", method: "post", request: { - headers: { - "content-type": "multipart/form-data", - }, + body: multipart({ + files: [ + { fieldname: "file", originalname: "image.png", buffer: pngFile, mimetype: "image/png" }, + ], + }), }, response: { status: 204, @@ -483,9 +487,12 @@ Scenarios.Payload_MultiPart_FormData_File_uploadFileArray = passOnSuccess({ uri: "/multipart/form-data/file/file-array", method: "post", request: { - headers: { - "content-type": "multipart/form-data", - }, + body: multipart({ + files: [ + { fieldname: "files", originalname: "image.png", buffer: pngFile, mimetype: "image/png" }, + { fieldname: "files", originalname: "image.png", buffer: pngFile, mimetype: "image/png" }, + ], + }), }, response: { status: 204, diff --git a/packages/http-specs/specs/payload/pageable/mockapi.ts b/packages/http-specs/specs/payload/pageable/mockapi.ts index 3fdbf8c794e..c77b1328a1e 100644 --- a/packages/http-specs/specs/payload/pageable/mockapi.ts +++ b/packages/http-specs/specs/payload/pageable/mockapi.ts @@ -4,6 +4,7 @@ import { json, MockRequest, passOnSuccess, + ResolverConfig, ScenarioMockApi, ValidationError, xml, @@ -553,7 +554,7 @@ Scenarios.Payload_Pageable_XmlPagination_listWithContinuation = passOnSuccess([ status: 200, body: xml(XmlContTokenFirstPage), headers: { - "content-type": "application/xml", + "content-type": "application/xml; charset=utf-8", }, }, handler: (req: MockRequest) => { @@ -590,7 +591,7 @@ Scenarios.Payload_Pageable_XmlPagination_listWithContinuation = passOnSuccess([ status: 200, body: xml(XmlContTokenSecondPage), headers: { - "content-type": "application/xml", + "content-type": "application/xml; charset=utf-8", }, }, handler: (req: MockRequest) => { @@ -659,9 +660,15 @@ Scenarios.Payload_Pageable_XmlPagination_listWithNextLink = passOnSuccess([ request: {}, response: { status: 200, - body: xml(xmlNextLinkFirstPage("PLACEHOLDER_BASE_URL")), + body: { + contentType: "application/xml", + rawContent: { + serialize: (config: ResolverConfig) => + `` + xmlNextLinkFirstPage(config.baseUrl), + }, + }, headers: { - "content-type": "application/xml", + "content-type": "application/xml; charset=utf-8", }, }, handler: (req: MockRequest) => { @@ -683,7 +690,7 @@ Scenarios.Payload_Pageable_XmlPagination_listWithNextLink = passOnSuccess([ status: 200, body: xml(XmlNextLinkSecondPage), headers: { - "content-type": "application/xml", + "content-type": "application/xml; charset=utf-8", }, }, kind: "MockApiDefinition", diff --git a/packages/spector/src/actions/server-test.ts b/packages/spector/src/actions/server-test.ts index 6cd60ddbdf3..aeb1d8f2c3c 100644 --- a/packages/spector/src/actions/server-test.ts +++ b/packages/spector/src/actions/server-test.ts @@ -91,7 +91,7 @@ class ServerTestsGenerator { switch (body.contentType) { case "application/xml": case "text/plain": - if (body.rawContent !== responseData) { + if (raw !== responseData) { throw new ValidationError("Response data mismatch", raw, responseData); } break;