add non-string type for multipart/form-data basic/complex scenario (#484)

This commit is contained in:
Yuchao Yan 2024-08-29 22:34:58 +08:00 коммит произвёл GitHub
Родитель cca6fdf557
Коммит dac80400bd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 240 добавлений и 181 удалений

Просмотреть файл

@ -0,0 +1,5 @@
---
"@azure-tools/cadl-ranch-specs": minor
---
Add test case for multipart/form-data

Просмотреть файл

@ -3065,7 +3065,7 @@ Content-Type: image/jpg
--abcde12345--
```
### Payload_MultiPart_FormData_complex
### Payload_MultiPart_FormData_fileArrayAndBasic
- Endpoint: `post /multipart/form-data/complex-parts`
@ -3121,7 +3121,64 @@ Content-Type: application/octet-stream
--abcde12345--
```
### Payload_MultiPart_FormData_complexWithHttpPart
### Payload_MultiPart_FormData_HttpParts_ContentType_imageJpegContentType
- Endpoint: `post /multipart/form-data/check-filename-and-specific-content-type-with-httppart`
This case will check filename and specific content-type of file part, so expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="hello.jpg"
Content-Type: image/jpg
{…file content of .jpg file…}
--abcde12345--
```
### Payload_MultiPart_FormData_HttpParts_ContentType_optionalContentType
- Endpoint: `post /multipart/form-data/file-with-http-part-optional-content-type`
Please send request twice, first time with no content-type and second time with content-type "application/octet-stream". Expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345
```
### Payload_MultiPart_FormData_HttpParts_ContentType_requiredContentType
- Endpoint: `post /multipart/form-data/check-filename-and-required-content-type-with-httppart`
This case will check required content-type of file part, so expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345--
```
### Payload_MultiPart_FormData_HttpParts_jsonArrayAndFileArray
- Endpoint: `post /multipart/form-data/complex-parts-with-httppart`
@ -3172,11 +3229,11 @@ Content-Type: application/octet-stream
--abcde12345--
```
### Payload_MultiPart_FormData_fileWithHttpPartOptionalContentType
### Payload_MultiPart_FormData_HttpParts_NonString_float
- Endpoint: `post /multipart/form-data/file-with-http-part-optional-content-type`
- Endpoint: `post /multipart/form-data/non-string-float`
Please send request twice, first time with no content-type and second time with content-type "application/octet-stream". Expect request:
Expect request:
```
POST /upload HTTP/1.1
@ -3184,51 +3241,13 @@ Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
Content-Disposition: form-data; name="temperature"
Content-Type: text/plain
{…file content of .jpg file…}
0.5
--abcde12345
```
### Payload_MultiPart_FormData_fileWithHttpPartRequiredContentType
- Endpoint: `post /multipart/form-data/check-filename-and-required-content-type-with-httppart`
This case will check required content-type of file part, so expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345--
```
### Payload_MultiPart_FormData_fileWithHttpPartSpecificContentType
- Endpoint: `post /multipart/form-data/check-filename-and-specific-content-type-with-httppart`
This case will check filename and specific content-type of file part, so expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="hello.jpg"
Content-Type: image/jpg
{…file content of .jpg file…}
--abcde12345--
```
### Payload_MultiPart_FormData_jsonPart
- Endpoint: `post /multipart/form-data/json-part`

Просмотреть файл

@ -67,10 +67,6 @@ model BinaryArrayPartsRequest {
pictures: bytes[];
}
model JsonArrayPartsRequest {
profileImage: bytes;
}
model MultiBinaryPartsRequest {
profileImage: bytes;
picture?: bytes;
@ -164,7 +160,7 @@ namespace FormData {
@doc("Test content-type: multipart/form-data for mixed scenarios")
@post
@route("/complex-parts")
op complex(@header contentType: "multipart/form-data", @body body: ComplexPartsRequest): NoContentResponse;
op fileArrayAndBasic(@header contentType: "multipart/form-data", @body body: ComplexPartsRequest): NoContentResponse;
@scenario
@scenarioDoc("""
@ -330,131 +326,165 @@ namespace FormData {
profileImage: MultiPartRequest.profileImage,
): NoContentResponse;
@scenario
@scenarioDoc("""
This case will check filename and specific content-type of file part, so expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="hello.jpg"
Content-Type: image/jpg
{…file content of .jpg file…}
--abcde12345--
```
""")
@doc("Test content-type: multipart/form-data")
@post
@route("/check-filename-and-specific-content-type-with-httppart")
op fileWithHttpPartSpecificContentType(
@header contentType: "multipart/form-data",
@multipartBody body: FileWithHttpPartSpecificContentTypeRequest,
): NoContentResponse;
namespace HttpParts {
namespace ContentType {
@scenario
@scenarioDoc("""
This case will check filename and specific content-type of file part, so expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="hello.jpg"
Content-Type: image/jpg
{…file content of .jpg file…}
--abcde12345--
```
""")
@doc("Test content-type: multipart/form-data")
@post
@route("/check-filename-and-specific-content-type-with-httppart")
op imageJpegContentType(
@header contentType: "multipart/form-data",
@multipartBody body: FileWithHttpPartSpecificContentTypeRequest,
): NoContentResponse;
@scenario
@scenarioDoc("""
This case will check required content-type of file part, so expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345--
```
""")
@doc("Test content-type: multipart/form-data")
@post
@route("/check-filename-and-required-content-type-with-httppart")
op fileWithHttpPartRequiredContentType(
@header contentType: "multipart/form-data",
@multipartBody body: FileWithHttpPartRequiredContentTypeRequest,
): NoContentResponse;
@scenario
@scenarioDoc("""
This case will check required content-type of file part, so expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345--
```
""")
@doc("Test content-type: multipart/form-data")
@post
@route("/check-filename-and-required-content-type-with-httppart")
op requiredContentType(
@header contentType: "multipart/form-data",
@multipartBody body: FileWithHttpPartRequiredContentTypeRequest,
): NoContentResponse;
@scenario
@scenarioDoc("""
Please send request twice, first time with no content-type and second time with content-type "application/octet-stream". Expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345
```
""")
@doc("Test content-type: multipart/form-data for optional content type")
@post
@route("/file-with-http-part-optional-content-type")
op fileWithHttpPartOptionalContentType(
@header contentType: "multipart/form-data",
@multipartBody body: FileWithHttpPartOptionalContentTypeRequest,
): NoContentResponse;
@scenario
@scenarioDoc("""
For File part, filename will not be checked but it is necessary otherwise cadl-ranch can't parse it;
content-type will be checked with value "application/octet-stream". Expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="id"
Content-Type: text/plain
123
--abcde12345
Content-Disposition: form-data; name="address"
Content-Type: application/json
{
"city": "X"
@scenario
@scenarioDoc("""
Please send request twice, first time with no content-type and second time with content-type "application/octet-stream". Expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345
```
""")
@doc("Test content-type: multipart/form-data for optional content type")
@post
@route("/file-with-http-part-optional-content-type")
op optionalContentType(
@header contentType: "multipart/form-data",
@multipartBody body: FileWithHttpPartOptionalContentTypeRequest,
): NoContentResponse;
}
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345--
Content-Disposition: form-data; name="previousAddresses"
Content-Type: application/json
[{
"city": "Y"
},{
"city": "Z"
}]
--abcde12345
Content-Disposition: form-data; name="pictures"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .png file…}
--abcde12345
Content-Disposition: form-data; name="pictures"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .png file…}
--abcde12345--
```
""")
@doc("Test content-type: multipart/form-data for mixed scenarios")
@post
@route("/complex-parts-with-httppart")
op complexWithHttpPart(
@header contentType: "multipart/form-data",
@multipartBody body: ComplexHttpPartsModelRequest,
): NoContentResponse;
@scenario
@scenarioDoc("""
For File part, filename will not be checked but it is necessary otherwise cadl-ranch can't parse it;
content-type will be checked with value "application/octet-stream". Expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="id"
Content-Type: text/plain
123
--abcde12345
Content-Disposition: form-data; name="address"
Content-Type: application/json
{
"city": "X"
}
--abcde12345
Content-Disposition: form-data; name="profileImage"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .jpg file…}
--abcde12345--
Content-Disposition: form-data; name="previousAddresses"
Content-Type: application/json
[{
"city": "Y"
},{
"city": "Z"
}]
--abcde12345
Content-Disposition: form-data; name="pictures"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .png file…}
--abcde12345
Content-Disposition: form-data; name="pictures"; filename="<any-name-is-ok>"
Content-Type: application/octet-stream
{…file content of .png file…}
--abcde12345--
```
""")
@doc("Test content-type: multipart/form-data for mixed scenarios")
@post
@route("/complex-parts-with-httppart")
op jsonArrayAndFileArray(
@header contentType: "multipart/form-data",
@multipartBody body: ComplexHttpPartsModelRequest,
): NoContentResponse;
namespace NonString {
@scenario
@scenarioDoc("""
Expect request:
```
POST /upload HTTP/1.1
Content-Length: 428
Content-Type: multipart/form-data; boundary=abcde12345
--abcde12345
Content-Disposition: form-data; name="temperature"
Content-Type: text/plain
0.5
--abcde12345
```
""")
@doc("Test content-type: multipart/form-data for non string")
@post
@route("/non-string-float")
op float(
@header contentType: "multipart/form-data",
@multipartBody body: {
temperature: HttpPart<{
@body body: float64;
@header contentType: "text/plain";
}>;
},
): NoContentResponse;
}
}
}

Просмотреть файл

@ -105,7 +105,9 @@ function checkPictures(req: MockRequest) {
throw new ValidationError("No pictures found", "png files are expected", req.body);
}
}
function checkFloat(req: MockRequest) {
req.expect.deepEqual(parseFloat(req.body.temperature), 0.5);
}
function createMockApis(route: string, checkList: ((param: MockRequest) => void)[]): MockApi {
const url = `/multipart/form-data/${route}`;
return mockapi.post(url, (req) => {
@ -118,7 +120,7 @@ function createMockApis(route: string, checkList: ((param: MockRequest) => void)
Scenarios.Payload_MultiPart_FormData_basic = passOnSuccess(createMockApis("mixed-parts", [checkId, checkProfileImage]));
Scenarios.Payload_MultiPart_FormData_complex = passOnSuccess(
Scenarios.Payload_MultiPart_FormData_fileArrayAndBasic = passOnSuccess(
createMockApis("complex-parts", [checkId, checkAddress, checkAllFiles]),
);
@ -174,16 +176,19 @@ Scenarios.Payload_MultiPart_FormData_anonymousModel = passOnSuccess(
createMockApis("anonymous-model", [checkProfileImage]),
);
Scenarios.Payload_MultiPart_FormData_fileWithHttpPartSpecificContentType = passOnSuccess(
Scenarios.Payload_MultiPart_FormData_HttpParts_ContentType_imageJpegContentType = passOnSuccess(
createMockApis("check-filename-and-specific-content-type-with-httppart", [checkFileNameAndContentType]),
);
Scenarios.Payload_MultiPart_FormData_fileWithHttpPartRequiredContentType = passOnSuccess(
Scenarios.Payload_MultiPart_FormData_HttpParts_ContentType_requiredContentType = passOnSuccess(
createMockApis("check-filename-and-required-content-type-with-httppart", [checkProfileImage]),
);
Scenarios.Payload_MultiPart_FormData_fileWithHttpPartOptionalContentType = passOnSuccess(
Scenarios.Payload_MultiPart_FormData_HttpParts_ContentType_optionalContentType = passOnSuccess(
createMockApis("file-with-http-part-optional-content-type", [checkOptionalContentType]),
);
Scenarios.Payload_MultiPart_FormData_complexWithHttpPart = passOnSuccess(
Scenarios.Payload_MultiPart_FormData_HttpParts_jsonArrayAndFileArray = passOnSuccess(
createMockApis("complex-parts-with-httppart", [checkId, checkAddress, checkPreviousAddresses, checkAllFiles]),
);
Scenarios.Payload_MultiPart_FormData_HttpParts_NonString_float = passOnSuccess(
createMockApis("non-string-float", [checkFloat]),
);