@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.
- package/CHANGELOG.md +238 -0
- package/README.md +11 -3
- package/dist/specs/documentation/mockapi.d.ts.map +1 -0
- package/dist/specs/documentation/mockapi.js +38 -0
- package/dist/specs/documentation/mockapi.js.map +1 -0
- package/dist/specs/encode/array/mockapi.d.ts +3 -0
- package/dist/specs/encode/array/mockapi.d.ts.map +1 -0
- package/dist/specs/encode/array/mockapi.js +25 -0
- package/dist/specs/encode/array/mockapi.js.map +1 -0
- package/dist/specs/encode/bytes/mockapi.js +16 -24
- package/dist/specs/encode/bytes/mockapi.js.map +1 -1
- package/dist/specs/encode/datetime/mockapi.js +2 -2
- package/dist/specs/encode/datetime/mockapi.js.map +1 -1
- package/dist/specs/encode/duration/mockapi.js +74 -2
- package/dist/specs/encode/duration/mockapi.js.map +1 -1
- package/dist/specs/encode/numeric/mockapi.js +2 -2
- package/dist/specs/encode/numeric/mockapi.js.map +1 -1
- package/dist/specs/helper.d.ts +2 -2
- package/dist/specs/helper.d.ts.map +1 -1
- package/dist/specs/parameters/basic/mockapi.d.ts.map +1 -1
- package/dist/specs/parameters/basic/mockapi.js +3 -3
- package/dist/specs/parameters/basic/mockapi.js.map +1 -1
- package/dist/specs/parameters/body-optionality/mockapi.d.ts.map +1 -1
- package/dist/specs/parameters/body-optionality/mockapi.js +14 -4
- package/dist/specs/parameters/body-optionality/mockapi.js.map +1 -1
- package/dist/specs/parameters/collection-format/mockapi.js +4 -15
- package/dist/specs/parameters/collection-format/mockapi.js.map +1 -1
- package/dist/specs/parameters/path/mockapi.d.ts +3 -0
- package/dist/specs/parameters/path/mockapi.d.ts.map +1 -0
- package/dist/specs/parameters/path/mockapi.js +29 -0
- package/dist/specs/parameters/path/mockapi.js.map +1 -0
- package/dist/specs/parameters/spread/mockapi.d.ts.map +1 -1
- package/dist/specs/parameters/spread/mockapi.js +19 -19
- package/dist/specs/parameters/spread/mockapi.js.map +1 -1
- package/dist/specs/payload/json-merge-patch/mockapi.js +4 -4
- package/dist/specs/payload/json-merge-patch/mockapi.js.map +1 -1
- package/dist/specs/payload/media-type/mockapi.js +2 -2
- package/dist/specs/payload/media-type/mockapi.js.map +1 -1
- package/dist/specs/payload/multipart/mockapi.d.ts.map +1 -1
- package/dist/specs/payload/multipart/mockapi.js +42 -60
- package/dist/specs/payload/multipart/mockapi.js.map +1 -1
- package/dist/specs/payload/pageable/mockapi.d.ts.map +1 -1
- package/dist/specs/payload/pageable/mockapi.js +425 -18
- package/dist/specs/payload/pageable/mockapi.js.map +1 -1
- package/dist/specs/payload/xml/mockapi.js +1 -4
- package/dist/specs/payload/xml/mockapi.js.map +1 -1
- package/dist/specs/response/status-code-range/mockapi.d.ts +3 -0
- package/dist/specs/response/status-code-range/mockapi.d.ts.map +1 -0
- package/dist/specs/response/status-code-range/mockapi.js +29 -0
- package/dist/specs/response/status-code-range/mockapi.js.map +1 -0
- package/dist/specs/routes/mockapi.js +25 -25
- package/dist/specs/routes/mockapi.js.map +1 -1
- package/dist/specs/serialization/encoded-name/json/mockapi.js +1 -1
- package/dist/specs/serialization/encoded-name/json/mockapi.js.map +1 -1
- package/dist/specs/server/versions/not-versioned/mockapi.js +1 -1
- package/dist/specs/server/versions/not-versioned/mockapi.js.map +1 -1
- package/dist/specs/server/versions/versioned/mockapi.js +8 -12
- package/dist/specs/server/versions/versioned/mockapi.js.map +1 -1
- package/dist/specs/special-words/mockapi.d.ts.map +1 -1
- package/dist/specs/special-words/mockapi.js +28 -6
- package/dist/specs/special-words/mockapi.js.map +1 -1
- package/dist/specs/streaming/jsonl/mockapi.d.ts +3 -0
- package/dist/specs/streaming/jsonl/mockapi.d.ts.map +1 -0
- package/dist/specs/streaming/jsonl/mockapi.js +30 -0
- package/dist/specs/streaming/jsonl/mockapi.js.map +1 -0
- package/dist/specs/type/array/mockapi.js +1 -1
- package/dist/specs/type/array/mockapi.js.map +1 -1
- package/dist/specs/type/dictionary/mockapi.js +1 -1
- package/dist/specs/type/dictionary/mockapi.js.map +1 -1
- package/dist/specs/type/enum/extensible/mockapi.js +1 -1
- package/dist/specs/type/enum/extensible/mockapi.js.map +1 -1
- package/dist/specs/type/enum/fixed/mockapi.js +2 -2
- package/dist/specs/type/enum/fixed/mockapi.js.map +1 -1
- package/dist/specs/type/model/empty/mockapi.js +2 -2
- package/dist/specs/type/model/empty/mockapi.js.map +1 -1
- package/dist/specs/type/model/inheritance/enum-discriminator/mockapi.js +1 -1
- package/dist/specs/type/model/inheritance/enum-discriminator/mockapi.js.map +1 -1
- package/dist/specs/type/model/inheritance/nested-discriminator/mockapi.js +2 -2
- package/dist/specs/type/model/inheritance/nested-discriminator/mockapi.js.map +1 -1
- package/dist/specs/type/model/inheritance/not-discriminated/mockapi.js +2 -2
- package/dist/specs/type/model/inheritance/not-discriminated/mockapi.js.map +1 -1
- package/dist/specs/type/model/inheritance/recursive/mockapi.js +1 -1
- package/dist/specs/type/model/inheritance/recursive/mockapi.js.map +1 -1
- package/dist/specs/type/model/inheritance/single-discriminator/mockapi.js +2 -2
- package/dist/specs/type/model/inheritance/single-discriminator/mockapi.js.map +1 -1
- package/dist/specs/type/model/usage/mockapi.js +4 -4
- package/dist/specs/type/model/usage/mockapi.js.map +1 -1
- package/dist/specs/type/model/visibility/mockapi.js +9 -10
- package/dist/specs/type/model/visibility/mockapi.js.map +1 -1
- package/dist/specs/type/property/additional-properties/mockapi.js +9 -6
- package/dist/specs/type/property/additional-properties/mockapi.js.map +1 -1
- package/dist/specs/type/property/nullable/mockapi.js +2 -6
- package/dist/specs/type/property/nullable/mockapi.js.map +1 -1
- package/dist/specs/type/property/optionality/mockapi.js +1 -1
- package/dist/specs/type/property/optionality/mockapi.js.map +1 -1
- package/dist/specs/type/property/value-types/mockapi.js +3 -3
- package/dist/specs/type/property/value-types/mockapi.js.map +1 -1
- package/dist/specs/type/scalar/mockapi.js +9 -9
- package/dist/specs/type/scalar/mockapi.js.map +1 -1
- package/dist/specs/type/union/discriminated/mockapi.d.ts +3 -0
- package/dist/specs/type/union/discriminated/mockapi.d.ts.map +1 -0
- package/dist/specs/type/union/discriminated/mockapi.js +212 -0
- package/dist/specs/type/union/discriminated/mockapi.js.map +1 -0
- package/dist/specs/type/union/mockapi.js +2 -2
- package/dist/specs/type/union/mockapi.js.map +1 -1
- package/dist/specs/versioning/added/mockapi.js +6 -6
- package/dist/specs/versioning/added/mockapi.js.map +1 -1
- package/dist/specs/versioning/madeOptional/mockapi.js +2 -2
- package/dist/specs/versioning/madeOptional/mockapi.js.map +1 -1
- package/dist/specs/versioning/removed/mockapi.js +46 -2
- package/dist/specs/versioning/removed/mockapi.js.map +1 -1
- package/dist/specs/versioning/renamedFrom/mockapi.js +5 -5
- package/dist/specs/versioning/renamedFrom/mockapi.js.map +1 -1
- package/dist/specs/versioning/returnTypeChangedFrom/mockapi.js +1 -1
- package/dist/specs/versioning/returnTypeChangedFrom/mockapi.js.map +1 -1
- package/dist/specs/versioning/typeChangedFrom/mockapi.js +3 -3
- package/dist/specs/versioning/typeChangedFrom/mockapi.js.map +1 -1
- package/package.json +32 -19
- package/smoke/petstore/main.tsp +96 -0
- package/smoke/todoapp/main.tsp +293 -0
- package/spec-summary.md +1289 -265
- package/specs/documentation/main.tsp +158 -0
- package/specs/documentation/mockapi.ts +57 -0
- package/specs/encode/array/main.tsp +112 -0
- package/specs/encode/array/mockapi.ts +43 -0
- package/specs/encode/bytes/main.tsp +29 -20
- package/specs/encode/bytes/mockapi.ts +13 -31
- package/specs/encode/datetime/main.tsp +2 -7
- package/specs/encode/datetime/mockapi.ts +2 -2
- package/specs/encode/duration/main.tsp +420 -7
- package/specs/encode/duration/mockapi.ts +174 -2
- package/specs/encode/numeric/mockapi.ts +2 -2
- package/specs/parameters/basic/mockapi.ts +3 -3
- package/specs/parameters/body-optionality/main.tsp +2 -0
- package/specs/parameters/body-optionality/mockapi.ts +24 -4
- package/specs/parameters/collection-format/main.tsp +5 -25
- package/specs/parameters/collection-format/mockapi.ts +4 -16
- package/specs/parameters/path/main.tsp +48 -0
- package/specs/parameters/path/mockapi.ts +34 -0
- package/specs/parameters/spread/mockapi.ts +19 -19
- package/specs/payload/json-merge-patch/main.tsp +2 -2
- package/specs/payload/json-merge-patch/mockapi.ts +4 -4
- package/specs/payload/media-type/mockapi.ts +2 -2
- package/specs/payload/multipart/main.tsp +34 -32
- package/specs/payload/multipart/mockapi.ts +42 -59
- package/specs/payload/pageable/main.tsp +462 -7
- package/specs/payload/pageable/mockapi.ts +478 -18
- package/specs/payload/xml/mockapi.ts +1 -4
- package/specs/response/status-code-range/main.tsp +82 -0
- package/specs/response/status-code-range/mockapi.ts +31 -0
- package/specs/routes/main.tsp +48 -48
- package/specs/routes/mockapi.ts +25 -25
- package/specs/serialization/encoded-name/json/main.tsp +1 -1
- package/specs/serialization/encoded-name/json/mockapi.ts +1 -1
- package/specs/server/endpoint/not-defined/main.tsp +1 -3
- package/specs/server/path/multiple/main.tsp +3 -5
- package/specs/server/versions/not-versioned/mockapi.ts +1 -1
- package/specs/server/versions/versioned/main.tsp +1 -1
- package/specs/server/versions/versioned/mockapi.ts +6 -12
- package/specs/special-headers/conditional-request/main.tsp +1 -1
- package/specs/special-headers/repeatability/main.tsp +2 -2
- package/specs/special-words/main.tsp +44 -6
- package/specs/special-words/mockapi.ts +29 -6
- package/specs/streaming/jsonl/main.tsp +33 -0
- package/specs/streaming/jsonl/mockapi.ts +32 -0
- package/specs/type/array/mockapi.ts +1 -1
- package/specs/type/dictionary/mockapi.ts +1 -1
- package/specs/type/enum/extensible/main.tsp +18 -2
- package/specs/type/enum/extensible/mockapi.ts +1 -1
- package/specs/type/enum/fixed/main.tsp +15 -3
- package/specs/type/enum/fixed/mockapi.ts +2 -2
- package/specs/type/model/empty/mockapi.ts +2 -2
- package/specs/type/model/inheritance/enum-discriminator/mockapi.ts +1 -1
- package/specs/type/model/inheritance/nested-discriminator/mockapi.ts +2 -2
- package/specs/type/model/inheritance/not-discriminated/mockapi.ts +2 -2
- package/specs/type/model/inheritance/recursive/mockapi.ts +1 -1
- package/specs/type/model/inheritance/single-discriminator/mockapi.ts +2 -2
- package/specs/type/model/usage/mockapi.ts +4 -4
- package/specs/type/model/visibility/main.tsp +15 -23
- package/specs/type/model/visibility/mockapi.ts +9 -10
- package/specs/type/property/additional-properties/main.tsp +17 -17
- package/specs/type/property/additional-properties/mockapi.ts +10 -10
- package/specs/type/property/nullable/mockapi.ts +7 -8
- package/specs/type/property/optionality/mockapi.ts +1 -1
- package/specs/type/property/value-types/mockapi.ts +3 -3
- package/specs/type/scalar/main.tsp +58 -9
- package/specs/type/scalar/mockapi.ts +9 -9
- package/specs/type/union/discriminated/main.tsp +251 -0
- package/specs/type/union/discriminated/mockapi.ts +230 -0
- package/specs/type/union/mockapi.ts +2 -2
- package/specs/versioning/added/mockapi.ts +6 -6
- package/specs/versioning/madeOptional/mockapi.ts +2 -2
- package/specs/versioning/removed/main.tsp +65 -3
- package/specs/versioning/removed/mockapi.ts +49 -2
- package/specs/versioning/renamedFrom/mockapi.ts +5 -5
- package/specs/versioning/returnTypeChangedFrom/main.tsp +17 -2
- package/specs/versioning/returnTypeChangedFrom/mockapi.ts +1 -1
- package/specs/versioning/typeChangedFrom/mockapi.ts +3 -3
- package/temp/.tsbuildinfo +1 -1
- package/tspconfig.yaml +0 -2
- package/dist/specs/type/model/templated/mockapi.d.ts.map +0 -1
- package/dist/specs/type/model/templated/mockapi.js +0 -63
- package/dist/specs/type/model/templated/mockapi.js.map +0 -1
- package/specs/type/model/templated/main.tsp +0 -130
- package/specs/type/model/templated/mockapi.ts +0 -66
- /package/dist/specs/{type/model/templated → documentation}/mockapi.d.ts +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
|
|
1
|
+
import { json, passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
|
|
2
2
|
|
|
3
3
|
export const Scenarios: Record<string, ScenarioMockApi> = {};
|
|
4
4
|
function createServerTests(uri: string) {
|
|
@@ -6,9 +6,9 @@ function createServerTests(uri: string) {
|
|
|
6
6
|
uri,
|
|
7
7
|
method: "put",
|
|
8
8
|
request: {
|
|
9
|
-
body: {
|
|
9
|
+
body: json({
|
|
10
10
|
name: "foo",
|
|
11
|
-
},
|
|
11
|
+
}),
|
|
12
12
|
},
|
|
13
13
|
response: {
|
|
14
14
|
status: 204,
|
|
@@ -33,8 +33,10 @@ op requiredExplicit(@body body: BodyModel): NoContentResponse;
|
|
|
33
33
|
```json
|
|
34
34
|
{ "name": "foo" }
|
|
35
35
|
```
|
|
36
|
+
Expected Content-Type header: application/json
|
|
36
37
|
|
|
37
38
|
Expected no request body for `omit`
|
|
39
|
+
Expected Content-Type header: must NOT be present
|
|
38
40
|
""")
|
|
39
41
|
@route("/optional-explicit")
|
|
40
42
|
namespace OptionalExplicit {
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
json,
|
|
3
|
+
MockRequest,
|
|
4
|
+
passOnSuccess,
|
|
5
|
+
ScenarioMockApi,
|
|
6
|
+
ValidationError,
|
|
7
|
+
} from "@typespec/spec-api";
|
|
2
8
|
|
|
3
9
|
export const Scenarios: Record<string, ScenarioMockApi> = {};
|
|
4
10
|
function createServerTests(uri: string, data: any) {
|
|
@@ -6,7 +12,7 @@ function createServerTests(uri: string, data: any) {
|
|
|
6
12
|
uri,
|
|
7
13
|
method: "post",
|
|
8
14
|
request: {
|
|
9
|
-
body: data,
|
|
15
|
+
body: json(data),
|
|
10
16
|
},
|
|
11
17
|
response: {
|
|
12
18
|
status: 204,
|
|
@@ -27,13 +33,18 @@ Scenarios.Parameters_BodyOptionality_OptionalExplicit = passOnSuccess([
|
|
|
27
33
|
uri: "/parameters/body-optionality/optional-explicit/set",
|
|
28
34
|
method: "post",
|
|
29
35
|
request: {
|
|
30
|
-
body: {
|
|
36
|
+
body: json({
|
|
31
37
|
name: "foo",
|
|
32
|
-
},
|
|
38
|
+
}),
|
|
33
39
|
},
|
|
34
40
|
response: {
|
|
35
41
|
status: 204,
|
|
36
42
|
},
|
|
43
|
+
handler: (req: MockRequest) => {
|
|
44
|
+
// Validate that Content-Type header is present when body is provided
|
|
45
|
+
req.expect.containsHeader("content-type", "application/json");
|
|
46
|
+
return { status: 204 };
|
|
47
|
+
},
|
|
37
48
|
kind: "MockApiDefinition",
|
|
38
49
|
},
|
|
39
50
|
{
|
|
@@ -45,6 +56,15 @@ Scenarios.Parameters_BodyOptionality_OptionalExplicit = passOnSuccess([
|
|
|
45
56
|
},
|
|
46
57
|
handler: (req: MockRequest) => {
|
|
47
58
|
req.expect.rawBodyEquals(undefined);
|
|
59
|
+
// Validate that Content-Type header is NOT present when body is omitted
|
|
60
|
+
const contentTypeHeader = req.headers["content-type"];
|
|
61
|
+
if (contentTypeHeader !== undefined) {
|
|
62
|
+
throw new ValidationError(
|
|
63
|
+
"Content-Type header must NOT be present when body is omitted",
|
|
64
|
+
undefined,
|
|
65
|
+
contentTypeHeader,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
48
68
|
return { status: 204 };
|
|
49
69
|
},
|
|
50
70
|
kind: "MockApiDefinition",
|
|
@@ -27,25 +27,9 @@ namespace Query {
|
|
|
27
27
|
""")
|
|
28
28
|
@route("/ssv")
|
|
29
29
|
op ssv(
|
|
30
|
-
#suppress "deprecated" "Deprecated in next release"
|
|
31
30
|
@doc("Possible values for colors are [blue,red,green]")
|
|
32
|
-
@query
|
|
33
|
-
|
|
34
|
-
})
|
|
35
|
-
colors: string[],
|
|
36
|
-
): NoContentResponse;
|
|
37
|
-
|
|
38
|
-
@scenario
|
|
39
|
-
@scenarioDoc("""
|
|
40
|
-
This test is testing sending a tsv collection format array query parameters
|
|
41
|
-
""")
|
|
42
|
-
@route("/tsv")
|
|
43
|
-
op tsv(
|
|
44
|
-
#suppress "deprecated" "Deprecated in next release"
|
|
45
|
-
@doc("Possible values for colors are [blue,red,green]")
|
|
46
|
-
@query({
|
|
47
|
-
format: "tsv",
|
|
48
|
-
})
|
|
31
|
+
@query
|
|
32
|
+
@encode(ArrayEncoding.spaceDelimited)
|
|
49
33
|
colors: string[],
|
|
50
34
|
): NoContentResponse;
|
|
51
35
|
|
|
@@ -55,11 +39,9 @@ namespace Query {
|
|
|
55
39
|
""")
|
|
56
40
|
@route("/pipes")
|
|
57
41
|
op pipes(
|
|
58
|
-
#suppress "deprecated" "Deprecated in next release"
|
|
59
42
|
@doc("Possible values for colors are [blue,red,green]")
|
|
60
|
-
@query
|
|
61
|
-
|
|
62
|
-
})
|
|
43
|
+
@query
|
|
44
|
+
@encode(ArrayEncoding.pipeDelimited)
|
|
63
45
|
colors: string[],
|
|
64
46
|
): NoContentResponse;
|
|
65
47
|
|
|
@@ -84,9 +66,7 @@ namespace Header {
|
|
|
84
66
|
@route("/csv")
|
|
85
67
|
op csv(
|
|
86
68
|
@doc("Possible values for colors are [blue,red,green]")
|
|
87
|
-
@header
|
|
88
|
-
format: "csv",
|
|
89
|
-
})
|
|
69
|
+
@header
|
|
90
70
|
colors: string[],
|
|
91
71
|
): NoContentResponse;
|
|
92
72
|
}
|
|
@@ -8,7 +8,7 @@ Scenarios.Parameters_CollectionFormat_Query_multi = passOnSuccess({
|
|
|
8
8
|
uri: `/parameters/collection-format/query/multi`,
|
|
9
9
|
method: "get",
|
|
10
10
|
request: {
|
|
11
|
-
|
|
11
|
+
query: { colors: ["blue", "red", "green"] },
|
|
12
12
|
},
|
|
13
13
|
response: {
|
|
14
14
|
status: 204,
|
|
@@ -26,7 +26,7 @@ Scenarios.Parameters_CollectionFormat_Query_csv = passOnSuccess({
|
|
|
26
26
|
uri: `/parameters/collection-format/query/csv`,
|
|
27
27
|
method: "get",
|
|
28
28
|
request: {
|
|
29
|
-
|
|
29
|
+
query: { colors: colors.join(",") },
|
|
30
30
|
},
|
|
31
31
|
response: {
|
|
32
32
|
status: 204,
|
|
@@ -38,19 +38,7 @@ Scenarios.Parameters_CollectionFormat_Query_ssv = passOnSuccess({
|
|
|
38
38
|
uri: `/parameters/collection-format/query/ssv`,
|
|
39
39
|
method: "get",
|
|
40
40
|
request: {
|
|
41
|
-
|
|
42
|
-
},
|
|
43
|
-
response: {
|
|
44
|
-
status: 204,
|
|
45
|
-
},
|
|
46
|
-
kind: "MockApiDefinition",
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
Scenarios.Parameters_CollectionFormat_Query_tsv = passOnSuccess({
|
|
50
|
-
uri: `/parameters/collection-format/query/tsv`,
|
|
51
|
-
method: "get",
|
|
52
|
-
request: {
|
|
53
|
-
params: { colors: colors.join("\t") },
|
|
41
|
+
query: { colors: colors.join(" ") },
|
|
54
42
|
},
|
|
55
43
|
response: {
|
|
56
44
|
status: 204,
|
|
@@ -62,7 +50,7 @@ Scenarios.Parameters_CollectionFormat_Query_pipes = passOnSuccess({
|
|
|
62
50
|
uri: `/parameters/collection-format/query/pipes`,
|
|
63
51
|
method: "get",
|
|
64
52
|
request: {
|
|
65
|
-
|
|
53
|
+
query: { colors: colors.join("|") },
|
|
66
54
|
},
|
|
67
55
|
response: {
|
|
68
56
|
status: 204,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import "@typespec/http";
|
|
2
|
+
import "@typespec/spector";
|
|
3
|
+
|
|
4
|
+
using Http;
|
|
5
|
+
using Spector;
|
|
6
|
+
|
|
7
|
+
@doc("Test for path parameters cases.")
|
|
8
|
+
@scenarioService("/parameters/path")
|
|
9
|
+
namespace Parameters.Path;
|
|
10
|
+
|
|
11
|
+
@scenario
|
|
12
|
+
@scenarioDoc("""
|
|
13
|
+
Test case for normal path parameter.
|
|
14
|
+
|
|
15
|
+
Should generate an operation like below:
|
|
16
|
+
```
|
|
17
|
+
normal(name: string)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Expected request path:
|
|
21
|
+
```
|
|
22
|
+
/normal/foo
|
|
23
|
+
```
|
|
24
|
+
""")
|
|
25
|
+
@route("/normal/{name}")
|
|
26
|
+
op normal(@path name: string): NoContentResponse;
|
|
27
|
+
|
|
28
|
+
@scenario
|
|
29
|
+
@scenarioDoc("""
|
|
30
|
+
Test case for optional path parameter.
|
|
31
|
+
|
|
32
|
+
Should generate an operation like below:
|
|
33
|
+
```
|
|
34
|
+
optional(name?: string)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Expected two request:
|
|
38
|
+
First request path:
|
|
39
|
+
```
|
|
40
|
+
/optional
|
|
41
|
+
```
|
|
42
|
+
Second request path:
|
|
43
|
+
```
|
|
44
|
+
/optional/foo
|
|
45
|
+
```
|
|
46
|
+
""")
|
|
47
|
+
@route("/optional{/name}")
|
|
48
|
+
op optional(@path name?: string): NoContentResponse;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
|
|
2
|
+
|
|
3
|
+
export const Scenarios: Record<string, ScenarioMockApi> = {};
|
|
4
|
+
|
|
5
|
+
Scenarios.Parameters_Path_normal = passOnSuccess({
|
|
6
|
+
uri: "/parameters/path/normal/foo",
|
|
7
|
+
method: "get",
|
|
8
|
+
|
|
9
|
+
response: {
|
|
10
|
+
status: 204,
|
|
11
|
+
},
|
|
12
|
+
kind: "MockApiDefinition",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
Scenarios.Parameters_Path_optional = passOnSuccess([
|
|
16
|
+
{
|
|
17
|
+
uri: "/parameters/path/optional",
|
|
18
|
+
method: "get",
|
|
19
|
+
|
|
20
|
+
response: {
|
|
21
|
+
status: 204,
|
|
22
|
+
},
|
|
23
|
+
kind: "MockApiDefinition",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
uri: "/parameters/path/optional/foo",
|
|
27
|
+
method: "get",
|
|
28
|
+
|
|
29
|
+
response: {
|
|
30
|
+
status: 204,
|
|
31
|
+
},
|
|
32
|
+
kind: "MockApiDefinition",
|
|
33
|
+
},
|
|
34
|
+
]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
|
|
1
|
+
import { json, passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
|
|
2
2
|
|
|
3
3
|
export const Scenarios: Record<string, ScenarioMockApi> = {};
|
|
4
4
|
|
|
@@ -6,9 +6,9 @@ Scenarios.Parameters_Spread_Model_spreadAsRequestBody = passOnSuccess({
|
|
|
6
6
|
uri: `/parameters/spread/model/request-body`,
|
|
7
7
|
method: "put",
|
|
8
8
|
request: {
|
|
9
|
-
body: {
|
|
9
|
+
body: json({
|
|
10
10
|
name: "foo",
|
|
11
|
-
},
|
|
11
|
+
}),
|
|
12
12
|
},
|
|
13
13
|
response: {
|
|
14
14
|
status: 204,
|
|
@@ -20,9 +20,9 @@ Scenarios.Parameters_Spread_Model_spreadCompositeRequestOnlyWithBody = passOnSuc
|
|
|
20
20
|
uri: `/parameters/spread/model/composite-request-only-with-body`,
|
|
21
21
|
method: "put",
|
|
22
22
|
request: {
|
|
23
|
-
body: {
|
|
23
|
+
body: json({
|
|
24
24
|
name: "foo",
|
|
25
|
-
},
|
|
25
|
+
}),
|
|
26
26
|
},
|
|
27
27
|
response: {
|
|
28
28
|
status: 204,
|
|
@@ -48,9 +48,9 @@ Scenarios.Parameters_Spread_Model_spreadCompositeRequest = passOnSuccess({
|
|
|
48
48
|
uri: `/parameters/spread/model/composite-request/foo`,
|
|
49
49
|
method: "put",
|
|
50
50
|
request: {
|
|
51
|
-
body: {
|
|
51
|
+
body: json({
|
|
52
52
|
name: "foo",
|
|
53
|
-
},
|
|
53
|
+
}),
|
|
54
54
|
headers: {
|
|
55
55
|
"test-header": "bar",
|
|
56
56
|
},
|
|
@@ -65,9 +65,9 @@ Scenarios.Parameters_Spread_Model_spreadCompositeRequestMix = passOnSuccess({
|
|
|
65
65
|
uri: `/parameters/spread/model/composite-request-mix/foo`,
|
|
66
66
|
method: "put",
|
|
67
67
|
request: {
|
|
68
|
-
body: {
|
|
68
|
+
body: json({
|
|
69
69
|
prop: "foo",
|
|
70
|
-
},
|
|
70
|
+
}),
|
|
71
71
|
headers: {
|
|
72
72
|
"test-header": "bar",
|
|
73
73
|
},
|
|
@@ -82,9 +82,9 @@ Scenarios.Parameters_Spread_Alias_spreadAsRequestBody = passOnSuccess({
|
|
|
82
82
|
uri: `/parameters/spread/alias/request-body`,
|
|
83
83
|
method: "put",
|
|
84
84
|
request: {
|
|
85
|
-
body: {
|
|
85
|
+
body: json({
|
|
86
86
|
name: "foo",
|
|
87
|
-
},
|
|
87
|
+
}),
|
|
88
88
|
},
|
|
89
89
|
response: {
|
|
90
90
|
status: 204,
|
|
@@ -96,9 +96,9 @@ Scenarios.Parameters_Spread_Alias_spreadAsRequestParameter = passOnSuccess({
|
|
|
96
96
|
uri: `/parameters/spread/alias/request-parameter/1`,
|
|
97
97
|
method: "put",
|
|
98
98
|
request: {
|
|
99
|
-
body: {
|
|
99
|
+
body: json({
|
|
100
100
|
name: "foo",
|
|
101
|
-
},
|
|
101
|
+
}),
|
|
102
102
|
headers: {
|
|
103
103
|
"x-ms-test-header": "bar",
|
|
104
104
|
},
|
|
@@ -113,12 +113,12 @@ Scenarios.Parameters_Spread_Alias_spreadWithMultipleParameters = passOnSuccess({
|
|
|
113
113
|
uri: `/parameters/spread/alias/multiple-parameters/1`,
|
|
114
114
|
method: "put",
|
|
115
115
|
request: {
|
|
116
|
-
body: {
|
|
116
|
+
body: json({
|
|
117
117
|
requiredString: "foo",
|
|
118
118
|
optionalInt: 1,
|
|
119
119
|
requiredIntList: [1, 2],
|
|
120
120
|
optionalStringList: ["foo", "bar"],
|
|
121
|
-
},
|
|
121
|
+
}),
|
|
122
122
|
headers: {
|
|
123
123
|
"x-ms-test-header": "bar",
|
|
124
124
|
},
|
|
@@ -133,9 +133,9 @@ Scenarios.Parameters_Spread_Alias_spreadParameterWithInnerModel = passOnSuccess(
|
|
|
133
133
|
uri: `/parameters/spread/alias/inner-model-parameter/1`,
|
|
134
134
|
method: "post",
|
|
135
135
|
request: {
|
|
136
|
-
body: {
|
|
136
|
+
body: json({
|
|
137
137
|
name: "foo",
|
|
138
|
-
},
|
|
138
|
+
}),
|
|
139
139
|
headers: {
|
|
140
140
|
"x-ms-test-header": "bar",
|
|
141
141
|
},
|
|
@@ -150,10 +150,10 @@ Scenarios.Parameters_Spread_Alias_spreadParameterWithInnerAlias = passOnSuccess(
|
|
|
150
150
|
uri: `/parameters/spread/alias/inner-alias-parameter/1`,
|
|
151
151
|
method: "post",
|
|
152
152
|
request: {
|
|
153
|
-
body: {
|
|
153
|
+
body: json({
|
|
154
154
|
name: "foo",
|
|
155
155
|
age: 1,
|
|
156
|
-
},
|
|
156
|
+
}),
|
|
157
157
|
headers: {
|
|
158
158
|
"x-ms-test-header": "bar",
|
|
159
159
|
},
|
|
@@ -58,7 +58,7 @@ model InnerModel {
|
|
|
58
58
|
}
|
|
59
59
|
],
|
|
60
60
|
"intValue": 1,
|
|
61
|
-
"floatValue": 1.
|
|
61
|
+
"floatValue": 1.25,
|
|
62
62
|
"innerModel": {
|
|
63
63
|
"name": "InnerMadge",
|
|
64
64
|
"description": "innerDesc"
|
|
@@ -85,7 +85,7 @@ model InnerModel {
|
|
|
85
85
|
}
|
|
86
86
|
],
|
|
87
87
|
"intValue": 1,
|
|
88
|
-
"floatValue": 1.
|
|
88
|
+
"floatValue": 1.25,
|
|
89
89
|
"innerModel": {
|
|
90
90
|
"name": "InnerMadge",
|
|
91
91
|
"description": "innerDesc"
|
|
@@ -18,7 +18,7 @@ export const expectedCreateBody = {
|
|
|
18
18
|
},
|
|
19
19
|
],
|
|
20
20
|
intValue: 1,
|
|
21
|
-
floatValue: 1.
|
|
21
|
+
floatValue: 1.25,
|
|
22
22
|
innerModel: {
|
|
23
23
|
name: "InnerMadge",
|
|
24
24
|
description: "innerDesc",
|
|
@@ -45,7 +45,7 @@ Scenarios.Payload_JsonMergePatch_createResource = passOnSuccess({
|
|
|
45
45
|
uri: "/json-merge-patch/create/resource",
|
|
46
46
|
method: "put",
|
|
47
47
|
request: {
|
|
48
|
-
body: expectedCreateBody,
|
|
48
|
+
body: json(expectedCreateBody),
|
|
49
49
|
},
|
|
50
50
|
response: {
|
|
51
51
|
status: 200,
|
|
@@ -58,7 +58,7 @@ Scenarios.Payload_JsonMergePatch_updateResource = passOnSuccess({
|
|
|
58
58
|
uri: "/json-merge-patch/update/resource",
|
|
59
59
|
method: "patch",
|
|
60
60
|
request: {
|
|
61
|
-
body: expectedUpdateBody,
|
|
61
|
+
body: json(expectedUpdateBody),
|
|
62
62
|
},
|
|
63
63
|
response: {
|
|
64
64
|
status: 200,
|
|
@@ -78,7 +78,7 @@ Scenarios.Payload_JsonMergePatch_updateOptionalResource = passOnSuccess({
|
|
|
78
78
|
uri: "/json-merge-patch/update/resource/optional",
|
|
79
79
|
method: "patch",
|
|
80
80
|
request: {
|
|
81
|
-
body: expectedUpdateBody,
|
|
81
|
+
body: json(expectedUpdateBody),
|
|
82
82
|
},
|
|
83
83
|
response: {
|
|
84
84
|
status: 200,
|
|
@@ -6,7 +6,7 @@ Scenarios.Payload_MediaType_StringBody_sendAsText = passOnSuccess({
|
|
|
6
6
|
uri: "/payload/media-type/string-body/sendAsText",
|
|
7
7
|
method: "post",
|
|
8
8
|
request: {
|
|
9
|
-
body: "{cat}",
|
|
9
|
+
body: json("{cat}"),
|
|
10
10
|
headers: {
|
|
11
11
|
"Content-Type": "text/plain",
|
|
12
12
|
},
|
|
@@ -36,7 +36,7 @@ Scenarios.Payload_MediaType_StringBody_sendAsJson = passOnSuccess({
|
|
|
36
36
|
uri: "/payload/media-type/string-body/sendAsJson",
|
|
37
37
|
method: "post",
|
|
38
38
|
request: {
|
|
39
|
-
body: "foo",
|
|
39
|
+
body: json("foo"),
|
|
40
40
|
headers: {
|
|
41
41
|
"Content-Type": "application/json",
|
|
42
42
|
},
|
|
@@ -9,8 +9,8 @@ using Spector;
|
|
|
9
9
|
namespace Payload.MultiPart;
|
|
10
10
|
|
|
11
11
|
model MultiPartRequest {
|
|
12
|
-
id: string
|
|
13
|
-
profileImage: bytes
|
|
12
|
+
id: HttpPart<string>;
|
|
13
|
+
profileImage: HttpPart<bytes>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
model Address {
|
|
@@ -52,25 +52,25 @@ model ComplexHttpPartsModelRequest {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
model ComplexPartsRequest {
|
|
55
|
-
id: string
|
|
56
|
-
address: Address
|
|
57
|
-
profileImage: bytes
|
|
58
|
-
pictures: bytes[];
|
|
55
|
+
id: HttpPart<string>;
|
|
56
|
+
address: HttpPart<Address>;
|
|
57
|
+
profileImage: HttpPart<bytes>;
|
|
58
|
+
pictures: HttpPart<bytes>[];
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
model JsonPartRequest {
|
|
62
|
-
address: Address
|
|
63
|
-
profileImage: bytes
|
|
62
|
+
address: HttpPart<Address>;
|
|
63
|
+
profileImage: HttpPart<bytes>;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
model BinaryArrayPartsRequest {
|
|
67
|
-
id: string
|
|
68
|
-
pictures: bytes[];
|
|
67
|
+
id: HttpPart<string>;
|
|
68
|
+
pictures: HttpPart<bytes>[];
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
model MultiBinaryPartsRequest {
|
|
72
|
-
profileImage: bytes
|
|
73
|
-
picture?: bytes
|
|
72
|
+
profileImage: HttpPart<bytes>;
|
|
73
|
+
picture?: HttpPart<bytes>;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
@route("/form-data")
|
|
@@ -79,9 +79,9 @@ namespace FormData {
|
|
|
79
79
|
@scenarioDoc("""
|
|
80
80
|
Expect request (
|
|
81
81
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.4, content-type of file part shall be labeled with
|
|
82
|
-
appropriate media type,
|
|
82
|
+
appropriate media type, server will check it; content-type of other parts is optional, server will ignore it.
|
|
83
83
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.2, filename of file part SHOULD be supplied.
|
|
84
|
-
If there are duplicated filename in same fieldName,
|
|
84
|
+
If there are duplicated filename in same fieldName, server can't parse them all.
|
|
85
85
|
):
|
|
86
86
|
```
|
|
87
87
|
POST /upload HTTP/1.1
|
|
@@ -106,16 +106,16 @@ namespace FormData {
|
|
|
106
106
|
@route("/mixed-parts")
|
|
107
107
|
op basic(
|
|
108
108
|
@header contentType: "multipart/form-data",
|
|
109
|
-
@
|
|
109
|
+
@multipartBody body: MultiPartRequest,
|
|
110
110
|
): NoContentResponse;
|
|
111
111
|
|
|
112
112
|
@scenario
|
|
113
113
|
@scenarioDoc("""
|
|
114
114
|
Expect request (
|
|
115
115
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.4, content-type of file part shall be labeled with
|
|
116
|
-
appropriate media type,
|
|
116
|
+
appropriate media type, server will check it; content-type of other parts is optional, server will ignore it.
|
|
117
117
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.2, filename of file part SHOULD be supplied.
|
|
118
|
-
If there are duplicated filename in same fieldName,
|
|
118
|
+
If there are duplicated filename in same fieldName, server can't parse them all.
|
|
119
119
|
):
|
|
120
120
|
```
|
|
121
121
|
POST /upload HTTP/1.1
|
|
@@ -166,16 +166,16 @@ namespace FormData {
|
|
|
166
166
|
@route("/complex-parts")
|
|
167
167
|
op fileArrayAndBasic(
|
|
168
168
|
@header contentType: "multipart/form-data",
|
|
169
|
-
@
|
|
169
|
+
@multipartBody body: ComplexPartsRequest,
|
|
170
170
|
): NoContentResponse;
|
|
171
171
|
|
|
172
172
|
@scenario
|
|
173
173
|
@scenarioDoc("""
|
|
174
174
|
Expect request (
|
|
175
175
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.4, content-type of file part shall be labeled with
|
|
176
|
-
appropriate media type,
|
|
176
|
+
appropriate media type, server will check it; content-type of other parts is optional, server will ignore it.
|
|
177
177
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.2, filename of file part SHOULD be supplied.
|
|
178
|
-
If there are duplicated filename in same fieldName,
|
|
178
|
+
If there are duplicated filename in same fieldName, server can't parse them all.
|
|
179
179
|
):
|
|
180
180
|
```
|
|
181
181
|
POST /upload HTTP/1.1
|
|
@@ -202,16 +202,16 @@ namespace FormData {
|
|
|
202
202
|
@route("/json-part")
|
|
203
203
|
op jsonPart(
|
|
204
204
|
@header contentType: "multipart/form-data",
|
|
205
|
-
@
|
|
205
|
+
@multipartBody body: JsonPartRequest,
|
|
206
206
|
): NoContentResponse;
|
|
207
207
|
|
|
208
208
|
@scenario
|
|
209
209
|
@scenarioDoc("""
|
|
210
210
|
Expect request (
|
|
211
211
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.4, content-type of file part shall be labeled with
|
|
212
|
-
appropriate media type,
|
|
212
|
+
appropriate media type, server will check it; content-type of other parts is optional, server will ignore it.
|
|
213
213
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.2, filename of file part SHOULD be supplied.
|
|
214
|
-
If there are duplicated filename in same fieldName,
|
|
214
|
+
If there are duplicated filename in same fieldName, server can't parse them all.
|
|
215
215
|
):
|
|
216
216
|
```
|
|
217
217
|
POST /upload HTTP/1.1
|
|
@@ -241,16 +241,16 @@ namespace FormData {
|
|
|
241
241
|
@route("/binary-array-parts")
|
|
242
242
|
op binaryArrayParts(
|
|
243
243
|
@header contentType: "multipart/form-data",
|
|
244
|
-
@
|
|
244
|
+
@multipartBody body: BinaryArrayPartsRequest,
|
|
245
245
|
): NoContentResponse;
|
|
246
246
|
|
|
247
247
|
@scenario
|
|
248
248
|
@scenarioDoc("""
|
|
249
249
|
Please send request twice, first time with only profileImage, second time with both profileImage and picture(
|
|
250
250
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.4, content-type of file part shall be labeled with
|
|
251
|
-
appropriate media type,
|
|
251
|
+
appropriate media type, server will check it; content-type of other parts is optional, server will ignore it.
|
|
252
252
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.2, filename of file part SHOULD be supplied.
|
|
253
|
-
If there are duplicated filename in same fieldName,
|
|
253
|
+
If there are duplicated filename in same fieldName, server can't parse them all.
|
|
254
254
|
):
|
|
255
255
|
```
|
|
256
256
|
POST /upload HTTP/1.1
|
|
@@ -275,7 +275,7 @@ namespace FormData {
|
|
|
275
275
|
@route("/multi-binary-parts")
|
|
276
276
|
op multiBinaryParts(
|
|
277
277
|
@header contentType: "multipart/form-data",
|
|
278
|
-
@
|
|
278
|
+
@multipartBody body: MultiBinaryPartsRequest,
|
|
279
279
|
): NoContentResponse;
|
|
280
280
|
|
|
281
281
|
@scenario
|
|
@@ -304,16 +304,16 @@ namespace FormData {
|
|
|
304
304
|
@route("/check-filename-and-content-type")
|
|
305
305
|
op checkFileNameAndContentType(
|
|
306
306
|
@header contentType: "multipart/form-data",
|
|
307
|
-
@
|
|
307
|
+
@multipartBody body: MultiPartRequest,
|
|
308
308
|
): NoContentResponse;
|
|
309
309
|
|
|
310
310
|
@scenario
|
|
311
311
|
@scenarioDoc("""
|
|
312
312
|
Expect request (
|
|
313
313
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.4, content-type of file part shall be labeled with
|
|
314
|
-
appropriate media type,
|
|
314
|
+
appropriate media type, server will check it; content-type of other parts is optional, server will ignore it.
|
|
315
315
|
- according to https://datatracker.ietf.org/doc/html/rfc7578#section-4.2, filename of file part SHOULD be supplied.
|
|
316
|
-
If there are duplicated filename in same filedName,
|
|
316
|
+
If there are duplicated filename in same filedName, server can't parse them all.
|
|
317
317
|
):
|
|
318
318
|
```
|
|
319
319
|
POST /multipart/form-data/anonymous-model HTTP/1.1
|
|
@@ -333,7 +333,9 @@ namespace FormData {
|
|
|
333
333
|
@route("/anonymous-model")
|
|
334
334
|
op anonymousModel(
|
|
335
335
|
@header contentType: "multipart/form-data",
|
|
336
|
-
|
|
336
|
+
@multipartBody body: {
|
|
337
|
+
profileImage: HttpPart<bytes>;
|
|
338
|
+
},
|
|
337
339
|
): NoContentResponse;
|
|
338
340
|
|
|
339
341
|
namespace HttpParts {
|
|
@@ -412,7 +414,7 @@ namespace FormData {
|
|
|
412
414
|
}
|
|
413
415
|
@scenario
|
|
414
416
|
@scenarioDoc("""
|
|
415
|
-
For File part, filename will not be checked but it is necessary otherwise
|
|
417
|
+
For File part, filename will not be checked but it is necessary otherwise server can't parse it;
|
|
416
418
|
content-type will be checked with value "application/octet-stream". Expect request:
|
|
417
419
|
```
|
|
418
420
|
POST /upload HTTP/1.1
|