@typespec/http-specs 0.1.0-alpha.9 → 0.1.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/CHANGELOG.md +241 -3
  2. package/README.md +11 -3
  3. package/dist/specs/authentication/noauth/union/mockapi.d.ts +3 -0
  4. package/dist/specs/authentication/noauth/union/mockapi.d.ts.map +1 -0
  5. package/dist/specs/authentication/noauth/union/mockapi.js +25 -0
  6. package/dist/specs/authentication/noauth/union/mockapi.js.map +1 -0
  7. package/dist/specs/documentation/mockapi.d.ts +3 -0
  8. package/dist/specs/documentation/mockapi.d.ts.map +1 -0
  9. package/dist/specs/documentation/mockapi.js +40 -0
  10. package/dist/specs/documentation/mockapi.js.map +1 -0
  11. package/dist/specs/encode/array/mockapi.d.ts +3 -0
  12. package/dist/specs/encode/array/mockapi.d.ts.map +1 -0
  13. package/dist/specs/encode/array/mockapi.js +33 -0
  14. package/dist/specs/encode/array/mockapi.js.map +1 -0
  15. package/dist/specs/encode/bytes/mockapi.js +16 -24
  16. package/dist/specs/encode/bytes/mockapi.js.map +1 -1
  17. package/dist/specs/encode/datetime/mockapi.js +2 -2
  18. package/dist/specs/encode/datetime/mockapi.js.map +1 -1
  19. package/dist/specs/encode/duration/mockapi.d.ts.map +1 -1
  20. package/dist/specs/encode/duration/mockapi.js +110 -3
  21. package/dist/specs/encode/duration/mockapi.js.map +1 -1
  22. package/dist/specs/encode/numeric/mockapi.js +2 -2
  23. package/dist/specs/encode/numeric/mockapi.js.map +1 -1
  24. package/dist/specs/helper.d.ts +2 -2
  25. package/dist/specs/helper.d.ts.map +1 -1
  26. package/dist/specs/parameters/basic/mockapi.d.ts.map +1 -1
  27. package/dist/specs/parameters/basic/mockapi.js +3 -3
  28. package/dist/specs/parameters/basic/mockapi.js.map +1 -1
  29. package/dist/specs/parameters/body-optionality/mockapi.d.ts.map +1 -1
  30. package/dist/specs/parameters/body-optionality/mockapi.js +14 -4
  31. package/dist/specs/parameters/body-optionality/mockapi.js.map +1 -1
  32. package/dist/specs/parameters/collection-format/mockapi.js +4 -15
  33. package/dist/specs/parameters/collection-format/mockapi.js.map +1 -1
  34. package/dist/specs/parameters/path/mockapi.d.ts +3 -0
  35. package/dist/specs/parameters/path/mockapi.d.ts.map +1 -0
  36. package/dist/specs/parameters/path/mockapi.js +29 -0
  37. package/dist/specs/parameters/path/mockapi.js.map +1 -0
  38. package/dist/specs/parameters/query/mockapi.d.ts +3 -0
  39. package/dist/specs/parameters/query/mockapi.d.ts.map +1 -0
  40. package/dist/specs/parameters/query/mockapi.js +14 -0
  41. package/dist/specs/parameters/query/mockapi.js.map +1 -0
  42. package/dist/specs/parameters/spread/mockapi.d.ts.map +1 -1
  43. package/dist/specs/parameters/spread/mockapi.js +19 -19
  44. package/dist/specs/parameters/spread/mockapi.js.map +1 -1
  45. package/dist/specs/payload/json-merge-patch/mockapi.js +4 -4
  46. package/dist/specs/payload/json-merge-patch/mockapi.js.map +1 -1
  47. package/dist/specs/payload/media-type/mockapi.js +2 -2
  48. package/dist/specs/payload/media-type/mockapi.js.map +1 -1
  49. package/dist/specs/payload/multipart/mockapi.d.ts.map +1 -1
  50. package/dist/specs/payload/multipart/mockapi.js +189 -60
  51. package/dist/specs/payload/multipart/mockapi.js.map +1 -1
  52. package/dist/specs/payload/pageable/mockapi.d.ts.map +1 -1
  53. package/dist/specs/payload/pageable/mockapi.js +594 -14
  54. package/dist/specs/payload/pageable/mockapi.js.map +1 -1
  55. package/dist/specs/payload/xml/mockapi.d.ts +3 -0
  56. package/dist/specs/payload/xml/mockapi.d.ts.map +1 -1
  57. package/dist/specs/payload/xml/mockapi.js +35 -5
  58. package/dist/specs/payload/xml/mockapi.js.map +1 -1
  59. package/dist/specs/response/status-code-range/mockapi.d.ts.map +1 -1
  60. package/dist/specs/response/status-code-range/mockapi.js +5 -9
  61. package/dist/specs/response/status-code-range/mockapi.js.map +1 -1
  62. package/dist/specs/routes/mockapi.js +16 -16
  63. package/dist/specs/routes/mockapi.js.map +1 -1
  64. package/dist/specs/serialization/encoded-name/json/mockapi.js +1 -1
  65. package/dist/specs/serialization/encoded-name/json/mockapi.js.map +1 -1
  66. package/dist/specs/server/versions/not-versioned/mockapi.js +1 -1
  67. package/dist/specs/server/versions/not-versioned/mockapi.js.map +1 -1
  68. package/dist/specs/server/versions/versioned/mockapi.js +8 -12
  69. package/dist/specs/server/versions/versioned/mockapi.js.map +1 -1
  70. package/dist/specs/special-words/mockapi.d.ts.map +1 -1
  71. package/dist/specs/special-words/mockapi.js +59 -6
  72. package/dist/specs/special-words/mockapi.js.map +1 -1
  73. package/dist/specs/streaming/jsonl/mockapi.d.ts +3 -0
  74. package/dist/specs/streaming/jsonl/mockapi.d.ts.map +1 -0
  75. package/dist/specs/streaming/jsonl/mockapi.js +30 -0
  76. package/dist/specs/streaming/jsonl/mockapi.js.map +1 -0
  77. package/dist/specs/type/array/mockapi.js +1 -1
  78. package/dist/specs/type/array/mockapi.js.map +1 -1
  79. package/dist/specs/type/dictionary/mockapi.js +1 -1
  80. package/dist/specs/type/dictionary/mockapi.js.map +1 -1
  81. package/dist/specs/type/enum/extensible/mockapi.js +1 -1
  82. package/dist/specs/type/enum/extensible/mockapi.js.map +1 -1
  83. package/dist/specs/type/enum/fixed/mockapi.js +2 -2
  84. package/dist/specs/type/enum/fixed/mockapi.js.map +1 -1
  85. package/dist/specs/type/file/mockapi.d.ts +3 -0
  86. package/dist/specs/type/file/mockapi.d.ts.map +1 -0
  87. package/dist/specs/type/file/mockapi.js +187 -0
  88. package/dist/specs/type/file/mockapi.js.map +1 -0
  89. package/dist/specs/type/model/empty/mockapi.js +2 -2
  90. package/dist/specs/type/model/empty/mockapi.js.map +1 -1
  91. package/dist/specs/type/model/inheritance/enum-discriminator/mockapi.js +1 -1
  92. package/dist/specs/type/model/inheritance/enum-discriminator/mockapi.js.map +1 -1
  93. package/dist/specs/type/model/inheritance/nested-discriminator/mockapi.js +2 -2
  94. package/dist/specs/type/model/inheritance/nested-discriminator/mockapi.js.map +1 -1
  95. package/dist/specs/type/model/inheritance/not-discriminated/mockapi.js +2 -2
  96. package/dist/specs/type/model/inheritance/not-discriminated/mockapi.js.map +1 -1
  97. package/dist/specs/type/model/inheritance/recursive/mockapi.js +1 -1
  98. package/dist/specs/type/model/inheritance/recursive/mockapi.js.map +1 -1
  99. package/dist/specs/type/model/inheritance/single-discriminator/mockapi.js +2 -2
  100. package/dist/specs/type/model/inheritance/single-discriminator/mockapi.js.map +1 -1
  101. package/dist/specs/type/model/usage/mockapi.js +4 -4
  102. package/dist/specs/type/model/usage/mockapi.js.map +1 -1
  103. package/dist/specs/type/model/visibility/mockapi.js +9 -10
  104. package/dist/specs/type/model/visibility/mockapi.js.map +1 -1
  105. package/dist/specs/type/property/additional-properties/mockapi.js +9 -6
  106. package/dist/specs/type/property/additional-properties/mockapi.js.map +1 -1
  107. package/dist/specs/type/property/nullable/mockapi.js +2 -6
  108. package/dist/specs/type/property/nullable/mockapi.js.map +1 -1
  109. package/dist/specs/type/property/optionality/mockapi.js +1 -1
  110. package/dist/specs/type/property/optionality/mockapi.js.map +1 -1
  111. package/dist/specs/type/property/value-types/mockapi.js +3 -3
  112. package/dist/specs/type/property/value-types/mockapi.js.map +1 -1
  113. package/dist/specs/type/scalar/mockapi.js +9 -9
  114. package/dist/specs/type/scalar/mockapi.js.map +1 -1
  115. package/dist/specs/type/union/discriminated/mockapi.d.ts +3 -0
  116. package/dist/specs/type/union/discriminated/mockapi.d.ts.map +1 -0
  117. package/dist/specs/type/union/discriminated/mockapi.js +212 -0
  118. package/dist/specs/type/union/discriminated/mockapi.js.map +1 -0
  119. package/dist/specs/type/union/mockapi.js +2 -2
  120. package/dist/specs/type/union/mockapi.js.map +1 -1
  121. package/dist/specs/versioning/added/mockapi.js +6 -6
  122. package/dist/specs/versioning/added/mockapi.js.map +1 -1
  123. package/dist/specs/versioning/madeOptional/mockapi.js +2 -2
  124. package/dist/specs/versioning/madeOptional/mockapi.js.map +1 -1
  125. package/dist/specs/versioning/removed/mockapi.js +11 -11
  126. package/dist/specs/versioning/removed/mockapi.js.map +1 -1
  127. package/dist/specs/versioning/renamedFrom/mockapi.js +5 -5
  128. package/dist/specs/versioning/renamedFrom/mockapi.js.map +1 -1
  129. package/dist/specs/versioning/returnTypeChangedFrom/mockapi.js +1 -1
  130. package/dist/specs/versioning/returnTypeChangedFrom/mockapi.js.map +1 -1
  131. package/dist/specs/versioning/typeChangedFrom/mockapi.js +3 -3
  132. package/dist/specs/versioning/typeChangedFrom/mockapi.js.map +1 -1
  133. package/manifest.json +11200 -0
  134. package/package.json +30 -19
  135. package/smoke/petstore/main.tsp +96 -0
  136. package/smoke/todoapp/main.tsp +293 -0
  137. package/spec-summary.md +1745 -121
  138. package/specs/authentication/noauth/union/main.tsp +30 -0
  139. package/specs/authentication/noauth/union/mockapi.ts +27 -0
  140. package/specs/documentation/main.tsp +158 -0
  141. package/specs/documentation/mockapi.ts +59 -0
  142. package/specs/encode/array/main.tsp +339 -0
  143. package/specs/encode/array/mockapi.ts +83 -0
  144. package/specs/encode/bytes/main.tsp +29 -20
  145. package/specs/encode/bytes/mockapi.ts +13 -31
  146. package/specs/encode/datetime/main.tsp +2 -7
  147. package/specs/encode/datetime/mockapi.ts +2 -2
  148. package/specs/encode/duration/main.tsp +420 -7
  149. package/specs/encode/duration/mockapi.ts +216 -2
  150. package/specs/encode/numeric/mockapi.ts +2 -2
  151. package/specs/parameters/basic/mockapi.ts +3 -3
  152. package/specs/parameters/body-optionality/main.tsp +2 -0
  153. package/specs/parameters/body-optionality/mockapi.ts +24 -4
  154. package/specs/parameters/collection-format/main.tsp +5 -25
  155. package/specs/parameters/collection-format/mockapi.ts +4 -16
  156. package/specs/parameters/path/main.tsp +48 -0
  157. package/specs/parameters/path/mockapi.ts +34 -0
  158. package/specs/parameters/query/main.tsp +22 -0
  159. package/specs/parameters/query/mockapi.ts +15 -0
  160. package/specs/parameters/spread/mockapi.ts +19 -19
  161. package/specs/payload/json-merge-patch/main.tsp +2 -2
  162. package/specs/payload/json-merge-patch/mockapi.ts +4 -4
  163. package/specs/payload/media-type/mockapi.ts +2 -2
  164. package/specs/payload/multipart/main.tsp +230 -32
  165. package/specs/payload/multipart/mockapi.ts +200 -59
  166. package/specs/payload/pageable/main.tsp +601 -0
  167. package/specs/payload/pageable/mockapi.ts +656 -14
  168. package/specs/payload/xml/main.tsp +89 -0
  169. package/specs/payload/xml/mockapi.ts +44 -5
  170. package/specs/response/status-code-range/main.tsp +2 -2
  171. package/specs/response/status-code-range/mockapi.ts +5 -9
  172. package/specs/routes/main.tsp +29 -29
  173. package/specs/routes/mockapi.ts +16 -16
  174. package/specs/serialization/encoded-name/json/main.tsp +1 -1
  175. package/specs/serialization/encoded-name/json/mockapi.ts +1 -1
  176. package/specs/server/endpoint/not-defined/main.tsp +1 -3
  177. package/specs/server/path/multiple/main.tsp +3 -5
  178. package/specs/server/versions/not-versioned/mockapi.ts +1 -1
  179. package/specs/server/versions/versioned/main.tsp +1 -1
  180. package/specs/server/versions/versioned/mockapi.ts +6 -12
  181. package/specs/special-headers/conditional-request/main.tsp +1 -1
  182. package/specs/special-headers/repeatability/main.tsp +2 -2
  183. package/specs/special-words/main.tsp +118 -6
  184. package/specs/special-words/mockapi.ts +62 -6
  185. package/specs/streaming/jsonl/main.tsp +33 -0
  186. package/specs/streaming/jsonl/mockapi.ts +32 -0
  187. package/specs/type/array/mockapi.ts +1 -1
  188. package/specs/type/dictionary/mockapi.ts +1 -1
  189. package/specs/type/enum/extensible/main.tsp +18 -2
  190. package/specs/type/enum/extensible/mockapi.ts +1 -1
  191. package/specs/type/enum/fixed/main.tsp +15 -3
  192. package/specs/type/enum/fixed/mockapi.ts +2 -2
  193. package/specs/type/file/main.tsp +109 -0
  194. package/specs/type/file/mockapi.ts +200 -0
  195. package/specs/type/model/empty/mockapi.ts +2 -2
  196. package/specs/type/model/inheritance/enum-discriminator/mockapi.ts +1 -1
  197. package/specs/type/model/inheritance/nested-discriminator/mockapi.ts +2 -2
  198. package/specs/type/model/inheritance/not-discriminated/mockapi.ts +2 -2
  199. package/specs/type/model/inheritance/recursive/mockapi.ts +1 -1
  200. package/specs/type/model/inheritance/single-discriminator/mockapi.ts +2 -2
  201. package/specs/type/model/usage/mockapi.ts +4 -4
  202. package/specs/type/model/visibility/main.tsp +9 -17
  203. package/specs/type/model/visibility/mockapi.ts +9 -10
  204. package/specs/type/property/additional-properties/main.tsp +17 -17
  205. package/specs/type/property/additional-properties/mockapi.ts +10 -10
  206. package/specs/type/property/nullable/mockapi.ts +7 -8
  207. package/specs/type/property/optionality/mockapi.ts +1 -1
  208. package/specs/type/property/value-types/mockapi.ts +3 -3
  209. package/specs/type/scalar/main.tsp +58 -9
  210. package/specs/type/scalar/mockapi.ts +9 -9
  211. package/specs/type/union/discriminated/main.tsp +251 -0
  212. package/specs/type/union/discriminated/mockapi.ts +230 -0
  213. package/specs/type/union/mockapi.ts +2 -2
  214. package/specs/versioning/added/mockapi.ts +6 -6
  215. package/specs/versioning/madeOptional/mockapi.ts +2 -2
  216. package/specs/versioning/removed/main.tsp +5 -5
  217. package/specs/versioning/removed/mockapi.ts +11 -11
  218. package/specs/versioning/renamedFrom/mockapi.ts +5 -5
  219. package/specs/versioning/returnTypeChangedFrom/main.tsp +17 -2
  220. package/specs/versioning/returnTypeChangedFrom/mockapi.ts +1 -1
  221. package/specs/versioning/typeChangedFrom/mockapi.ts +3 -3
  222. package/temp/.tsbuildinfo +1 -1
  223. package/tsconfig.build.json +0 -4
  224. package/tspconfig.yaml +0 -2
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  MockRequest,
3
+ multipart,
3
4
  passOnSuccess,
4
5
  ScenarioMockApi,
5
6
  ValidationError,
@@ -29,7 +30,7 @@ function checkFile(
29
30
  fileName: string | undefined = undefined,
30
31
  mustCheckContentType: boolean = true,
31
32
  ) {
32
- // cadl-ranch depends on multer, which sets the mimetype to "text/plain" if this part has no content-type header
33
+ // server depends on multer, which sets the mimetype to "text/plain" if this part has no content-type header
33
34
  if (mustCheckContentType || file.mimetype !== "text/plain") {
34
35
  req.expect.deepEqual(file.mimetype, contentType);
35
36
  }
@@ -181,29 +182,93 @@ function createMultiBinaryPartsHandler(req: MockRequest) {
181
182
  }
182
183
  }
183
184
 
185
+ function createOptionalPartsHandler(req: MockRequest) {
186
+ const hasId = req.body.id !== undefined;
187
+ const hasProfileImage = req.files instanceof Array && req.files.length > 0;
188
+
189
+ if (hasId && hasProfileImage) {
190
+ checkId(req);
191
+ checkJpgFile(req, req.files[0]);
192
+ return { pass: "id,profileImage", status: 204 } as const;
193
+ } else if (hasId && !hasProfileImage) {
194
+ checkId(req);
195
+ return { pass: "id", status: 204 } as const;
196
+ } else if (!hasId && hasProfileImage) {
197
+ checkJpgFile(req, req.files[0]);
198
+ return { pass: "profileImage", status: 204 } as const;
199
+ } else {
200
+ throw new ValidationError(
201
+ "No id or profileImage found",
202
+ "At least one of id or profileImage is expected",
203
+ req.body,
204
+ );
205
+ }
206
+ }
207
+
184
208
  Scenarios.Payload_MultiPart_FormData_basic = passOnSuccess({
185
209
  uri: "/multipart/form-data/mixed-parts",
186
210
  method: "post",
187
211
  request: {
188
- headers: {
189
- "Content-Type": "multipart/form-data",
190
- },
191
- body: { id: 123 },
192
- files: [files[0]],
212
+ body: multipart({ parts: { id: 123 }, files: [files[0]] }),
213
+ },
214
+ response: { status: 204 },
215
+ handler: (req: MockRequest) => createHandler(req, [checkId, checkProfileImage]),
216
+ kind: "MockApiDefinition",
217
+ });
218
+ Scenarios.Payload_MultiPart_FormData_withWireName = passOnSuccess({
219
+ uri: "/multipart/form-data/mixed-parts-with-wire-name",
220
+ method: "post",
221
+ request: {
222
+ body: multipart({ parts: { id: 123 }, files: [files[0]] }),
193
223
  },
194
224
  response: { status: 204 },
195
225
  handler: (req: MockRequest) => createHandler(req, [checkId, checkProfileImage]),
196
226
  kind: "MockApiDefinition",
197
227
  });
228
+ Scenarios.Payload_MultiPart_FormData_optionalParts = withServiceKeys([
229
+ "id",
230
+ "profileImage",
231
+ "id,profileImage",
232
+ ]).pass([
233
+ {
234
+ uri: "/multipart/form-data/optional-parts",
235
+ method: "post",
236
+ request: {
237
+ body: multipart({ parts: { id: 123 } }),
238
+ },
239
+ response: { status: 204 },
240
+ handler: createOptionalPartsHandler,
241
+ kind: "MockApiDefinition",
242
+ },
243
+ {
244
+ uri: "/multipart/form-data/optional-parts",
245
+ method: "post",
246
+ request: {
247
+ body: multipart({ files: [files[0]] }),
248
+ },
249
+ response: { status: 204 },
250
+ handler: createOptionalPartsHandler,
251
+ kind: "MockApiDefinition",
252
+ },
253
+ {
254
+ uri: "/multipart/form-data/optional-parts",
255
+ method: "post",
256
+ request: {
257
+ body: multipart({ parts: { id: 123 }, files: [files[0]] }),
258
+ },
259
+ response: { status: 204 },
260
+ handler: createOptionalPartsHandler,
261
+ kind: "MockApiDefinition",
262
+ },
263
+ ]);
198
264
  Scenarios.Payload_MultiPart_FormData_fileArrayAndBasic = passOnSuccess({
199
265
  uri: "/multipart/form-data/complex-parts",
200
266
  method: "post",
201
267
  request: {
202
- headers: {
203
- "Content-Type": "multipart/form-data",
204
- },
205
- body: { id: 123, address: { city: "X" } },
206
- files: [files[0], files[1], files[1]],
268
+ body: multipart({
269
+ parts: { id: 123, address: { city: "X" } },
270
+ files: [files[0], files[1], files[1]],
271
+ }),
207
272
  },
208
273
  response: { status: 204 },
209
274
  handler: (req: MockRequest) => createHandler(req, [checkId, checkAddress, checkAllFiles]),
@@ -213,11 +278,7 @@ Scenarios.Payload_MultiPart_FormData_jsonPart = passOnSuccess({
213
278
  uri: "/multipart/form-data/json-part",
214
279
  method: "post",
215
280
  request: {
216
- headers: {
217
- "Content-Type": "multipart/form-data",
218
- },
219
- body: { address: { city: "X" } },
220
- files: [files[0]],
281
+ body: multipart({ parts: { address: { city: "X" } }, files: [files[0]] }),
221
282
  },
222
283
  response: { status: 204 },
223
284
  handler: (req: MockRequest) => createHandler(req, [checkAddress, checkProfileImage]),
@@ -227,11 +288,7 @@ Scenarios.Payload_MultiPart_FormData_binaryArrayParts = passOnSuccess({
227
288
  uri: "/multipart/form-data/binary-array-parts",
228
289
  method: "post",
229
290
  request: {
230
- headers: {
231
- "Content-Type": "multipart/form-data",
232
- },
233
- body: { id: 123 },
234
- files: [files[1], files[1]],
291
+ body: multipart({ parts: { id: 123 }, files: [files[1], files[1]] }),
235
292
  },
236
293
  response: { status: 204 },
237
294
  handler: (req: MockRequest) => createHandler(req, [checkId, checkPictures]),
@@ -245,10 +302,9 @@ Scenarios.Payload_MultiPart_FormData_multiBinaryParts = withServiceKeys([
245
302
  uri: "/multipart/form-data/multi-binary-parts",
246
303
  method: "post",
247
304
  request: {
248
- headers: {
249
- "Content-Type": "multipart/form-data",
250
- },
251
- files: [files[0]],
305
+ body: multipart({
306
+ files: [files[0]],
307
+ }),
252
308
  },
253
309
  response: { status: 204 },
254
310
  handler: createMultiBinaryPartsHandler,
@@ -258,10 +314,9 @@ Scenarios.Payload_MultiPart_FormData_multiBinaryParts = withServiceKeys([
258
314
  uri: "/multipart/form-data/multi-binary-parts",
259
315
  method: "post",
260
316
  request: {
261
- headers: {
262
- "Content-Type": "multipart/form-data",
263
- },
264
- files: [files[0], { ...files[1], fieldname: "picture" }],
317
+ body: multipart({
318
+ files: [files[0], { ...files[1], fieldname: "picture" }],
319
+ }),
265
320
  },
266
321
  response: { status: 204 },
267
322
  handler: createMultiBinaryPartsHandler,
@@ -272,11 +327,10 @@ Scenarios.Payload_MultiPart_FormData_checkFileNameAndContentType = passOnSuccess
272
327
  uri: "/multipart/form-data/check-filename-and-content-type",
273
328
  method: "post",
274
329
  request: {
275
- headers: {
276
- "Content-Type": "multipart/form-data",
277
- },
278
- body: { id: 123 },
279
- files: [{ ...files[0], mimetype: "image/jpg", originalname: "hello.jpg" }],
330
+ body: multipart({
331
+ parts: { id: 123 },
332
+ files: [{ ...files[0], mimetype: "image/jpg", originalname: "hello.jpg" }],
333
+ }),
280
334
  },
281
335
  response: { status: 204 },
282
336
  handler: (req: MockRequest) => createHandler(req, [checkId, checkFileNameAndContentType]),
@@ -286,10 +340,9 @@ Scenarios.Payload_MultiPart_FormData_anonymousModel = passOnSuccess({
286
340
  uri: "/multipart/form-data/anonymous-model",
287
341
  method: "post",
288
342
  request: {
289
- headers: {
290
- "Content-Type": "multipart/form-data",
291
- },
292
- files: [files[0]],
343
+ body: multipart({
344
+ files: [files[0]],
345
+ }),
293
346
  },
294
347
  response: { status: 204 },
295
348
  handler: (req: MockRequest) => createHandler(req, [checkProfileImage]),
@@ -299,10 +352,9 @@ Scenarios.Payload_MultiPart_FormData_HttpParts_ContentType_imageJpegContentType
299
352
  uri: "/multipart/form-data/check-filename-and-specific-content-type-with-httppart",
300
353
  method: "post",
301
354
  request: {
302
- headers: {
303
- "Content-Type": "multipart/form-data",
304
- },
305
- files: [{ ...files[0], mimetype: "image/jpg", originalname: "hello.jpg" }],
355
+ body: multipart({
356
+ files: [{ ...files[0], mimetype: "image/jpg", originalname: "hello.jpg" }],
357
+ }),
306
358
  },
307
359
  response: { status: 204 },
308
360
  handler: (req: MockRequest) => createHandler(req, [checkFileNameAndContentType]),
@@ -312,10 +364,9 @@ Scenarios.Payload_MultiPart_FormData_HttpParts_ContentType_requiredContentType =
312
364
  uri: "/multipart/form-data/check-filename-and-required-content-type-with-httppart",
313
365
  method: "post",
314
366
  request: {
315
- headers: {
316
- "Content-Type": "multipart/form-data",
317
- },
318
- files: [files[0]],
367
+ body: multipart({
368
+ files: [files[0]],
369
+ }),
319
370
  },
320
371
  response: { status: 204 },
321
372
  handler: (req: MockRequest) => createHandler(req, [checkProfileImage]),
@@ -325,10 +376,9 @@ Scenarios.Payload_MultiPart_FormData_HttpParts_ContentType_optionalContentType =
325
376
  uri: "/multipart/form-data/file-with-http-part-optional-content-type",
326
377
  method: "post",
327
378
  request: {
328
- headers: {
329
- "Content-Type": "multipart/form-data",
330
- },
331
- files: [files[0]],
379
+ body: multipart({
380
+ files: [files[0]],
381
+ }),
332
382
  },
333
383
  response: { status: 204 },
334
384
  handler: (req: MockRequest) => createHandler(req, [checkOptionalContentType]),
@@ -338,11 +388,14 @@ Scenarios.Payload_MultiPart_FormData_HttpParts_jsonArrayAndFileArray = passOnSuc
338
388
  uri: "/multipart/form-data/complex-parts-with-httppart",
339
389
  method: "post",
340
390
  request: {
341
- headers: {
342
- "Content-Type": "multipart/form-data",
343
- },
344
- body: { id: 123, address: { city: "X" }, previousAddresses: [{ city: "Y" }, { city: "Z" }] },
345
- files: [files[0], files[1], files[1]],
391
+ body: multipart({
392
+ parts: {
393
+ id: 123,
394
+ address: { city: "X" },
395
+ previousAddresses: [{ city: "Y" }, { city: "Z" }],
396
+ },
397
+ files: [files[0], files[1], files[1]],
398
+ }),
346
399
  },
347
400
  response: { status: 204 },
348
401
  handler: (req: MockRequest) =>
@@ -353,12 +406,100 @@ Scenarios.Payload_MultiPart_FormData_HttpParts_NonString_float = passOnSuccess({
353
406
  uri: "/multipart/form-data/non-string-float",
354
407
  method: "post",
355
408
  request: {
356
- body: { temperature: 0.5 },
357
- headers: {
358
- "Content-Type": "multipart/form-data",
359
- },
409
+ body: multipart({
410
+ parts: { temperature: 0.5 },
411
+ }),
360
412
  },
361
413
  response: { status: 204 },
362
414
  handler: (req: MockRequest) => createHandler(req, [checkFloat]),
363
415
  kind: "MockApiDefinition",
364
416
  });
417
+
418
+ // Helper function to check file in multipart for File type tests
419
+ function checkMultipartFile(
420
+ req: MockRequest,
421
+ file: Record<string, any>,
422
+ expectedContent: Buffer,
423
+ expectedContentType: string,
424
+ fieldName: string = "file",
425
+ expectedFileName?: string,
426
+ ) {
427
+ req.expect.deepEqual(file.fieldname, fieldName);
428
+ req.expect.deepEqual(file.mimetype, expectedContentType);
429
+ req.expect.deepEqual(file.buffer, expectedContent);
430
+ if (expectedFileName) {
431
+ req.expect.deepEqual(file.originalname, expectedFileName);
432
+ }
433
+ }
434
+
435
+ // Multipart File type tests
436
+ Scenarios.Payload_MultiPart_FormData_File_uploadFileSpecificContentType = passOnSuccess({
437
+ uri: "/multipart/form-data/file/specific-content-type",
438
+ method: "post",
439
+ request: {
440
+ headers: {
441
+ "content-type": "multipart/form-data",
442
+ },
443
+ },
444
+ response: {
445
+ status: 204,
446
+ },
447
+ handler(req: MockRequest) {
448
+ if (req.files instanceof Array && req.files.length === 1) {
449
+ const file = req.files[0];
450
+ checkMultipartFile(req, file, pngFile, "image/png", "file", "image.png");
451
+ return { status: 204 };
452
+ } else {
453
+ throw new ValidationError("Expected exactly one file", "1 file", req.files);
454
+ }
455
+ },
456
+ kind: "MockApiDefinition",
457
+ });
458
+
459
+ Scenarios.Payload_MultiPart_FormData_File_uploadFileRequiredFilename = passOnSuccess({
460
+ uri: "/multipart/form-data/file/required-filename",
461
+ method: "post",
462
+ request: {
463
+ headers: {
464
+ "content-type": "multipart/form-data",
465
+ },
466
+ },
467
+ response: {
468
+ status: 204,
469
+ },
470
+ handler(req: MockRequest) {
471
+ if (req.files instanceof Array && req.files.length === 1) {
472
+ const file = req.files[0];
473
+ checkMultipartFile(req, file, pngFile, "image/png", "file", "image.png");
474
+ return { status: 204 };
475
+ } else {
476
+ throw new ValidationError("Expected exactly one file", "1 file", req.files);
477
+ }
478
+ },
479
+ kind: "MockApiDefinition",
480
+ });
481
+
482
+ Scenarios.Payload_MultiPart_FormData_File_uploadFileArray = passOnSuccess({
483
+ uri: "/multipart/form-data/file/file-array",
484
+ method: "post",
485
+ request: {
486
+ headers: {
487
+ "content-type": "multipart/form-data",
488
+ },
489
+ },
490
+ response: {
491
+ status: 204,
492
+ },
493
+ handler(req: MockRequest) {
494
+ if (req.files instanceof Array && req.files.length === 2) {
495
+ for (const file of req.files) {
496
+ req.expect.deepEqual(file.fieldname, "files");
497
+ checkMultipartFile(req, file, pngFile, "image/png", "files");
498
+ }
499
+ return { status: 204 };
500
+ } else {
501
+ throw new ValidationError("Expected exactly two files", "2 files", req.files);
502
+ }
503
+ },
504
+ kind: "MockApiDefinition",
505
+ });