@typespec/http-specs 0.1.0-alpha.3-dev.6 → 0.1.0-alpha.30-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 (206) hide show
  1. package/CHANGELOG.md +238 -0
  2. package/README.md +11 -3
  3. package/dist/specs/documentation/mockapi.d.ts.map +1 -0
  4. package/dist/specs/documentation/mockapi.js +38 -0
  5. package/dist/specs/documentation/mockapi.js.map +1 -0
  6. package/dist/specs/encode/array/mockapi.d.ts +3 -0
  7. package/dist/specs/encode/array/mockapi.d.ts.map +1 -0
  8. package/dist/specs/encode/array/mockapi.js +25 -0
  9. package/dist/specs/encode/array/mockapi.js.map +1 -0
  10. package/dist/specs/encode/bytes/mockapi.js +16 -24
  11. package/dist/specs/encode/bytes/mockapi.js.map +1 -1
  12. package/dist/specs/encode/datetime/mockapi.js +2 -2
  13. package/dist/specs/encode/datetime/mockapi.js.map +1 -1
  14. package/dist/specs/encode/duration/mockapi.js +74 -2
  15. package/dist/specs/encode/duration/mockapi.js.map +1 -1
  16. package/dist/specs/encode/numeric/mockapi.js +2 -2
  17. package/dist/specs/encode/numeric/mockapi.js.map +1 -1
  18. package/dist/specs/helper.d.ts +2 -2
  19. package/dist/specs/helper.d.ts.map +1 -1
  20. package/dist/specs/parameters/basic/mockapi.d.ts.map +1 -1
  21. package/dist/specs/parameters/basic/mockapi.js +3 -3
  22. package/dist/specs/parameters/basic/mockapi.js.map +1 -1
  23. package/dist/specs/parameters/body-optionality/mockapi.d.ts.map +1 -1
  24. package/dist/specs/parameters/body-optionality/mockapi.js +14 -4
  25. package/dist/specs/parameters/body-optionality/mockapi.js.map +1 -1
  26. package/dist/specs/parameters/collection-format/mockapi.js +4 -15
  27. package/dist/specs/parameters/collection-format/mockapi.js.map +1 -1
  28. package/dist/specs/parameters/path/mockapi.d.ts +3 -0
  29. package/dist/specs/parameters/path/mockapi.d.ts.map +1 -0
  30. package/dist/specs/parameters/path/mockapi.js +29 -0
  31. package/dist/specs/parameters/path/mockapi.js.map +1 -0
  32. package/dist/specs/parameters/spread/mockapi.d.ts.map +1 -1
  33. package/dist/specs/parameters/spread/mockapi.js +19 -19
  34. package/dist/specs/parameters/spread/mockapi.js.map +1 -1
  35. package/dist/specs/payload/json-merge-patch/mockapi.js +4 -4
  36. package/dist/specs/payload/json-merge-patch/mockapi.js.map +1 -1
  37. package/dist/specs/payload/media-type/mockapi.js +2 -2
  38. package/dist/specs/payload/media-type/mockapi.js.map +1 -1
  39. package/dist/specs/payload/multipart/mockapi.d.ts.map +1 -1
  40. package/dist/specs/payload/multipart/mockapi.js +42 -60
  41. package/dist/specs/payload/multipart/mockapi.js.map +1 -1
  42. package/dist/specs/payload/pageable/mockapi.d.ts.map +1 -1
  43. package/dist/specs/payload/pageable/mockapi.js +425 -18
  44. package/dist/specs/payload/pageable/mockapi.js.map +1 -1
  45. package/dist/specs/payload/xml/mockapi.js +1 -4
  46. package/dist/specs/payload/xml/mockapi.js.map +1 -1
  47. package/dist/specs/response/status-code-range/mockapi.d.ts +3 -0
  48. package/dist/specs/response/status-code-range/mockapi.d.ts.map +1 -0
  49. package/dist/specs/response/status-code-range/mockapi.js +29 -0
  50. package/dist/specs/response/status-code-range/mockapi.js.map +1 -0
  51. package/dist/specs/routes/mockapi.js +25 -25
  52. package/dist/specs/routes/mockapi.js.map +1 -1
  53. package/dist/specs/serialization/encoded-name/json/mockapi.js +1 -1
  54. package/dist/specs/serialization/encoded-name/json/mockapi.js.map +1 -1
  55. package/dist/specs/server/versions/not-versioned/mockapi.js +1 -1
  56. package/dist/specs/server/versions/not-versioned/mockapi.js.map +1 -1
  57. package/dist/specs/server/versions/versioned/mockapi.js +8 -12
  58. package/dist/specs/server/versions/versioned/mockapi.js.map +1 -1
  59. package/dist/specs/special-words/mockapi.d.ts.map +1 -1
  60. package/dist/specs/special-words/mockapi.js +28 -6
  61. package/dist/specs/special-words/mockapi.js.map +1 -1
  62. package/dist/specs/streaming/jsonl/mockapi.d.ts +3 -0
  63. package/dist/specs/streaming/jsonl/mockapi.d.ts.map +1 -0
  64. package/dist/specs/streaming/jsonl/mockapi.js +30 -0
  65. package/dist/specs/streaming/jsonl/mockapi.js.map +1 -0
  66. package/dist/specs/type/array/mockapi.js +1 -1
  67. package/dist/specs/type/array/mockapi.js.map +1 -1
  68. package/dist/specs/type/dictionary/mockapi.js +1 -1
  69. package/dist/specs/type/dictionary/mockapi.js.map +1 -1
  70. package/dist/specs/type/enum/extensible/mockapi.js +1 -1
  71. package/dist/specs/type/enum/extensible/mockapi.js.map +1 -1
  72. package/dist/specs/type/enum/fixed/mockapi.js +2 -2
  73. package/dist/specs/type/enum/fixed/mockapi.js.map +1 -1
  74. package/dist/specs/type/model/empty/mockapi.js +2 -2
  75. package/dist/specs/type/model/empty/mockapi.js.map +1 -1
  76. package/dist/specs/type/model/inheritance/enum-discriminator/mockapi.js +1 -1
  77. package/dist/specs/type/model/inheritance/enum-discriminator/mockapi.js.map +1 -1
  78. package/dist/specs/type/model/inheritance/nested-discriminator/mockapi.js +2 -2
  79. package/dist/specs/type/model/inheritance/nested-discriminator/mockapi.js.map +1 -1
  80. package/dist/specs/type/model/inheritance/not-discriminated/mockapi.js +2 -2
  81. package/dist/specs/type/model/inheritance/not-discriminated/mockapi.js.map +1 -1
  82. package/dist/specs/type/model/inheritance/recursive/mockapi.js +1 -1
  83. package/dist/specs/type/model/inheritance/recursive/mockapi.js.map +1 -1
  84. package/dist/specs/type/model/inheritance/single-discriminator/mockapi.js +2 -2
  85. package/dist/specs/type/model/inheritance/single-discriminator/mockapi.js.map +1 -1
  86. package/dist/specs/type/model/usage/mockapi.js +4 -4
  87. package/dist/specs/type/model/usage/mockapi.js.map +1 -1
  88. package/dist/specs/type/model/visibility/mockapi.js +9 -10
  89. package/dist/specs/type/model/visibility/mockapi.js.map +1 -1
  90. package/dist/specs/type/property/additional-properties/mockapi.js +9 -6
  91. package/dist/specs/type/property/additional-properties/mockapi.js.map +1 -1
  92. package/dist/specs/type/property/nullable/mockapi.js +2 -6
  93. package/dist/specs/type/property/nullable/mockapi.js.map +1 -1
  94. package/dist/specs/type/property/optionality/mockapi.js +1 -1
  95. package/dist/specs/type/property/optionality/mockapi.js.map +1 -1
  96. package/dist/specs/type/property/value-types/mockapi.js +3 -3
  97. package/dist/specs/type/property/value-types/mockapi.js.map +1 -1
  98. package/dist/specs/type/scalar/mockapi.js +9 -9
  99. package/dist/specs/type/scalar/mockapi.js.map +1 -1
  100. package/dist/specs/type/union/discriminated/mockapi.d.ts +3 -0
  101. package/dist/specs/type/union/discriminated/mockapi.d.ts.map +1 -0
  102. package/dist/specs/type/union/discriminated/mockapi.js +212 -0
  103. package/dist/specs/type/union/discriminated/mockapi.js.map +1 -0
  104. package/dist/specs/type/union/mockapi.js +2 -2
  105. package/dist/specs/type/union/mockapi.js.map +1 -1
  106. package/dist/specs/versioning/added/mockapi.js +6 -6
  107. package/dist/specs/versioning/added/mockapi.js.map +1 -1
  108. package/dist/specs/versioning/madeOptional/mockapi.js +2 -2
  109. package/dist/specs/versioning/madeOptional/mockapi.js.map +1 -1
  110. package/dist/specs/versioning/removed/mockapi.js +46 -2
  111. package/dist/specs/versioning/removed/mockapi.js.map +1 -1
  112. package/dist/specs/versioning/renamedFrom/mockapi.js +5 -5
  113. package/dist/specs/versioning/renamedFrom/mockapi.js.map +1 -1
  114. package/dist/specs/versioning/returnTypeChangedFrom/mockapi.js +1 -1
  115. package/dist/specs/versioning/returnTypeChangedFrom/mockapi.js.map +1 -1
  116. package/dist/specs/versioning/typeChangedFrom/mockapi.js +3 -3
  117. package/dist/specs/versioning/typeChangedFrom/mockapi.js.map +1 -1
  118. package/package.json +32 -19
  119. package/smoke/petstore/main.tsp +96 -0
  120. package/smoke/todoapp/main.tsp +293 -0
  121. package/spec-summary.md +1289 -265
  122. package/specs/documentation/main.tsp +158 -0
  123. package/specs/documentation/mockapi.ts +57 -0
  124. package/specs/encode/array/main.tsp +112 -0
  125. package/specs/encode/array/mockapi.ts +43 -0
  126. package/specs/encode/bytes/main.tsp +29 -20
  127. package/specs/encode/bytes/mockapi.ts +13 -31
  128. package/specs/encode/datetime/main.tsp +2 -7
  129. package/specs/encode/datetime/mockapi.ts +2 -2
  130. package/specs/encode/duration/main.tsp +420 -7
  131. package/specs/encode/duration/mockapi.ts +174 -2
  132. package/specs/encode/numeric/mockapi.ts +2 -2
  133. package/specs/parameters/basic/mockapi.ts +3 -3
  134. package/specs/parameters/body-optionality/main.tsp +2 -0
  135. package/specs/parameters/body-optionality/mockapi.ts +24 -4
  136. package/specs/parameters/collection-format/main.tsp +5 -25
  137. package/specs/parameters/collection-format/mockapi.ts +4 -16
  138. package/specs/parameters/path/main.tsp +48 -0
  139. package/specs/parameters/path/mockapi.ts +34 -0
  140. package/specs/parameters/spread/mockapi.ts +19 -19
  141. package/specs/payload/json-merge-patch/main.tsp +2 -2
  142. package/specs/payload/json-merge-patch/mockapi.ts +4 -4
  143. package/specs/payload/media-type/mockapi.ts +2 -2
  144. package/specs/payload/multipart/main.tsp +34 -32
  145. package/specs/payload/multipart/mockapi.ts +42 -59
  146. package/specs/payload/pageable/main.tsp +462 -7
  147. package/specs/payload/pageable/mockapi.ts +478 -18
  148. package/specs/payload/xml/mockapi.ts +1 -4
  149. package/specs/response/status-code-range/main.tsp +82 -0
  150. package/specs/response/status-code-range/mockapi.ts +31 -0
  151. package/specs/routes/main.tsp +48 -48
  152. package/specs/routes/mockapi.ts +25 -25
  153. package/specs/serialization/encoded-name/json/main.tsp +1 -1
  154. package/specs/serialization/encoded-name/json/mockapi.ts +1 -1
  155. package/specs/server/endpoint/not-defined/main.tsp +1 -3
  156. package/specs/server/path/multiple/main.tsp +3 -5
  157. package/specs/server/versions/not-versioned/mockapi.ts +1 -1
  158. package/specs/server/versions/versioned/main.tsp +1 -1
  159. package/specs/server/versions/versioned/mockapi.ts +6 -12
  160. package/specs/special-headers/conditional-request/main.tsp +1 -1
  161. package/specs/special-headers/repeatability/main.tsp +2 -2
  162. package/specs/special-words/main.tsp +44 -6
  163. package/specs/special-words/mockapi.ts +29 -6
  164. package/specs/streaming/jsonl/main.tsp +33 -0
  165. package/specs/streaming/jsonl/mockapi.ts +32 -0
  166. package/specs/type/array/mockapi.ts +1 -1
  167. package/specs/type/dictionary/mockapi.ts +1 -1
  168. package/specs/type/enum/extensible/main.tsp +18 -2
  169. package/specs/type/enum/extensible/mockapi.ts +1 -1
  170. package/specs/type/enum/fixed/main.tsp +15 -3
  171. package/specs/type/enum/fixed/mockapi.ts +2 -2
  172. package/specs/type/model/empty/mockapi.ts +2 -2
  173. package/specs/type/model/inheritance/enum-discriminator/mockapi.ts +1 -1
  174. package/specs/type/model/inheritance/nested-discriminator/mockapi.ts +2 -2
  175. package/specs/type/model/inheritance/not-discriminated/mockapi.ts +2 -2
  176. package/specs/type/model/inheritance/recursive/mockapi.ts +1 -1
  177. package/specs/type/model/inheritance/single-discriminator/mockapi.ts +2 -2
  178. package/specs/type/model/usage/mockapi.ts +4 -4
  179. package/specs/type/model/visibility/main.tsp +15 -23
  180. package/specs/type/model/visibility/mockapi.ts +9 -10
  181. package/specs/type/property/additional-properties/main.tsp +17 -17
  182. package/specs/type/property/additional-properties/mockapi.ts +10 -10
  183. package/specs/type/property/nullable/mockapi.ts +7 -8
  184. package/specs/type/property/optionality/mockapi.ts +1 -1
  185. package/specs/type/property/value-types/mockapi.ts +3 -3
  186. package/specs/type/scalar/main.tsp +58 -9
  187. package/specs/type/scalar/mockapi.ts +9 -9
  188. package/specs/type/union/discriminated/main.tsp +251 -0
  189. package/specs/type/union/discriminated/mockapi.ts +230 -0
  190. package/specs/type/union/mockapi.ts +2 -2
  191. package/specs/versioning/added/mockapi.ts +6 -6
  192. package/specs/versioning/madeOptional/mockapi.ts +2 -2
  193. package/specs/versioning/removed/main.tsp +65 -3
  194. package/specs/versioning/removed/mockapi.ts +49 -2
  195. package/specs/versioning/renamedFrom/mockapi.ts +5 -5
  196. package/specs/versioning/returnTypeChangedFrom/main.tsp +17 -2
  197. package/specs/versioning/returnTypeChangedFrom/mockapi.ts +1 -1
  198. package/specs/versioning/typeChangedFrom/mockapi.ts +3 -3
  199. package/temp/.tsbuildinfo +1 -1
  200. package/tspconfig.yaml +0 -2
  201. package/dist/specs/type/model/templated/mockapi.d.ts.map +0 -1
  202. package/dist/specs/type/model/templated/mockapi.js +0 -63
  203. package/dist/specs/type/model/templated/mockapi.js.map +0 -1
  204. package/specs/type/model/templated/main.tsp +0 -130
  205. package/specs/type/model/templated/mockapi.ts +0 -66
  206. /package/dist/specs/{type/model/templated → documentation}/mockapi.d.ts +0 -0
@@ -1,12 +1,217 @@
1
- import { json, MockRequest, passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
1
+ import {
2
+ dyn,
3
+ dynItem,
4
+ json,
5
+ MockRequest,
6
+ passOnSuccess,
7
+ ScenarioMockApi,
8
+ ValidationError,
9
+ } from "@typespec/spec-api";
2
10
 
3
11
  export const Scenarios: Record<string, ScenarioMockApi> = {};
4
12
 
13
+ const FirstPage = [
14
+ { id: "1", name: "dog" },
15
+ { id: "2", name: "cat" },
16
+ ];
17
+
18
+ const SecondPage = [
19
+ { id: "3", name: "bird" },
20
+ { id: "4", name: "fish" },
21
+ ];
22
+
23
+ const FirstResponseTokenInBody = {
24
+ status: 200,
25
+ body: json({
26
+ pets: FirstPage,
27
+ nextToken: "page2",
28
+ }),
29
+ };
30
+
31
+ const SecondResponse = {
32
+ status: 200,
33
+ body: json({
34
+ pets: SecondPage,
35
+ }),
36
+ };
37
+
38
+ const FirstResponseTokenInHeader = {
39
+ status: 200,
40
+ body: json({
41
+ pets: FirstPage,
42
+ }),
43
+ headers: {
44
+ "next-token": "page2",
45
+ foo: "foo",
46
+ },
47
+ };
48
+
49
+ const RequestTokenInQuery = {
50
+ query: { token: "page2", bar: "bar" },
51
+ headers: { foo: "foo" },
52
+ };
53
+
54
+ const RequestTokenInHeader = { headers: { token: "page2", foo: "foo" }, query: { bar: "bar" } };
55
+
56
+ function createTests(reqInfo: "query" | "header", resInfo: "body" | "header") {
57
+ const uri = `/payload/pageable/server-driven-pagination/continuationtoken/request-${reqInfo}-response-${resInfo}`;
58
+ function createHandler() {
59
+ return (req: MockRequest) => {
60
+ req.expect.containsHeader("foo", "foo");
61
+ req.expect.containsQueryParam("bar", "bar");
62
+ const token = reqInfo === "header" ? req.headers?.token : req.query?.token;
63
+ switch (token) {
64
+ case undefined:
65
+ return resInfo === "header" ? FirstResponseTokenInHeader : FirstResponseTokenInBody;
66
+ case "page2":
67
+ return SecondResponse;
68
+ default:
69
+ throw new ValidationError(
70
+ "Unsupported continuation token",
71
+ `"undefined" | "page2"`,
72
+ token,
73
+ );
74
+ }
75
+ };
76
+ }
77
+
78
+ return passOnSuccess([
79
+ {
80
+ uri: uri,
81
+ method: "get",
82
+ request: { headers: { foo: "foo" }, query: { bar: "bar" } },
83
+ response: resInfo === "header" ? FirstResponseTokenInHeader : FirstResponseTokenInBody,
84
+ handler: createHandler(),
85
+ kind: "MockApiDefinition",
86
+ },
87
+ {
88
+ uri: uri,
89
+ method: "get",
90
+ request: reqInfo === "header" ? RequestTokenInHeader : RequestTokenInQuery,
91
+ response: SecondResponse,
92
+ handler: createHandler(),
93
+ kind: "MockApiDefinition",
94
+ },
95
+ ]);
96
+ }
97
+
5
98
  Scenarios.Payload_Pageable_ServerDrivenPagination_link = passOnSuccess([
6
99
  {
7
100
  uri: "/payload/pageable/server-driven-pagination/link",
8
101
  method: "get",
9
102
  request: {},
103
+ response: {
104
+ status: 200,
105
+ body: json({
106
+ pets: FirstPage,
107
+ next: dyn`${dynItem("baseUrl")}/payload/pageable/server-driven-pagination/link/nextPage`,
108
+ }),
109
+ },
110
+ kind: "MockApiDefinition",
111
+ },
112
+ {
113
+ uri: "/payload/pageable/server-driven-pagination/link/nextPage",
114
+ method: "get",
115
+ request: {},
116
+ response: SecondResponse,
117
+ kind: "MockApiDefinition",
118
+ },
119
+ ]);
120
+
121
+ Scenarios.Payload_Pageable_ServerDrivenPagination_linkString = passOnSuccess([
122
+ {
123
+ uri: "/payload/pageable/server-driven-pagination/link-string",
124
+ method: "get",
125
+ request: {},
126
+ response: {
127
+ status: 200,
128
+ body: json({
129
+ pets: FirstPage,
130
+ next: dyn`${dynItem("baseUrl")}/payload/pageable/server-driven-pagination/link-string/nextPage`,
131
+ }),
132
+ },
133
+ kind: "MockApiDefinition",
134
+ },
135
+ {
136
+ uri: "/payload/pageable/server-driven-pagination/link-string/nextPage",
137
+ method: "get",
138
+ request: {},
139
+ response: SecondResponse,
140
+ kind: "MockApiDefinition",
141
+ },
142
+ ]);
143
+
144
+ Scenarios.Payload_Pageable_ServerDrivenPagination_nestedLink = passOnSuccess([
145
+ {
146
+ uri: "/payload/pageable/server-driven-pagination/nested-link",
147
+ method: "get",
148
+ request: {},
149
+ response: {
150
+ status: 200,
151
+ body: json({
152
+ nestedItems: {
153
+ pets: FirstPage,
154
+ },
155
+ nestedNext: {
156
+ next: dyn`${dynItem("baseUrl")}/payload/pageable/server-driven-pagination/nested-link/nextPage`,
157
+ },
158
+ }),
159
+ },
160
+ kind: "MockApiDefinition",
161
+ },
162
+ {
163
+ uri: "/payload/pageable/server-driven-pagination/nested-link/nextPage",
164
+ method: "get",
165
+ request: {},
166
+ response: {
167
+ status: 200,
168
+ body: json({
169
+ nestedItems: {
170
+ pets: SecondPage,
171
+ },
172
+ }),
173
+ },
174
+ kind: "MockApiDefinition",
175
+ },
176
+ ]);
177
+
178
+ Scenarios.Payload_Pageable_ServerDrivenPagination_ContinuationToken_requestQueryResponseBody =
179
+ createTests("query", "body");
180
+
181
+ Scenarios.Payload_Pageable_ServerDrivenPagination_ContinuationToken_requestHeaderResponseBody =
182
+ createTests("header", "body");
183
+
184
+ Scenarios.Payload_Pageable_ServerDrivenPagination_ContinuationToken_requestQueryResponseHeader =
185
+ createTests("query", "header");
186
+
187
+ Scenarios.Payload_Pageable_ServerDrivenPagination_ContinuationToken_requestHeaderResponseHeader =
188
+ createTests("header", "header");
189
+
190
+ Scenarios.Payload_Pageable_PageSize_listWithoutContinuation = passOnSuccess([
191
+ {
192
+ uri: "/payload/pageable/pagesize/without-continuation",
193
+ method: "get",
194
+ request: {},
195
+ response: {
196
+ status: 200,
197
+ body: json({
198
+ pets: [
199
+ { id: "1", name: "dog" },
200
+ { id: "2", name: "cat" },
201
+ { id: "3", name: "bird" },
202
+ { id: "4", name: "fish" },
203
+ ],
204
+ }),
205
+ },
206
+ kind: "MockApiDefinition",
207
+ },
208
+ ]);
209
+
210
+ Scenarios.Payload_Pageable_PageSize_listWithPageSize = passOnSuccess([
211
+ {
212
+ uri: "/payload/pageable/pagesize/list",
213
+ method: "get",
214
+ request: { query: { pageSize: "2" } },
10
215
  response: {
11
216
  status: 200,
12
217
  body: json({
@@ -14,40 +219,295 @@ Scenarios.Payload_Pageable_ServerDrivenPagination_link = passOnSuccess([
14
219
  { id: "1", name: "dog" },
15
220
  { id: "2", name: "cat" },
16
221
  ],
17
- links: {
18
- next: "/payload/pageable/server-driven-pagination/link/nextPage",
19
- },
20
222
  }),
21
223
  },
22
224
  handler: (req: MockRequest) => {
23
- return {
24
- status: 200,
25
- body: json({
26
- pets: [
27
- { id: "1", name: "dog" },
28
- { id: "2", name: "cat" },
29
- ],
30
- links: {
31
- next: `${req.baseUrl}/payload/pageable/server-driven-pagination/link/nextPage`,
32
- },
33
- }),
34
- };
225
+ const pageSize = req.query?.pageSize;
226
+
227
+ switch (pageSize) {
228
+ case "2":
229
+ return {
230
+ status: 200,
231
+ body: json({
232
+ pets: [
233
+ { id: "1", name: "dog" },
234
+ { id: "2", name: "cat" },
235
+ ],
236
+ }),
237
+ };
238
+ case "4":
239
+ return {
240
+ status: 200,
241
+ body: json({
242
+ pets: [
243
+ { id: "1", name: "dog" },
244
+ { id: "2", name: "cat" },
245
+ { id: "3", name: "bird" },
246
+ { id: "4", name: "fish" },
247
+ ],
248
+ }),
249
+ };
250
+ default:
251
+ throw new ValidationError("Unsupported page size", `"2" | "4"`, pageSize);
252
+ }
35
253
  },
36
254
  kind: "MockApiDefinition",
37
255
  },
38
256
  {
39
- uri: "/payload/pageable/server-driven-pagination/link/nextPage",
257
+ uri: "/payload/pageable/pagesize/list",
40
258
  method: "get",
41
- request: {},
259
+ request: { query: { pageSize: "4" } },
42
260
  response: {
43
261
  status: 200,
44
262
  body: json({
45
263
  pets: [
264
+ { id: "1", name: "dog" },
265
+ { id: "2", name: "cat" },
46
266
  { id: "3", name: "bird" },
47
267
  { id: "4", name: "fish" },
48
268
  ],
49
269
  }),
50
270
  },
271
+ handler: (req: MockRequest) => {
272
+ const pageSize = req.query?.pageSize;
273
+
274
+ switch (pageSize) {
275
+ case "2":
276
+ return {
277
+ status: 200,
278
+ body: json({
279
+ pets: [
280
+ { id: "1", name: "dog" },
281
+ { id: "2", name: "cat" },
282
+ ],
283
+ }),
284
+ };
285
+ case "4":
286
+ return {
287
+ status: 200,
288
+ body: json({
289
+ pets: [
290
+ { id: "1", name: "dog" },
291
+ { id: "2", name: "cat" },
292
+ { id: "3", name: "bird" },
293
+ { id: "4", name: "fish" },
294
+ ],
295
+ }),
296
+ };
297
+ default:
298
+ throw new ValidationError("Unsupported page size", `"2" | "4"`, pageSize);
299
+ }
300
+ },
51
301
  kind: "MockApiDefinition",
52
302
  },
53
303
  ]);
304
+
305
+ Scenarios.Payload_Pageable_ServerDrivenPagination_ContinuationToken_requestQueryNestedResponseBody =
306
+ passOnSuccess([
307
+ {
308
+ uri: "/payload/pageable/server-driven-pagination/continuationtoken/request-query-nested-response-body",
309
+ method: "get",
310
+ request: { headers: { foo: "foo" }, query: { bar: "bar" } },
311
+ response: {
312
+ status: 200,
313
+ body: json({
314
+ nestedItems: {
315
+ pets: FirstPage,
316
+ },
317
+ nestedNext: {
318
+ nextToken: "page2",
319
+ },
320
+ }),
321
+ },
322
+ handler: (req: MockRequest) => {
323
+ req.expect.containsHeader("foo", "foo");
324
+ req.expect.containsQueryParam("bar", "bar");
325
+ const token = req.query?.token;
326
+
327
+ switch (token) {
328
+ case undefined:
329
+ return {
330
+ status: 200,
331
+ body: json({
332
+ nestedItems: {
333
+ pets: FirstPage,
334
+ },
335
+ nestedNext: {
336
+ nextToken: "page2",
337
+ },
338
+ }),
339
+ };
340
+ case "page2":
341
+ return {
342
+ status: 200,
343
+ body: json({
344
+ nestedItems: {
345
+ pets: SecondPage,
346
+ },
347
+ }),
348
+ };
349
+ default:
350
+ throw new ValidationError(
351
+ "Unsupported continuation token",
352
+ `"undefined" | "page2"`,
353
+ token,
354
+ );
355
+ }
356
+ },
357
+ kind: "MockApiDefinition",
358
+ },
359
+ {
360
+ uri: "/payload/pageable/server-driven-pagination/continuationtoken/request-query-nested-response-body",
361
+ method: "get",
362
+ request: RequestTokenInQuery,
363
+ response: {
364
+ status: 200,
365
+ body: json({
366
+ nestedItems: {
367
+ pets: SecondPage,
368
+ },
369
+ }),
370
+ },
371
+ handler: (req: MockRequest) => {
372
+ req.expect.containsHeader("foo", "foo");
373
+ req.expect.containsQueryParam("bar", "bar");
374
+ const token = req.query?.token;
375
+
376
+ switch (token) {
377
+ case undefined:
378
+ return {
379
+ status: 200,
380
+ body: json({
381
+ nestedItems: {
382
+ pets: FirstPage,
383
+ },
384
+ nestedNext: {
385
+ nextToken: "page2",
386
+ },
387
+ }),
388
+ };
389
+ case "page2":
390
+ return {
391
+ status: 200,
392
+ body: json({
393
+ nestedItems: {
394
+ pets: SecondPage,
395
+ },
396
+ }),
397
+ };
398
+ default:
399
+ throw new ValidationError(
400
+ "Unsupported continuation token",
401
+ `"undefined" | "page2"`,
402
+ token,
403
+ );
404
+ }
405
+ },
406
+ kind: "MockApiDefinition",
407
+ },
408
+ ]);
409
+
410
+ Scenarios.Payload_Pageable_ServerDrivenPagination_ContinuationToken_requestHeaderNestedResponseBody =
411
+ passOnSuccess([
412
+ {
413
+ uri: "/payload/pageable/server-driven-pagination/continuationtoken/request-header-nested-response-body",
414
+ method: "get",
415
+ request: { headers: { foo: "foo" }, query: { bar: "bar" } },
416
+ response: {
417
+ status: 200,
418
+ body: json({
419
+ nestedItems: {
420
+ pets: FirstPage,
421
+ },
422
+ nestedNext: {
423
+ nextToken: "page2",
424
+ },
425
+ }),
426
+ },
427
+ handler: (req: MockRequest) => {
428
+ req.expect.containsHeader("foo", "foo");
429
+ req.expect.containsQueryParam("bar", "bar");
430
+ const token = req.headers?.token;
431
+
432
+ switch (token) {
433
+ case undefined:
434
+ return {
435
+ status: 200,
436
+ body: json({
437
+ nestedItems: {
438
+ pets: FirstPage,
439
+ },
440
+ nestedNext: {
441
+ nextToken: "page2",
442
+ },
443
+ }),
444
+ };
445
+ case "page2":
446
+ return {
447
+ status: 200,
448
+ body: json({
449
+ nestedItems: {
450
+ pets: SecondPage,
451
+ },
452
+ }),
453
+ };
454
+ default:
455
+ throw new ValidationError(
456
+ "Unsupported continuation token",
457
+ `"undefined" | "page2"`,
458
+ token,
459
+ );
460
+ }
461
+ },
462
+ kind: "MockApiDefinition",
463
+ },
464
+ {
465
+ uri: "/payload/pageable/server-driven-pagination/continuationtoken/request-header-nested-response-body",
466
+ method: "get",
467
+ request: RequestTokenInHeader,
468
+ response: {
469
+ status: 200,
470
+ body: json({
471
+ nestedItems: {
472
+ pets: SecondPage,
473
+ },
474
+ }),
475
+ },
476
+ handler: (req: MockRequest) => {
477
+ req.expect.containsHeader("foo", "foo");
478
+ req.expect.containsQueryParam("bar", "bar");
479
+ const token = req.headers?.token;
480
+
481
+ switch (token) {
482
+ case undefined:
483
+ return {
484
+ status: 200,
485
+ body: json({
486
+ nestedItems: {
487
+ pets: FirstPage,
488
+ },
489
+ nestedNext: {
490
+ nextToken: "page2",
491
+ },
492
+ }),
493
+ };
494
+ case "page2":
495
+ return {
496
+ status: 200,
497
+ body: json({
498
+ nestedItems: {
499
+ pets: SecondPage,
500
+ },
501
+ }),
502
+ };
503
+ default:
504
+ throw new ValidationError(
505
+ "Unsupported continuation token",
506
+ `"undefined" | "page2"`,
507
+ token,
508
+ );
509
+ }
510
+ },
511
+ kind: "MockApiDefinition",
512
+ },
513
+ ]);
@@ -139,10 +139,7 @@ function createServerTests(uri: string, data?: any) {
139
139
  uri,
140
140
  method: "put",
141
141
  request: {
142
- body: data,
143
- headers: {
144
- "content-type": "application/xml",
145
- },
142
+ body: xml(data),
146
143
  },
147
144
  handler: (req: MockRequest) => {
148
145
  req.expect.containsHeader("content-type", "application/xml");
@@ -0,0 +1,82 @@
1
+ import "@typespec/http";
2
+ import "@typespec/spector";
3
+
4
+ using Http;
5
+ using Spector;
6
+
7
+ /**
8
+ * Test for range of status code.
9
+ */
10
+ @scenarioService("/response/status-code-range")
11
+ namespace Response.StatusCodeRange;
12
+
13
+ @scenario
14
+ @scenarioDoc("""
15
+ Test case for range of status code in error response.
16
+
17
+ Verify that the result of the API is an error/exception in client, and the error response can be de-serialized to ErrorInRange model (instead of DefaultError model).
18
+
19
+ Expected status code 494 and response body:
20
+ ```json
21
+ {
22
+ "code": "request-header-too-large",
23
+ "message": "Request header too large"
24
+ }
25
+ ```
26
+ """)
27
+ @route("/error-response-status-code-in-range")
28
+ @get
29
+ op errorResponseStatusCodeInRange(): NoContentResponse | ErrorInRange | DefaultError;
30
+
31
+ @scenario
32
+ @scenarioDoc("""
33
+ Test case for range of status code in error response.
34
+
35
+ Verify that the result of the API is an error/exception in client, and the error response can be de-serialized to NotFoundError model (instead of Standard4XXError model).
36
+
37
+ Expected status code 404 and response body:
38
+ ```json
39
+ {
40
+ "code": "not-found",
41
+ "resourceId": "resource1"
42
+ }
43
+ ```
44
+ """)
45
+ @route("/error-response-status-code-404")
46
+ @get
47
+ op errorResponseStatusCode404(): NoContentResponse | NotFoundError | Standard4XXError;
48
+
49
+ @error
50
+ model NotFoundError {
51
+ @statusCode
52
+ _: 404;
53
+
54
+ code: string;
55
+ resourceId: string;
56
+ }
57
+
58
+ @error
59
+ model ErrorInRange {
60
+ @minValue(494)
61
+ @maxValue(499)
62
+ @statusCode
63
+ _: int32;
64
+
65
+ code: string;
66
+ message: string;
67
+ }
68
+
69
+ @error
70
+ model Standard4XXError {
71
+ @minValue(400)
72
+ @maxValue(499)
73
+ @statusCode
74
+ _: int32;
75
+
76
+ code: string;
77
+ }
78
+
79
+ @error
80
+ model DefaultError {
81
+ code: string;
82
+ }
@@ -0,0 +1,31 @@
1
+ import { json, passOnCode, ScenarioMockApi } from "@typespec/spec-api";
2
+
3
+ export const Scenarios: Record<string, ScenarioMockApi> = {};
4
+
5
+ Scenarios.Response_StatusCodeRange_errorResponseStatusCodeInRange = passOnCode(494, {
6
+ uri: "/response/status-code-range/error-response-status-code-in-range",
7
+ method: "get",
8
+ request: {},
9
+ response: {
10
+ status: 494,
11
+ body: json({
12
+ code: "request-header-too-large",
13
+ message: "Request header too large",
14
+ }),
15
+ },
16
+ kind: "MockApiDefinition",
17
+ });
18
+
19
+ Scenarios.Response_StatusCodeRange_errorResponseStatusCode404 = passOnCode(404, {
20
+ uri: "/response/status-code-range/error-response-status-code-404",
21
+ method: "get",
22
+ request: {},
23
+ response: {
24
+ status: 404,
25
+ body: json({
26
+ code: "not-found",
27
+ resourceId: "resource1",
28
+ }),
29
+ },
30
+ kind: "MockApiDefinition",
31
+ });