diff --git a/.chronus/changes/add-optional-array-body-spector-2026-6-2.md b/.chronus/changes/add-optional-array-body-spector-2026-6-2.md new file mode 100644 index 00000000000..2dfb7ada7c3 --- /dev/null +++ b/.chronus/changes/add-optional-array-body-spector-2026-6-2.md @@ -0,0 +1,7 @@ +--- +changeKind: internal +packages: + - "@typespec/http-specs" +--- + +Add Spector coverage for omitted optional array request bodies. diff --git a/packages/http-specs/spec-summary.md b/packages/http-specs/spec-summary.md index c623a91cc95..186ab6ea7a9 100644 --- a/packages/http-specs/spec-summary.md +++ b/packages/http-specs/spec-summary.md @@ -5431,6 +5431,13 @@ Expected Array input body: ["hello", null, "world"] ``` +### Type_Array_OptionalValue + +- Endpoint: `put /type/array/optional` + +Expected no request body. +Expected Content-Type header: must NOT be present + ### Type_Array_StringValue_get - Endpoint: `get /type/array/string` diff --git a/packages/http-specs/specs/type/array/main.tsp b/packages/http-specs/specs/type/array/main.tsp index b91b2fe6847..77402b031fe 100644 --- a/packages/http-specs/specs/type/array/main.tsp +++ b/packages/http-specs/specs/type/array/main.tsp @@ -106,3 +106,15 @@ interface NullableModelValue NullableModel[], "[{'property': 'hello'}, null, {'property': 'world'}]" > {} + +@scenario +@doc("Optional array value") +@scenarioDoc(""" + Expected no request body. + Expected Content-Type header: must NOT be present + """) +@route("/optional") +interface OptionalValue { + @put + omit(@body body?: string[]): void; +} diff --git a/packages/http-specs/specs/type/array/mockapi.ts b/packages/http-specs/specs/type/array/mockapi.ts index 7bab93b261b..3a998eb763a 100644 --- a/packages/http-specs/specs/type/array/mockapi.ts +++ b/packages/http-specs/specs/type/array/mockapi.ts @@ -1,4 +1,10 @@ -import { json, passOnSuccess, ScenarioMockApi } from "@typespec/spec-api"; +import { + json, + MockRequest, + passOnSuccess, + ScenarioMockApi, + ValidationError, +} from "@typespec/spec-api"; export const Scenarios: Record = {}; @@ -105,3 +111,25 @@ const Type_Array_Nullable_Model = createServerTests(`/type/array/nullable-model` ]); Scenarios.Type_Array_NullableModelValue_get = Type_Array_Nullable_Model.get; Scenarios.Type_Array_NullableModelValue_put = Type_Array_Nullable_Model.put; + +Scenarios.Type_Array_OptionalValue = passOnSuccess({ + uri: "/type/array/optional/omit", + method: "put", + request: {}, + response: { + status: 204, + }, + handler: (req: MockRequest) => { + req.expect.rawBodyEquals(undefined); + const contentTypeHeader = req.headers["content-type"]; + if (contentTypeHeader !== undefined) { + throw new ValidationError( + "Content-Type header must NOT be present when body is omitted", + undefined, + contentTypeHeader, + ); + } + return { status: 204 }; + }, + kind: "MockApiDefinition", +});