@typespec/http-specs 0.1.0-alpha.32-dev.0 → 0.1.0-alpha.32-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.
@@ -8,6 +8,19 @@ using Spector;
8
8
  @scenarioService("/encode/array")
9
9
  namespace Encode.Array;
10
10
 
11
+ enum Colors {
12
+ Blue: "blue",
13
+ Red: "red",
14
+ Green: "green",
15
+ }
16
+
17
+ union ColorsExtensibleEnum {
18
+ string,
19
+ Blue: "blue",
20
+ Red: "red",
21
+ Green: "green",
22
+ }
23
+
11
24
  model CommaDelimitedArrayProperty {
12
25
  @encode(ArrayEncoding.commaDelimited)
13
26
  value: string[];
@@ -28,6 +41,46 @@ model NewlineDelimitedArrayProperty {
28
41
  value: string[];
29
42
  }
30
43
 
44
+ model CommaDelimitedEnumArrayProperty {
45
+ @encode(ArrayEncoding.commaDelimited)
46
+ value: Colors[];
47
+ }
48
+
49
+ model SpaceDelimitedEnumArrayProperty {
50
+ @encode(ArrayEncoding.spaceDelimited)
51
+ value: Colors[];
52
+ }
53
+
54
+ model PipeDelimitedEnumArrayProperty {
55
+ @encode(ArrayEncoding.pipeDelimited)
56
+ value: Colors[];
57
+ }
58
+
59
+ model NewlineDelimitedEnumArrayProperty {
60
+ @encode(ArrayEncoding.newlineDelimited)
61
+ value: Colors[];
62
+ }
63
+
64
+ model CommaDelimitedExtensibleEnumArrayProperty {
65
+ @encode(ArrayEncoding.commaDelimited)
66
+ value: ColorsExtensibleEnum[];
67
+ }
68
+
69
+ model SpaceDelimitedExtensibleEnumArrayProperty {
70
+ @encode(ArrayEncoding.spaceDelimited)
71
+ value: ColorsExtensibleEnum[];
72
+ }
73
+
74
+ model PipeDelimitedExtensibleEnumArrayProperty {
75
+ @encode(ArrayEncoding.pipeDelimited)
76
+ value: ColorsExtensibleEnum[];
77
+ }
78
+
79
+ model NewlineDelimitedExtensibleEnumArrayProperty {
80
+ @encode(ArrayEncoding.newlineDelimited)
81
+ value: ColorsExtensibleEnum[];
82
+ }
83
+
31
84
  @route("/property")
32
85
  namespace Property {
33
86
  @route("/comma-delimited")
@@ -109,4 +162,178 @@ namespace Property {
109
162
  """)
110
163
  @post
111
164
  op newlineDelimited(@body body: NewlineDelimitedArrayProperty): NewlineDelimitedArrayProperty;
165
+
166
+ @route("/enum/comma-delimited")
167
+ @scenario
168
+ @scenarioDoc("""
169
+ Test operation with request and response model contains an enum array property with commaDelimited encode.
170
+ Expected request body:
171
+ ```json
172
+ {
173
+ "value": "blue,red,green"
174
+ }
175
+ ```
176
+ Expected response body:
177
+ ```json
178
+ {
179
+ "value": "blue,red,green"
180
+ }
181
+ ```
182
+ """)
183
+ @post
184
+ op enumCommaDelimited(
185
+ @body body: CommaDelimitedEnumArrayProperty,
186
+ ): CommaDelimitedEnumArrayProperty;
187
+
188
+ @route("/enum/space-delimited")
189
+ @scenario
190
+ @scenarioDoc("""
191
+ Test operation with request and response model contains an enum array property with spaceDelimited encode.
192
+ Expected request body:
193
+ ```json
194
+ {
195
+ "value": "blue red green"
196
+ }
197
+ ```
198
+ Expected response body:
199
+ ```json
200
+ {
201
+ "value": "blue red green"
202
+ }
203
+ ```
204
+ """)
205
+ @post
206
+ op enumSpaceDelimited(
207
+ @body body: SpaceDelimitedEnumArrayProperty,
208
+ ): SpaceDelimitedEnumArrayProperty;
209
+
210
+ @route("/enum/pipe-delimited")
211
+ @scenario
212
+ @scenarioDoc("""
213
+ Test operation with request and response model contains an enum array property with pipeDelimited encode.
214
+ Expected request body:
215
+ ```json
216
+ {
217
+ "value": "blue|red|green"
218
+ }
219
+ ```
220
+ Expected response body:
221
+ ```json
222
+ {
223
+ "value": "blue|red|green"
224
+ }
225
+ ```
226
+ """)
227
+ @post
228
+ op enumPipeDelimited(@body body: PipeDelimitedEnumArrayProperty): PipeDelimitedEnumArrayProperty;
229
+
230
+ @route("/enum/newline-delimited")
231
+ @scenario
232
+ @scenarioDoc("""
233
+ Test operation with request and response model contains an enum array property with newlineDelimited encode.
234
+ Expected request body:
235
+ ```json
236
+ {
237
+ "value": "blue\\nred\\ngreen"
238
+ }
239
+ ```
240
+ Expected response body:
241
+ ```json
242
+ {
243
+ "value": "blue\\nred\\ngreen"
244
+ }
245
+ ```
246
+ """)
247
+ @post
248
+ op enumNewlineDelimited(
249
+ @body body: NewlineDelimitedEnumArrayProperty,
250
+ ): NewlineDelimitedEnumArrayProperty;
251
+
252
+ @route("/extensible-enum/comma-delimited")
253
+ @scenario
254
+ @scenarioDoc("""
255
+ Test operation with request and response model contains an extensible enum (union) array property with commaDelimited encode.
256
+ Expected request body:
257
+ ```json
258
+ {
259
+ "value": "blue,red,green"
260
+ }
261
+ ```
262
+ Expected response body:
263
+ ```json
264
+ {
265
+ "value": "blue,red,green"
266
+ }
267
+ ```
268
+ """)
269
+ @post
270
+ op extensibleEnumCommaDelimited(
271
+ @body body: CommaDelimitedExtensibleEnumArrayProperty,
272
+ ): CommaDelimitedExtensibleEnumArrayProperty;
273
+
274
+ @route("/extensible-enum/space-delimited")
275
+ @scenario
276
+ @scenarioDoc("""
277
+ Test operation with request and response model contains an extensible enum (union) array property with spaceDelimited encode.
278
+ Expected request body:
279
+ ```json
280
+ {
281
+ "value": "blue red green"
282
+ }
283
+ ```
284
+ Expected response body:
285
+ ```json
286
+ {
287
+ "value": "blue red green"
288
+ }
289
+ ```
290
+ """)
291
+ @post
292
+ op extensibleEnumSpaceDelimited(
293
+ @body body: SpaceDelimitedExtensibleEnumArrayProperty,
294
+ ): SpaceDelimitedExtensibleEnumArrayProperty;
295
+
296
+ @route("/extensible-enum/pipe-delimited")
297
+ @scenario
298
+ @scenarioDoc("""
299
+ Test operation with request and response model contains an extensible enum (union) array property with pipeDelimited encode.
300
+ Expected request body:
301
+ ```json
302
+ {
303
+ "value": "blue|red|green"
304
+ }
305
+ ```
306
+ Expected response body:
307
+ ```json
308
+ {
309
+ "value": "blue|red|green"
310
+ }
311
+ ```
312
+ """)
313
+ @post
314
+ op extensibleEnumPipeDelimited(
315
+ @body body: PipeDelimitedExtensibleEnumArrayProperty,
316
+ ): PipeDelimitedExtensibleEnumArrayProperty;
317
+
318
+ @route("/extensible-enum/newline-delimited")
319
+ @scenario
320
+ @scenarioDoc("""
321
+ Test operation with request and response model contains an extensible enum (union) array property with newlineDelimited encode.
322
+ Expected request body:
323
+ ```json
324
+ {
325
+ "value": "blue\\nred\\ngreen"
326
+ }
327
+ ```
328
+ Expected response body:
329
+ ```json
330
+ {
331
+ "value": "blue\\nred\\ngreen"
332
+ }
333
+ ```
334
+ """)
335
+ @post
336
+ op extensibleEnumNewlineDelimited(
337
+ @body body: NewlineDelimitedExtensibleEnumArrayProperty,
338
+ ): NewlineDelimitedExtensibleEnumArrayProperty;
112
339
  }
@@ -41,3 +41,43 @@ Scenarios.Encode_Array_Property_newlineDelimited = createPropertyServerTests(
41
41
  "/encode/array/property/newline-delimited",
42
42
  "\n",
43
43
  );
44
+
45
+ Scenarios.Encode_Array_Property_enumCommaDelimited = createPropertyServerTests(
46
+ "/encode/array/property/enum/comma-delimited",
47
+ ",",
48
+ );
49
+
50
+ Scenarios.Encode_Array_Property_enumSpaceDelimited = createPropertyServerTests(
51
+ "/encode/array/property/enum/space-delimited",
52
+ " ",
53
+ );
54
+
55
+ Scenarios.Encode_Array_Property_enumPipeDelimited = createPropertyServerTests(
56
+ "/encode/array/property/enum/pipe-delimited",
57
+ "|",
58
+ );
59
+
60
+ Scenarios.Encode_Array_Property_enumNewlineDelimited = createPropertyServerTests(
61
+ "/encode/array/property/enum/newline-delimited",
62
+ "\n",
63
+ );
64
+
65
+ Scenarios.Encode_Array_Property_extensibleEnumCommaDelimited = createPropertyServerTests(
66
+ "/encode/array/property/extensible-enum/comma-delimited",
67
+ ",",
68
+ );
69
+
70
+ Scenarios.Encode_Array_Property_extensibleEnumSpaceDelimited = createPropertyServerTests(
71
+ "/encode/array/property/extensible-enum/space-delimited",
72
+ " ",
73
+ );
74
+
75
+ Scenarios.Encode_Array_Property_extensibleEnumPipeDelimited = createPropertyServerTests(
76
+ "/encode/array/property/extensible-enum/pipe-delimited",
77
+ "|",
78
+ );
79
+
80
+ Scenarios.Encode_Array_Property_extensibleEnumNewlineDelimited = createPropertyServerTests(
81
+ "/encode/array/property/extensible-enum/newline-delimited",
82
+ "\n",
83
+ );
@@ -1,8 +1,10 @@
1
1
  import "@typespec/http";
2
2
  import "@typespec/spector";
3
+ import "@typespec/xml";
3
4
 
4
5
  using Http;
5
6
  using Spector;
7
+ using Xml;
6
8
 
7
9
  /**
8
10
  * Test for pageable payload.
@@ -514,3 +516,141 @@ namespace PageSize {
514
516
  pets: Pet[];
515
517
  };
516
518
  }
519
+
520
+ @doc("An XML pet item.")
521
+ @name("Pet")
522
+ model XmlPet {
523
+ @name("Id") id: string;
524
+ @name("Name") name: string;
525
+ }
526
+
527
+ @route("/xml")
528
+ namespace XmlPagination {
529
+ @scenario
530
+ @scenarioDoc("""
531
+ Test case for XML pagination with continuation token. Continuation token is passed in the request query and response body.
532
+
533
+ Two requests need to be tested.
534
+
535
+ 1. Initial request:
536
+ Expected route: /payload/pageable/xml/list
537
+
538
+ Expected response body:
539
+ ```xml
540
+ <PetListResult>
541
+ <Pets>
542
+ <Pet>
543
+ <Id>1</Id>
544
+ <Name>dog</Name>
545
+ </Pet>
546
+ <Pet>
547
+ <Id>2</Id>
548
+ <Name>cat</Name>
549
+ </Pet>
550
+ </Pets>
551
+ <NextMarker>page2</NextMarker>
552
+ </PetListResult>
553
+ ```
554
+
555
+ 2. Next page request:
556
+ Expected route: /payload/pageable/xml/list?marker=page2
557
+
558
+ Expected response body:
559
+ ```xml
560
+ <PetListResult>
561
+ <Pets>
562
+ <Pet>
563
+ <Id>3</Id>
564
+ <Name>bird</Name>
565
+ </Pet>
566
+ <Pet>
567
+ <Id>4</Id>
568
+ <Name>fish</Name>
569
+ </Pet>
570
+ </Pets>
571
+ </PetListResult>
572
+ ```
573
+ """)
574
+ @route("/list-with-continuation")
575
+ @list
576
+ op listWithContinuation(@continuationToken @query marker?: string): {
577
+ @header("content-type") contentType: "application/xml";
578
+ @body body: XmlPetListResult;
579
+ };
580
+
581
+ @scenario
582
+ @scenarioDoc("""
583
+ Test case for XML pagination with next link.
584
+
585
+ Two requests need to be tested.
586
+
587
+ 1. Initial request:
588
+ Expected route: /payload/pageable/xml/list-with-next-link
589
+
590
+ Expected response body:
591
+ ```xml
592
+ <PetListResult>
593
+ <Pets>
594
+ <Pet>
595
+ <Id>1</Id>
596
+ <Name>dog</Name>
597
+ </Pet>
598
+ <Pet>
599
+ <Id>2</Id>
600
+ <Name>cat</Name>
601
+ </Pet>
602
+ </Pets>
603
+ <NextLink>http://[host]:[port]/payload/pageable/xml/list-with-next-link/nextPage</NextLink>
604
+ </PetListResult>
605
+ ```
606
+
607
+ 2. Next page request:
608
+ Expected route: /payload/pageable/xml/list-with-next-link/nextPage
609
+
610
+ Expected response body:
611
+ ```xml
612
+ <PetListResult>
613
+ <Pets>
614
+ <Pet>
615
+ <Id>3</Id>
616
+ <Name>bird</Name>
617
+ </Pet>
618
+ <Pet>
619
+ <Id>4</Id>
620
+ <Name>fish</Name>
621
+ </Pet>
622
+ </Pets>
623
+ </PetListResult>
624
+ ```
625
+ """)
626
+ @route("/list-with-next-link")
627
+ @list
628
+ op listWithNextLink(): {
629
+ @header("content-type") contentType: "application/xml";
630
+ @body body: XmlPetListResultWithNextLink;
631
+ };
632
+ }
633
+
634
+ @doc("The XML response for listing pets.")
635
+ @name("PetListResult")
636
+ model XmlPetListResult {
637
+ @pageItems
638
+ @name("Pets")
639
+ pets: XmlPet[];
640
+
641
+ @continuationToken
642
+ @name("NextMarker")
643
+ nextMarker?: string;
644
+ }
645
+
646
+ @doc("The XML response for listing pets with next link.")
647
+ @name("PetListResult")
648
+ model XmlPetListResultWithNextLink {
649
+ @pageItems
650
+ @name("Pets")
651
+ pets: XmlPet[];
652
+
653
+ @nextLink
654
+ @name("NextLink")
655
+ nextLink?: url;
656
+ }
@@ -6,6 +6,7 @@ import {
6
6
  passOnSuccess,
7
7
  ScenarioMockApi,
8
8
  ValidationError,
9
+ xml,
9
10
  } from "@typespec/spec-api";
10
11
 
11
12
  export const Scenarios: Record<string, ScenarioMockApi> = {};
@@ -511,3 +512,180 @@ Scenarios.Payload_Pageable_ServerDrivenPagination_ContinuationToken_requestHeade
511
512
  kind: "MockApiDefinition",
512
513
  },
513
514
  ]);
515
+
516
+ const XmlContTokenFirstPage = `
517
+ <PetListResult>
518
+ <Pets>
519
+ <Pet>
520
+ <Id>1</Id>
521
+ <Name>dog</Name>
522
+ </Pet>
523
+ <Pet>
524
+ <Id>2</Id>
525
+ <Name>cat</Name>
526
+ </Pet>
527
+ </Pets>
528
+ <NextMarker>page2</NextMarker>
529
+ </PetListResult>
530
+ `;
531
+
532
+ const XmlContTokenSecondPage = `
533
+ <PetListResult>
534
+ <Pets>
535
+ <Pet>
536
+ <Id>3</Id>
537
+ <Name>bird</Name>
538
+ </Pet>
539
+ <Pet>
540
+ <Id>4</Id>
541
+ <Name>fish</Name>
542
+ </Pet>
543
+ </Pets>
544
+ </PetListResult>
545
+ `;
546
+
547
+ Scenarios.Payload_Pageable_XmlPagination_listWithContinuation = passOnSuccess([
548
+ {
549
+ uri: "/payload/pageable/xml/list-with-continuation",
550
+ method: "get",
551
+ request: {},
552
+ response: {
553
+ status: 200,
554
+ body: xml(XmlContTokenFirstPage),
555
+ headers: {
556
+ "content-type": "application/xml",
557
+ },
558
+ },
559
+ handler: (req: MockRequest) => {
560
+ const marker = req.query?.marker;
561
+
562
+ switch (marker) {
563
+ case undefined:
564
+ return {
565
+ status: 200,
566
+ body: xml(XmlContTokenFirstPage),
567
+ headers: {
568
+ "content-type": "application/xml",
569
+ },
570
+ };
571
+ case "page2":
572
+ return {
573
+ status: 200,
574
+ body: xml(XmlContTokenSecondPage),
575
+ headers: {
576
+ "content-type": "application/xml",
577
+ },
578
+ };
579
+ default:
580
+ throw new ValidationError("Unsupported marker", `"undefined" | "page2"`, marker);
581
+ }
582
+ },
583
+ kind: "MockApiDefinition",
584
+ },
585
+ {
586
+ uri: "/payload/pageable/xml/list-with-continuation",
587
+ method: "get",
588
+ request: { query: { marker: "page2" } },
589
+ response: {
590
+ status: 200,
591
+ body: xml(XmlContTokenSecondPage),
592
+ headers: {
593
+ "content-type": "application/xml",
594
+ },
595
+ },
596
+ handler: (req: MockRequest) => {
597
+ const marker = req.query?.marker;
598
+
599
+ switch (marker) {
600
+ case undefined:
601
+ return {
602
+ status: 200,
603
+ body: xml(XmlContTokenFirstPage),
604
+ headers: {
605
+ "content-type": "application/xml",
606
+ },
607
+ };
608
+ case "page2":
609
+ return {
610
+ status: 200,
611
+ body: xml(XmlContTokenSecondPage),
612
+ headers: {
613
+ "content-type": "application/xml",
614
+ },
615
+ };
616
+ default:
617
+ throw new ValidationError("Unsupported marker", `"undefined" | "page2"`, marker);
618
+ }
619
+ },
620
+ kind: "MockApiDefinition",
621
+ },
622
+ ]);
623
+
624
+ const xmlNextLinkFirstPage = (baseUrl: string) => `
625
+ <PetListResult>
626
+ <Pets>
627
+ <Pet>
628
+ <Id>1</Id>
629
+ <Name>dog</Name>
630
+ </Pet>
631
+ <Pet>
632
+ <Id>2</Id>
633
+ <Name>cat</Name>
634
+ </Pet>
635
+ </Pets>
636
+ <NextLink>${baseUrl}/payload/pageable/xml/list-with-next-link/nextPage</NextLink>
637
+ </PetListResult>
638
+ `;
639
+
640
+ const XmlNextLinkSecondPage = `
641
+ <PetListResult>
642
+ <Pets>
643
+ <Pet>
644
+ <Id>3</Id>
645
+ <Name>bird</Name>
646
+ </Pet>
647
+ <Pet>
648
+ <Id>4</Id>
649
+ <Name>fish</Name>
650
+ </Pet>
651
+ </Pets>
652
+ </PetListResult>
653
+ `;
654
+
655
+ Scenarios.Payload_Pageable_XmlPagination_listWithNextLink = passOnSuccess([
656
+ {
657
+ uri: "/payload/pageable/xml/list-with-next-link",
658
+ method: "get",
659
+ request: {},
660
+ response: {
661
+ status: 200,
662
+ body: xml(xmlNextLinkFirstPage("PLACEHOLDER_BASE_URL")),
663
+ headers: {
664
+ "content-type": "application/xml",
665
+ },
666
+ },
667
+ handler: (req: MockRequest) => {
668
+ return {
669
+ status: 200,
670
+ body: xml(xmlNextLinkFirstPage(req.baseUrl)),
671
+ headers: {
672
+ "content-type": "application/xml",
673
+ },
674
+ };
675
+ },
676
+ kind: "MockApiDefinition",
677
+ },
678
+ {
679
+ uri: "/payload/pageable/xml/list-with-next-link/nextPage",
680
+ method: "get",
681
+ request: {},
682
+ response: {
683
+ status: 200,
684
+ body: xml(XmlNextLinkSecondPage),
685
+ headers: {
686
+ "content-type": "application/xml",
687
+ },
688
+ },
689
+ kind: "MockApiDefinition",
690
+ },
691
+ ]);