@typespec/http-specs 0.1.0-alpha.35-dev.5 → 0.1.0-alpha.36-dev.3

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.
@@ -1,244 +1,149 @@
1
- import {
2
- CollectionFormat,
3
- json,
4
- MockRequest,
5
- passOnSuccess,
6
- ScenarioMockApi,
7
- validateValueFormat,
8
- ValidationError,
9
- } from "@typespec/spec-api";
1
+ import { json, match, MockRequest, passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
10
2
 
11
3
  export const Scenarios: Record<string, ScenarioMockApi> = {};
12
4
 
13
5
  function createQueryServerTests(
14
6
  uri: string,
15
- paramData: any,
16
- format: "rfc7231" | "rfc3339" | undefined,
17
7
  value: any,
18
- collectionFormat?: CollectionFormat,
8
+ format: "rfc7231" | "rfc3339" | "utcRfc3339" | undefined,
19
9
  ) {
20
10
  return passOnSuccess({
21
11
  uri,
22
12
  method: "get",
23
13
  request: {
24
- query: paramData,
14
+ query: { value: format ? match.dateTime[format](value) : value },
25
15
  },
26
16
  response: {
27
17
  status: 204,
28
18
  },
29
- handler(req: MockRequest) {
30
- if (format) {
31
- validateValueFormat(req.query["value"] as string, format);
32
- if (Date.parse(req.query["value"] as string) !== Date.parse(value)) {
33
- throw new ValidationError(`Wrong value`, value, req.query["value"]);
34
- }
35
- } else {
36
- req.expect.containsQueryParam("value", value, collectionFormat);
37
- }
38
- return {
39
- status: 204,
40
- };
41
- },
42
19
  kind: "MockApiDefinition",
43
20
  });
44
21
  }
45
22
  Scenarios.Encode_Datetime_Query_default = createQueryServerTests(
46
23
  "/encode/datetime/query/default",
47
- {
48
- value: "2022-08-26T18:38:00.000Z",
49
- },
50
- "rfc3339",
51
24
  "2022-08-26T18:38:00.000Z",
25
+ "utcRfc3339",
52
26
  );
53
27
  Scenarios.Encode_Datetime_Query_rfc3339 = createQueryServerTests(
54
28
  "/encode/datetime/query/rfc3339",
55
- {
56
- value: "2022-08-26T18:38:00.000Z",
57
- },
58
- "rfc3339",
59
29
  "2022-08-26T18:38:00.000Z",
30
+ "utcRfc3339",
60
31
  );
61
32
  Scenarios.Encode_Datetime_Query_rfc7231 = createQueryServerTests(
62
33
  "/encode/datetime/query/rfc7231",
63
- {
64
- value: "Fri, 26 Aug 2022 14:38:00 GMT",
65
- },
66
- "rfc7231",
67
34
  "Fri, 26 Aug 2022 14:38:00 GMT",
35
+ "rfc7231",
68
36
  );
69
37
  Scenarios.Encode_Datetime_Query_unixTimestamp = createQueryServerTests(
70
38
  "/encode/datetime/query/unix-timestamp",
71
- {
72
- value: 1686566864,
73
- },
74
- undefined,
75
39
  "1686566864",
40
+ undefined,
76
41
  );
77
42
  Scenarios.Encode_Datetime_Query_unixTimestampArray = createQueryServerTests(
78
43
  "/encode/datetime/query/unix-timestamp-array",
79
- {
80
- value: [1686566864, 1686734256].join(","),
81
- },
44
+ [1686566864, 1686734256].join(","),
82
45
  undefined,
83
- ["1686566864", "1686734256"],
84
- "csv",
85
46
  );
86
47
  function createPropertyServerTests(
87
48
  uri: string,
88
- data: any,
89
- format: "rfc7231" | "rfc3339" | undefined,
90
49
  value: any,
50
+ format: "rfc7231" | "rfc3339" | "utcRfc3339" | undefined,
91
51
  ) {
52
+ const matcherBody = { value: format ? match.dateTime[format](value) : value };
92
53
  return passOnSuccess({
93
54
  uri,
94
55
  method: "post",
95
56
  request: {
96
- body: json(data),
57
+ body: json(matcherBody),
97
58
  },
98
59
  response: {
99
60
  status: 200,
100
- },
101
- handler: (req: MockRequest) => {
102
- if (format) {
103
- validateValueFormat(req.body["value"], format);
104
- if (Date.parse(req.body["value"]) !== Date.parse(value)) {
105
- throw new ValidationError(`Wrong value`, value, req.body["value"]);
106
- }
107
- } else {
108
- req.expect.coercedBodyEquals({ value: value });
109
- }
110
- return {
111
- status: 200,
112
- body: json({ value: value }),
113
- };
61
+ body: json(matcherBody),
114
62
  },
115
63
  kind: "MockApiDefinition",
116
64
  });
117
65
  }
118
66
  Scenarios.Encode_Datetime_Property_default = createPropertyServerTests(
119
67
  "/encode/datetime/property/default",
120
- {
121
- value: "2022-08-26T18:38:00.000Z",
122
- },
123
- "rfc3339",
124
68
  "2022-08-26T18:38:00.000Z",
69
+ "utcRfc3339",
125
70
  );
126
71
  Scenarios.Encode_Datetime_Property_rfc3339 = createPropertyServerTests(
127
72
  "/encode/datetime/property/rfc3339",
128
- {
129
- value: "2022-08-26T18:38:00.000Z",
130
- },
131
- "rfc3339",
132
73
  "2022-08-26T18:38:00.000Z",
74
+ "utcRfc3339",
133
75
  );
134
76
  Scenarios.Encode_Datetime_Property_rfc7231 = createPropertyServerTests(
135
77
  "/encode/datetime/property/rfc7231",
136
- {
137
- value: "Fri, 26 Aug 2022 14:38:00 GMT",
138
- },
139
- "rfc7231",
140
78
  "Fri, 26 Aug 2022 14:38:00 GMT",
79
+ "rfc7231",
141
80
  );
142
81
  Scenarios.Encode_Datetime_Property_unixTimestamp = createPropertyServerTests(
143
82
  "/encode/datetime/property/unix-timestamp",
144
- {
145
- value: 1686566864,
146
- },
147
- undefined,
148
83
  1686566864,
84
+ undefined,
149
85
  );
150
86
  Scenarios.Encode_Datetime_Property_unixTimestampArray = createPropertyServerTests(
151
87
  "/encode/datetime/property/unix-timestamp-array",
152
- {
153
- value: [1686566864, 1686734256],
154
- },
155
- undefined,
156
88
  [1686566864, 1686734256],
89
+ undefined,
157
90
  );
158
91
  function createHeaderServerTests(
159
92
  uri: string,
160
- data: any,
161
- format: "rfc7231" | "rfc3339" | undefined,
162
93
  value: any,
94
+ format: "rfc7231" | "rfc3339" | "utcRfc3339" | undefined,
163
95
  ) {
96
+ const matcherHeaders = { value: format ? match.dateTime[format](value) : value };
164
97
  return passOnSuccess({
165
98
  uri,
166
99
  method: "get",
167
100
  request: {
168
- headers: data,
101
+ headers: matcherHeaders,
169
102
  },
170
103
  response: {
171
104
  status: 204,
172
105
  },
173
- handler(req: MockRequest) {
174
- if (format) {
175
- validateValueFormat(req.headers["value"], format);
176
- if (Date.parse(req.headers["value"]) !== Date.parse(value)) {
177
- throw new ValidationError(`Wrong value`, value, req.headers["value"]);
178
- }
179
- } else {
180
- req.expect.containsHeader("value", value);
181
- }
182
- return {
183
- status: 204,
184
- };
185
- },
186
106
  kind: "MockApiDefinition",
187
107
  });
188
108
  }
189
109
  Scenarios.Encode_Datetime_Header_default = createHeaderServerTests(
190
110
  "/encode/datetime/header/default",
191
- {
192
- value: "Fri, 26 Aug 2022 14:38:00 GMT",
193
- },
194
- "rfc7231",
195
111
  "Fri, 26 Aug 2022 14:38:00 GMT",
112
+ "rfc7231",
196
113
  );
197
114
  Scenarios.Encode_Datetime_Header_rfc3339 = createHeaderServerTests(
198
115
  "/encode/datetime/header/rfc3339",
199
- {
200
- value: "2022-08-26T18:38:00.000Z",
201
- },
202
- "rfc3339",
203
116
  "2022-08-26T18:38:00.000Z",
117
+ "utcRfc3339",
204
118
  );
205
119
  Scenarios.Encode_Datetime_Header_rfc7231 = createHeaderServerTests(
206
120
  "/encode/datetime/header/rfc7231",
207
- {
208
- value: "Fri, 26 Aug 2022 14:38:00 GMT",
209
- },
210
- "rfc7231",
211
121
  "Fri, 26 Aug 2022 14:38:00 GMT",
122
+ "rfc7231",
212
123
  );
213
124
  Scenarios.Encode_Datetime_Header_unixTimestamp = createHeaderServerTests(
214
125
  "/encode/datetime/header/unix-timestamp",
215
- {
216
- value: 1686566864,
217
- },
126
+ 1686566864,
218
127
  undefined,
219
- "1686566864",
220
128
  );
221
129
  Scenarios.Encode_Datetime_Header_unixTimestampArray = createHeaderServerTests(
222
130
  "/encode/datetime/header/unix-timestamp-array",
223
- {
224
- value: [1686566864, 1686734256].join(","),
225
- },
131
+ [1686566864, 1686734256].join(","),
226
132
  undefined,
227
- "1686566864,1686734256",
228
133
  );
229
- function createResponseHeaderServerTests(uri: string, data: any, value: any) {
134
+ function createResponseHeaderServerTests(uri: string, value: any) {
230
135
  return passOnSuccess({
231
136
  uri,
232
137
  method: "get",
233
138
  request: {},
234
139
  response: {
235
140
  status: 204,
236
- headers: data,
141
+ headers: { value },
237
142
  },
238
143
  handler: (req: MockRequest) => {
239
144
  return {
240
145
  status: 204,
241
- headers: { value: value },
146
+ headers: { value },
242
147
  };
243
148
  },
244
149
  kind: "MockApiDefinition",
@@ -246,29 +151,17 @@ function createResponseHeaderServerTests(uri: string, data: any, value: any) {
246
151
  }
247
152
  Scenarios.Encode_Datetime_ResponseHeader_default = createResponseHeaderServerTests(
248
153
  "/encode/datetime/responseheader/default",
249
- {
250
- value: "Fri, 26 Aug 2022 14:38:00 GMT",
251
- },
252
154
  "Fri, 26 Aug 2022 14:38:00 GMT",
253
155
  );
254
156
  Scenarios.Encode_Datetime_ResponseHeader_rfc3339 = createResponseHeaderServerTests(
255
157
  "/encode/datetime/responseheader/rfc3339",
256
- {
257
- value: "2022-08-26T18:38:00.000Z",
258
- },
259
158
  "2022-08-26T18:38:00.000Z",
260
159
  );
261
160
  Scenarios.Encode_Datetime_ResponseHeader_rfc7231 = createResponseHeaderServerTests(
262
161
  "/encode/datetime/responseheader/rfc7231",
263
- {
264
- value: "Fri, 26 Aug 2022 14:38:00 GMT",
265
- },
266
162
  "Fri, 26 Aug 2022 14:38:00 GMT",
267
163
  );
268
164
  Scenarios.Encode_Datetime_ResponseHeader_unixTimestamp = createResponseHeaderServerTests(
269
165
  "/encode/datetime/responseheader/unix-timestamp",
270
- {
271
- value: "1686566864",
272
- },
273
- 1686566864,
166
+ "1686566864",
274
167
  );
@@ -2,9 +2,9 @@ import {
2
2
  dyn,
3
3
  dynItem,
4
4
  json,
5
+ match,
5
6
  MockRequest,
6
7
  passOnSuccess,
7
- ResolverConfig,
8
8
  ScenarioMockApi,
9
9
  ValidationError,
10
10
  xml,
@@ -650,22 +650,6 @@ Scenarios.Payload_Pageable_XmlPagination_listWithContinuation = passOnSuccess([
650
650
  },
651
651
  ]);
652
652
 
653
- const xmlNextLinkFirstPage = (baseUrl: string) => `
654
- <PetListResult>
655
- <Pets>
656
- <Pet>
657
- <Id>1</Id>
658
- <Name>dog</Name>
659
- </Pet>
660
- <Pet>
661
- <Id>2</Id>
662
- <Name>cat</Name>
663
- </Pet>
664
- </Pets>
665
- <NextLink>${baseUrl}/payload/pageable/xml/list-with-next-link/nextPage</NextLink>
666
- </PetListResult>
667
- `;
668
-
669
653
  const XmlNextLinkSecondPage = `
670
654
  <PetListResult>
671
655
  <Pets>
@@ -688,26 +672,25 @@ Scenarios.Payload_Pageable_XmlPagination_listWithNextLink = passOnSuccess([
688
672
  request: {},
689
673
  response: {
690
674
  status: 200,
691
- body: {
692
- contentType: "application/xml",
693
- rawContent: {
694
- serialize: (config: ResolverConfig) =>
695
- `<?xml version='1.0' encoding='UTF-8'?>` + xmlNextLinkFirstPage(config.baseUrl),
696
- },
697
- },
675
+ body: xml`
676
+ <PetListResult>
677
+ <Pets>
678
+ <Pet>
679
+ <Id>1</Id>
680
+ <Name>dog</Name>
681
+ </Pet>
682
+ <Pet>
683
+ <Id>2</Id>
684
+ <Name>cat</Name>
685
+ </Pet>
686
+ </Pets>
687
+ <NextLink>${match.localUrl("/payload/pageable/xml/list-with-next-link/nextPage")}</NextLink>
688
+ </PetListResult>
689
+ `,
698
690
  headers: {
699
691
  "content-type": "application/xml; charset=utf-8",
700
692
  },
701
693
  },
702
- handler: (req: MockRequest) => {
703
- return {
704
- status: 200,
705
- body: xml(xmlNextLinkFirstPage(req.baseUrl)),
706
- headers: {
707
- "content-type": "application/xml",
708
- },
709
- };
710
- },
711
694
  kind: "MockApiDefinition",
712
695
  },
713
696
  {
@@ -1,4 +1,11 @@
1
- import { MockRequest, passOnCode, passOnSuccess, ScenarioMockApi, xml } from "@typespec/spec-api";
1
+ import {
2
+ match,
3
+ type MockBody,
4
+ passOnCode,
5
+ passOnSuccess,
6
+ ScenarioMockApi,
7
+ xml,
8
+ } from "@typespec/spec-api";
2
9
 
3
10
  export const Scenarios: Record<string, ScenarioMockApi> = {};
4
11
 
@@ -270,22 +277,19 @@ export const modelWithEnum = `
270
277
  </ModelWithEnum>
271
278
  `;
272
279
 
273
- export const modelWithDatetime = `
280
+ export const modelWithDatetime = xml`
274
281
  <ModelWithDatetime>
275
- <rfc3339>2022-08-26T18:38:00.000Z</rfc3339>
276
- <rfc7231>Fri, 26 Aug 2022 14:38:00 GMT</rfc7231>
282
+ <rfc3339>${match.dateTime.utcRfc3339("2022-08-26T18:38:00.000Z")}</rfc3339>
283
+ <rfc7231>${match.dateTime.rfc7231("Fri, 26 Aug 2022 14:38:00 GMT")}</rfc7231>
277
284
  </ModelWithDatetime>
278
285
  `;
279
286
 
280
- // Some clients serialize UTC datetimes without trailing zero milliseconds. Both
281
- // "2022-08-26T18:38:00.000Z" and "2022-08-26T18:38:00Z" are valid RFC3339 representations
282
- // of the same instant; accept either form.
283
- const modelWithDatetimeNoMs = `
284
- <ModelWithDatetime>
285
- <rfc3339>2022-08-26T18:38:00Z</rfc3339>
286
- <rfc7231>Fri, 26 Aug 2022 14:38:00 GMT</rfc7231>
287
- </ModelWithDatetime>
288
- `;
287
+ const Payload_Xml_ModelWithDatetime = createServerTests(
288
+ "/payload/xml/modelWithDatetime",
289
+ modelWithDatetime,
290
+ );
291
+ Scenarios.Payload_Xml_ModelWithDatetimeValue_get = Payload_Xml_ModelWithDatetime.get;
292
+ Scenarios.Payload_Xml_ModelWithDatetimeValue_put = Payload_Xml_ModelWithDatetime.put;
289
293
 
290
294
  export const xmlError = `
291
295
  <XmlErrorBody>
@@ -298,7 +302,12 @@ export const xmlError = `
298
302
  // Scenario registrations
299
303
  // ────────────────────────────────────────────────────────────────────────────
300
304
 
305
+ function isMockBody(data: any): data is MockBody {
306
+ return typeof data === "object" && data !== null && "contentType" in data;
307
+ }
308
+
301
309
  function createServerTests(uri: string, data?: any) {
310
+ const body = isMockBody(data) ? data : xml(data);
302
311
  return {
303
312
  get: passOnSuccess({
304
313
  uri,
@@ -306,7 +315,7 @@ function createServerTests(uri: string, data?: any) {
306
315
  request: {},
307
316
  response: {
308
317
  status: 200,
309
- body: xml(data),
318
+ body,
310
319
  },
311
320
  kind: "MockApiDefinition",
312
321
  }),
@@ -314,14 +323,7 @@ function createServerTests(uri: string, data?: any) {
314
323
  uri,
315
324
  method: "put",
316
325
  request: {
317
- body: xml(data),
318
- },
319
- handler: (req: MockRequest) => {
320
- req.expect.containsHeader("content-type", "application/xml");
321
- req.expect.xmlBodyEquals(data);
322
- return {
323
- status: 204,
324
- };
326
+ body,
325
327
  },
326
328
  response: {
327
329
  status: 204,
@@ -522,45 +524,6 @@ const Payload_Xml_ModelWithEnum = createServerTests("/payload/xml/modelWithEnum"
522
524
  Scenarios.Payload_Xml_ModelWithEnumValue_get = Payload_Xml_ModelWithEnum.get;
523
525
  Scenarios.Payload_Xml_ModelWithEnumValue_put = Payload_Xml_ModelWithEnum.put;
524
526
 
525
- Scenarios.Payload_Xml_ModelWithDatetimeValue_get = passOnSuccess({
526
- uri: "/payload/xml/modelWithDatetime",
527
- method: "get",
528
- request: {},
529
- response: {
530
- status: 200,
531
- body: xml(modelWithDatetime),
532
- },
533
- kind: "MockApiDefinition",
534
- });
535
-
536
- Scenarios.Payload_Xml_ModelWithDatetimeValue_put = passOnSuccess({
537
- uri: "/payload/xml/modelWithDatetime",
538
- method: "put",
539
- request: {
540
- body: xml(modelWithDatetime),
541
- },
542
- handler: (req: MockRequest) => {
543
- req.expect.containsHeader("content-type", "application/xml");
544
- // Accept both "2022-08-26T18:38:00.000Z" and "2022-08-26T18:38:00Z" as equivalent UTC datetimes.
545
- let firstError: unknown;
546
- try {
547
- req.expect.xmlBodyEquals(modelWithDatetime);
548
- } catch (e) {
549
- firstError = e;
550
- }
551
- if (firstError !== undefined) {
552
- req.expect.xmlBodyEquals(modelWithDatetimeNoMs);
553
- }
554
- return {
555
- status: 204,
556
- };
557
- },
558
- response: {
559
- status: 204,
560
- },
561
- kind: "MockApiDefinition",
562
- });
563
-
564
527
  Scenarios.Payload_Xml_XmlErrorValue_get = passOnCode(400, {
565
528
  uri: "/payload/xml/error",
566
529
  method: "get",