diff --git a/.chronus/changes/copilot-fix-xml-test-case-error-2026-2-11-20-7-16.md b/.chronus/changes/copilot-fix-xml-test-case-error-2026-2-11-20-7-16.md new file mode 100644 index 00000000000..37a44acbc51 --- /dev/null +++ b/.chronus/changes/copilot-fix-xml-test-case-error-2026-2-11-20-7-16.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/http-specs" +--- + +Accept both `2022-08-26T18:38:00.000Z` and `2022-08-26T18:38:00Z` as valid RFC3339 UTC datetime forms in the `ModelWithDatetime` XML scenario. \ No newline at end of file diff --git a/.chronus/changes/copilot-fix-xml-test-case-error-2026-2-11-20-8-54.md b/.chronus/changes/copilot-fix-xml-test-case-error-2026-2-11-20-8-54.md new file mode 100644 index 00000000000..4446f699c26 --- /dev/null +++ b/.chronus/changes/copilot-fix-xml-test-case-error-2026-2-11-20-8-54.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/spec-api" +--- + +Remove prettier used for ValidationError message, in validateXmlBodyEquals. \ No newline at end of file diff --git a/packages/http-specs/specs/payload/xml/mockapi.ts b/packages/http-specs/specs/payload/xml/mockapi.ts index 1560c5e84ba..de2d3f85834 100644 --- a/packages/http-specs/specs/payload/xml/mockapi.ts +++ b/packages/http-specs/specs/payload/xml/mockapi.ts @@ -136,6 +136,16 @@ export const modelWithDatetime = ` `; +// Some clients serialize UTC datetimes without trailing zero milliseconds. Both +// "2022-08-26T18:38:00.000Z" and "2022-08-26T18:38:00Z" are valid RFC3339 representations +// of the same instant; accept either form. +const modelWithDatetimeNoMs = ` + + 2022-08-26T18:38:00Z + Fri, 26 Aug 2022 14:38:00 GMT + +`; + function createServerTests(uri: string, data?: any) { return { get: passOnSuccess({ @@ -251,12 +261,44 @@ const Payload_Xml_ModelWithEnum = createServerTests("/payload/xml/modelWithEnum" Scenarios.Payload_Xml_ModelWithEnumValue_get = Payload_Xml_ModelWithEnum.get; Scenarios.Payload_Xml_ModelWithEnumValue_put = Payload_Xml_ModelWithEnum.put; -const Payload_Xml_ModelWithDatetime = createServerTests( - "/payload/xml/modelWithDatetime", - modelWithDatetime, -); -Scenarios.Payload_Xml_ModelWithDatetimeValue_get = Payload_Xml_ModelWithDatetime.get; -Scenarios.Payload_Xml_ModelWithDatetimeValue_put = Payload_Xml_ModelWithDatetime.put; +Scenarios.Payload_Xml_ModelWithDatetimeValue_get = passOnSuccess({ + uri: "/payload/xml/modelWithDatetime", + method: "get", + request: {}, + response: { + status: 200, + body: xml(modelWithDatetime), + }, + kind: "MockApiDefinition", +}); + +Scenarios.Payload_Xml_ModelWithDatetimeValue_put = passOnSuccess({ + uri: "/payload/xml/modelWithDatetime", + method: "put", + request: { + body: xml(modelWithDatetime), + }, + handler: (req: MockRequest) => { + req.expect.containsHeader("content-type", "application/xml"); + // Accept both "2022-08-26T18:38:00.000Z" and "2022-08-26T18:38:00Z" as equivalent UTC datetimes. + let firstError: unknown; + try { + req.expect.xmlBodyEquals(modelWithDatetime); + } catch (e) { + firstError = e; + } + if (firstError !== undefined) { + req.expect.xmlBodyEquals(modelWithDatetimeNoMs); + } + return { + status: 204, + }; + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", +}); export const xmlError = ` diff --git a/packages/spec-api/src/request-validations.ts b/packages/spec-api/src/request-validations.ts index 223b439ce2a..3dc7f7260ab 100644 --- a/packages/spec-api/src/request-validations.ts +++ b/packages/spec-api/src/request-validations.ts @@ -1,5 +1,4 @@ import deepEqual from "deep-equal"; -import * as prettier from "prettier"; import { parseString } from "xml2js"; import { CollectionFormat, RequestExt } from "./types.js"; import { ValidationError } from "./validation-error.js"; @@ -66,11 +65,7 @@ export const validateXmlBodyEquals = (request: RequestExt, expectedBody: string) }); if (!deepEqual(actualParsedBody, expectedParsedBody, { strict: true })) { - throw new ValidationError( - BODY_NOT_EQUAL_ERROR_MESSAGE, - prettier.format(expectedBody), - prettier.format(request.body), - ); + throw new ValidationError(BODY_NOT_EQUAL_ERROR_MESSAGE, expectedBody, request.rawBody); } };