mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-21 09:49:21 +00:00
LibWeb: Implement formData()
for "multipart/form-data"
This commit is contained in:
parent
7ae46bf8b7
commit
8b097b38dd
Notes:
github-actions[bot]
2025-01-20 23:34:52 +00:00
Author: https://github.com/F3n67u
Commit: 8b097b38dd
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3036
Reviewed-by: https://github.com/konradekk
Reviewed-by: https://github.com/tcl3 ✅
27 changed files with 1356 additions and 4 deletions
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
|
||||
<div id=log></div>
|
||||
<script src="../../../fetch/api/body/formdata.any.js"></script>
|
|
@ -0,0 +1,25 @@
|
|||
promise_test(async t => {
|
||||
const res = new Response(new FormData());
|
||||
const fd = await res.formData();
|
||||
assert_true(fd instanceof FormData);
|
||||
}, 'Consume empty response.formData() as FormData');
|
||||
|
||||
promise_test(async t => {
|
||||
const req = new Request('about:blank', {
|
||||
method: 'POST',
|
||||
body: new FormData()
|
||||
});
|
||||
const fd = await req.formData();
|
||||
assert_true(fd instanceof FormData);
|
||||
}, 'Consume empty request.formData() as FormData');
|
||||
|
||||
promise_test(async t => {
|
||||
let formdata = new FormData();
|
||||
formdata.append('foo', new Blob([JSON.stringify({ bar: "baz", })], { type: "application/json" }));
|
||||
let blob = await new Response(formdata).blob();
|
||||
let body = await blob.text();
|
||||
blob = new Blob([body.toLowerCase()], { type: blob.type.toLowerCase() });
|
||||
let formdataWithLowercaseBody = await new Response(blob).formData();
|
||||
assert_true(formdataWithLowercaseBody.has("foo"));
|
||||
assert_equals(formdataWithLowercaseBody.get("foo").type, "application/json");
|
||||
}, 'Consume multipart/form-data headers case-insensitively');
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Request consume empty bodies</title>
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
|
||||
<div id=log></div>
|
||||
<script src="../../../fetch/api/request/request-consume-empty.any.js"></script>
|
|
@ -0,0 +1,89 @@
|
|||
// META: global=window,worker
|
||||
// META: title=Request consume empty bodies
|
||||
|
||||
function checkBodyText(test, request) {
|
||||
return request.text().then(function(bodyAsText) {
|
||||
assert_equals(bodyAsText, "", "Resolved value should be empty");
|
||||
assert_false(request.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
async function checkBodyBlob(test, request) {
|
||||
const bodyAsBlob = await request.blob();
|
||||
const body = await bodyAsBlob.text();
|
||||
assert_equals(body, "", "Resolved value should be empty");
|
||||
assert_false(request.bodyUsed);
|
||||
}
|
||||
|
||||
function checkBodyArrayBuffer(test, request) {
|
||||
return request.arrayBuffer().then(function(bodyAsArrayBuffer) {
|
||||
assert_equals(bodyAsArrayBuffer.byteLength, 0, "Resolved value should be empty");
|
||||
assert_false(request.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyJSON(test, request) {
|
||||
return request.json().then(
|
||||
function(bodyAsJSON) {
|
||||
assert_unreached("JSON parsing should fail");
|
||||
},
|
||||
function() {
|
||||
assert_false(request.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormData(test, request) {
|
||||
return request.formData().then(function(bodyAsFormData) {
|
||||
assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
|
||||
assert_false(request.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormDataError(test, request) {
|
||||
return promise_rejects_js(test, TypeError, request.formData()).then(function() {
|
||||
assert_false(request.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkRequestWithNoBody(bodyType, checkFunction, headers = []) {
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "headers": headers});
|
||||
assert_false(request.bodyUsed);
|
||||
return checkFunction(test, request);
|
||||
}, "Consume request's body as " + bodyType);
|
||||
}
|
||||
|
||||
checkRequestWithNoBody("text", checkBodyText);
|
||||
checkRequestWithNoBody("blob", checkBodyBlob);
|
||||
checkRequestWithNoBody("arrayBuffer", checkBodyArrayBuffer);
|
||||
checkRequestWithNoBody("json (error case)", checkBodyJSON);
|
||||
checkRequestWithNoBody("formData with correct multipart type (error case)", checkBodyFormDataError, [["Content-Type", 'multipart/form-data; boundary="boundary"']]);
|
||||
checkRequestWithNoBody("formData with correct urlencoded type", checkBodyFormData, [["Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"]]);
|
||||
checkRequestWithNoBody("formData without correct type (error case)", checkBodyFormDataError);
|
||||
|
||||
function checkRequestWithEmptyBody(bodyType, body, asText) {
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "body": body});
|
||||
assert_false(request.bodyUsed, "bodyUsed is false at init");
|
||||
if (asText) {
|
||||
return request.text().then(function(bodyAsString) {
|
||||
assert_equals(bodyAsString.length, 0, "Resolved value should be empty");
|
||||
assert_true(request.bodyUsed, "bodyUsed is true after being consumed");
|
||||
});
|
||||
}
|
||||
return request.arrayBuffer().then(function(bodyAsArrayBuffer) {
|
||||
assert_equals(bodyAsArrayBuffer.byteLength, 0, "Resolved value should be empty");
|
||||
assert_true(request.bodyUsed, "bodyUsed is true after being consumed");
|
||||
});
|
||||
}, "Consume empty " + bodyType + " request body as " + (asText ? "text" : "arrayBuffer"));
|
||||
}
|
||||
|
||||
// FIXME: Add BufferSource, FormData and URLSearchParams.
|
||||
checkRequestWithEmptyBody("blob", new Blob([], { "type" : "text/plain" }), false);
|
||||
checkRequestWithEmptyBody("text", "", false);
|
||||
checkRequestWithEmptyBody("blob", new Blob([], { "type" : "text/plain" }), true);
|
||||
checkRequestWithEmptyBody("text", "", true);
|
||||
checkRequestWithEmptyBody("URLSearchParams", new URLSearchParams(""), true);
|
||||
// FIXME: This test assumes that the empty string be returned but it is not clear whether that is right. See https://github.com/web-platform-tests/wpt/pull/3950.
|
||||
checkRequestWithEmptyBody("FormData", new FormData(), true);
|
||||
checkRequestWithEmptyBody("ArrayBuffer", new ArrayBuffer(), true);
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Request consume</title>
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../resources/utils.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../../fetch/api/request/request-consume.any.js"></script>
|
|
@ -0,0 +1,148 @@
|
|||
// META: global=window,worker
|
||||
// META: title=Request consume
|
||||
// META: script=../resources/utils.js
|
||||
|
||||
function checkBodyText(request, expectedBody) {
|
||||
return request.text().then(function(bodyAsText) {
|
||||
assert_equals(bodyAsText, expectedBody, "Retrieve and verify request's body");
|
||||
assert_true(request.bodyUsed, "body as text: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
async function checkBodyBlob(request, expectedBody, checkContentType) {
|
||||
const bodyAsBlob = await request.blob();
|
||||
|
||||
if (checkContentType)
|
||||
assert_equals(bodyAsBlob.type, "text/plain", "Blob body type should be computed from the request Content-Type");
|
||||
|
||||
const body = await bodyAsBlob.text();
|
||||
assert_equals(body, expectedBody, "Retrieve and verify request's body");
|
||||
assert_true(request.bodyUsed, "body as blob: bodyUsed turned true");
|
||||
}
|
||||
|
||||
function checkBodyArrayBuffer(request, expectedBody) {
|
||||
return request.arrayBuffer().then(function(bodyAsArrayBuffer) {
|
||||
validateBufferFromString(bodyAsArrayBuffer, expectedBody, "Retrieve and verify request's body");
|
||||
assert_true(request.bodyUsed, "body as arrayBuffer: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyBytes(request, expectedBody) {
|
||||
return request.bytes().then(function(bodyAsUint8Array) {
|
||||
assert_true(bodyAsUint8Array instanceof Uint8Array);
|
||||
validateBufferFromString(bodyAsUint8Array.buffer, expectedBody, "Retrieve and verify request's body");
|
||||
assert_true(request.bodyUsed, "body as bytes: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyJSON(request, expectedBody) {
|
||||
return request.json().then(function(bodyAsJSON) {
|
||||
var strBody = JSON.stringify(bodyAsJSON)
|
||||
assert_equals(strBody, expectedBody, "Retrieve and verify request's body");
|
||||
assert_true(request.bodyUsed, "body as json: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormData(request, expectedBody) {
|
||||
return request.formData().then(function(bodyAsFormData) {
|
||||
assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
|
||||
assert_true(request.bodyUsed, "body as formData: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkRequestBody(body, expected, bodyType) {
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "body": body, "headers": [["Content-Type", "text/PLAIN"]] });
|
||||
assert_false(request.bodyUsed, "bodyUsed is false at init");
|
||||
return checkBodyText(request, expected);
|
||||
}, "Consume " + bodyType + " request's body as text");
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "body": body });
|
||||
assert_false(request.bodyUsed, "bodyUsed is false at init");
|
||||
return checkBodyBlob(request, expected);
|
||||
}, "Consume " + bodyType + " request's body as blob");
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "body": body });
|
||||
assert_false(request.bodyUsed, "bodyUsed is false at init");
|
||||
return checkBodyArrayBuffer(request, expected);
|
||||
}, "Consume " + bodyType + " request's body as arrayBuffer");
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "body": body });
|
||||
assert_false(request.bodyUsed, "bodyUsed is false at init");
|
||||
return checkBodyBytes(request, expected);
|
||||
}, "Consume " + bodyType + " request's body as bytes");
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "body": body });
|
||||
assert_false(request.bodyUsed, "bodyUsed is false at init");
|
||||
return checkBodyJSON(request, expected);
|
||||
}, "Consume " + bodyType + " request's body as JSON");
|
||||
}
|
||||
|
||||
var textData = JSON.stringify("This is response's body");
|
||||
var blob = new Blob([textData], { "type" : "text/plain" });
|
||||
|
||||
checkRequestBody(textData, textData, "String");
|
||||
|
||||
var string = "\"123456\"";
|
||||
function getArrayBuffer() {
|
||||
var arrayBuffer = new ArrayBuffer(8);
|
||||
var int8Array = new Int8Array(arrayBuffer);
|
||||
for (var cptr = 0; cptr < 8; cptr++)
|
||||
int8Array[cptr] = string.charCodeAt(cptr);
|
||||
return arrayBuffer;
|
||||
}
|
||||
|
||||
function getArrayBufferWithZeros() {
|
||||
var arrayBuffer = new ArrayBuffer(10);
|
||||
var int8Array = new Int8Array(arrayBuffer);
|
||||
for (var cptr = 0; cptr < 8; cptr++)
|
||||
int8Array[cptr + 1] = string.charCodeAt(cptr);
|
||||
return arrayBuffer;
|
||||
}
|
||||
|
||||
checkRequestBody(getArrayBuffer(), string, "ArrayBuffer");
|
||||
checkRequestBody(new Uint8Array(getArrayBuffer()), string, "Uint8Array");
|
||||
checkRequestBody(new Int8Array(getArrayBufferWithZeros(), 1, 8), string, "Int8Array");
|
||||
checkRequestBody(new Float32Array(getArrayBuffer()), string, "Float32Array");
|
||||
checkRequestBody(new DataView(getArrayBufferWithZeros(), 1, 8), string, "DataView");
|
||||
|
||||
promise_test(function(test) {
|
||||
var formData = new FormData();
|
||||
formData.append("name", "value")
|
||||
var request = new Request("", {"method": "POST", "body": formData });
|
||||
assert_false(request.bodyUsed, "bodyUsed is false at init");
|
||||
return checkBodyFormData(request, formData);
|
||||
}, "Consume FormData request's body as FormData");
|
||||
|
||||
function checkBlobResponseBody(blobBody, blobData, bodyType, checkFunction) {
|
||||
promise_test(function(test) {
|
||||
var response = new Response(blobBody);
|
||||
assert_false(response.bodyUsed, "bodyUsed is false at init");
|
||||
return checkFunction(response, blobData);
|
||||
}, "Consume blob response's body as " + bodyType);
|
||||
}
|
||||
|
||||
checkBlobResponseBody(blob, textData, "blob", checkBodyBlob);
|
||||
checkBlobResponseBody(blob, textData, "text", checkBodyText);
|
||||
checkBlobResponseBody(blob, textData, "json", checkBodyJSON);
|
||||
checkBlobResponseBody(blob, textData, "arrayBuffer", checkBodyArrayBuffer);
|
||||
checkBlobResponseBody(blob, textData, "bytes", checkBodyBytes);
|
||||
checkBlobResponseBody(new Blob([""]), "", "blob (empty blob as input)", checkBodyBlob);
|
||||
|
||||
var goodJSONValues = ["null", "1", "true", "\"string\""];
|
||||
goodJSONValues.forEach(function(value) {
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "body": value});
|
||||
return request.json().then(function(v) {
|
||||
assert_equals(v, JSON.parse(value));
|
||||
});
|
||||
}, "Consume JSON from text: '" + JSON.stringify(value) + "'");
|
||||
});
|
||||
|
||||
var badJSONValues = ["undefined", "{", "a", "["];
|
||||
badJSONValues.forEach(function(value) {
|
||||
promise_test(function(test) {
|
||||
var request = new Request("", {"method": "POST", "body": value});
|
||||
return promise_rejects_js(test, SyntaxError, request.json());
|
||||
}, "Trying to consume bad JSON text as JSON: '" + value + "'");
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
top
|
120
Tests/LibWeb/Text/input/wpt-import/fetch/api/resources/utils.js
Normal file
120
Tests/LibWeb/Text/input/wpt-import/fetch/api/resources/utils.js
Normal file
|
@ -0,0 +1,120 @@
|
|||
var RESOURCES_DIR = "../resources/";
|
||||
|
||||
function dirname(path) {
|
||||
return path.replace(/\/[^\/]*$/, '/')
|
||||
}
|
||||
|
||||
function checkRequest(request, ExpectedValuesDict) {
|
||||
for (var attribute in ExpectedValuesDict) {
|
||||
switch(attribute) {
|
||||
case "headers":
|
||||
for (var key in ExpectedValuesDict["headers"].keys()) {
|
||||
assert_equals(request["headers"].get(key), ExpectedValuesDict["headers"].get(key),
|
||||
"Check headers attribute has " + key + ":" + ExpectedValuesDict["headers"].get(key));
|
||||
}
|
||||
break;
|
||||
|
||||
case "body":
|
||||
//for checking body's content, a dedicated asyncronous/promise test should be used
|
||||
assert_true(request["headers"].has("Content-Type") , "Check request has body using Content-Type header")
|
||||
break;
|
||||
|
||||
case "method":
|
||||
case "referrer":
|
||||
case "referrerPolicy":
|
||||
case "credentials":
|
||||
case "cache":
|
||||
case "redirect":
|
||||
case "integrity":
|
||||
case "url":
|
||||
case "destination":
|
||||
assert_equals(request[attribute], ExpectedValuesDict[attribute], "Check " + attribute + " attribute")
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stringToArray(str) {
|
||||
var array = new Uint8Array(str.length);
|
||||
for (var i=0, strLen = str.length; i < strLen; i++)
|
||||
array[i] = str.charCodeAt(i);
|
||||
return array;
|
||||
}
|
||||
|
||||
function encode_utf8(str)
|
||||
{
|
||||
if (self.TextEncoder)
|
||||
return (new TextEncoder).encode(str);
|
||||
return stringToArray(unescape(encodeURIComponent(str)));
|
||||
}
|
||||
|
||||
function validateBufferFromString(buffer, expectedValue, message)
|
||||
{
|
||||
return assert_array_equals(new Uint8Array(buffer !== undefined ? buffer : []), stringToArray(expectedValue), message);
|
||||
}
|
||||
|
||||
function validateStreamFromString(reader, expectedValue, retrievedArrayBuffer) {
|
||||
// Passing Uint8Array for byte streams; non-byte streams will simply ignore it
|
||||
return reader.read(new Uint8Array(64)).then(function(data) {
|
||||
if (!data.done) {
|
||||
assert_true(data.value instanceof Uint8Array, "Fetch ReadableStream chunks should be Uint8Array");
|
||||
var newBuffer;
|
||||
if (retrievedArrayBuffer) {
|
||||
newBuffer = new Uint8Array(data.value.length + retrievedArrayBuffer.length);
|
||||
newBuffer.set(retrievedArrayBuffer, 0);
|
||||
newBuffer.set(data.value, retrievedArrayBuffer.length);
|
||||
} else {
|
||||
newBuffer = data.value;
|
||||
}
|
||||
return validateStreamFromString(reader, expectedValue, newBuffer);
|
||||
}
|
||||
validateBufferFromString(retrievedArrayBuffer, expectedValue, "Retrieve and verify stream");
|
||||
});
|
||||
}
|
||||
|
||||
function validateStreamFromPartialString(reader, expectedValue, retrievedArrayBuffer) {
|
||||
// Passing Uint8Array for byte streams; non-byte streams will simply ignore it
|
||||
return reader.read(new Uint8Array(64)).then(function(data) {
|
||||
if (!data.done) {
|
||||
assert_true(data.value instanceof Uint8Array, "Fetch ReadableStream chunks should be Uint8Array");
|
||||
var newBuffer;
|
||||
if (retrievedArrayBuffer) {
|
||||
newBuffer = new Uint8Array(data.value.length + retrievedArrayBuffer.length);
|
||||
newBuffer.set(retrievedArrayBuffer, 0);
|
||||
newBuffer.set(data.value, retrievedArrayBuffer.length);
|
||||
} else {
|
||||
newBuffer = data.value;
|
||||
}
|
||||
return validateStreamFromPartialString(reader, expectedValue, newBuffer);
|
||||
}
|
||||
|
||||
var string = new TextDecoder("utf-8").decode(retrievedArrayBuffer);
|
||||
return assert_true(string.search(expectedValue) != -1, "Retrieve and verify stream");
|
||||
});
|
||||
}
|
||||
|
||||
// From streams tests
|
||||
function delay(milliseconds)
|
||||
{
|
||||
return new Promise(function(resolve) {
|
||||
step_timeout(resolve, milliseconds);
|
||||
});
|
||||
}
|
||||
|
||||
function requestForbiddenHeaders(desc, forbiddenHeaders) {
|
||||
var url = RESOURCES_DIR + "inspect-headers.py";
|
||||
var requestInit = {"headers": forbiddenHeaders}
|
||||
var urlParameters = "?headers=" + Object.keys(forbiddenHeaders).join("|");
|
||||
|
||||
promise_test(function(test){
|
||||
return fetch(url + urlParameters, requestInit).then(function(resp) {
|
||||
assert_equals(resp.status, 200, "HTTP status is 200");
|
||||
assert_equals(resp.type , "basic", "Response's type is basic");
|
||||
for (var header in forbiddenHeaders)
|
||||
assert_not_equals(resp.headers.get("x-request-" + header), forbiddenHeaders[header], header + " does not have the value we defined");
|
||||
});
|
||||
}, desc);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Response consume empty bodies</title>
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
|
||||
<div id=log></div>
|
||||
<script src="../../../fetch/api/response/response-consume-empty.any.js"></script>
|
|
@ -0,0 +1,88 @@
|
|||
// META: global=window,worker
|
||||
// META: title=Response consume empty bodies
|
||||
|
||||
function checkBodyText(test, response) {
|
||||
return response.text().then(function(bodyAsText) {
|
||||
assert_equals(bodyAsText, "", "Resolved value should be empty");
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
async function checkBodyBlob(test, response) {
|
||||
const bodyAsBlob = await response.blob();
|
||||
const body = await bodyAsBlob.text();
|
||||
|
||||
assert_equals(body, "", "Resolved value should be empty");
|
||||
assert_false(response.bodyUsed);
|
||||
}
|
||||
|
||||
function checkBodyArrayBuffer(test, response) {
|
||||
return response.arrayBuffer().then(function(bodyAsArrayBuffer) {
|
||||
assert_equals(bodyAsArrayBuffer.byteLength, 0, "Resolved value should be empty");
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyJSON(test, response) {
|
||||
return response.json().then(
|
||||
function(bodyAsJSON) {
|
||||
assert_unreached("JSON parsing should fail");
|
||||
},
|
||||
function() {
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormData(test, response) {
|
||||
return response.formData().then(function(bodyAsFormData) {
|
||||
assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormDataError(test, response) {
|
||||
return promise_rejects_js(test, TypeError, response.formData()).then(function() {
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkResponseWithNoBody(bodyType, checkFunction, headers = []) {
|
||||
promise_test(function(test) {
|
||||
var response = new Response(undefined, { "headers": headers });
|
||||
assert_false(response.bodyUsed);
|
||||
return checkFunction(test, response);
|
||||
}, "Consume response's body as " + bodyType);
|
||||
}
|
||||
|
||||
checkResponseWithNoBody("text", checkBodyText);
|
||||
checkResponseWithNoBody("blob", checkBodyBlob);
|
||||
checkResponseWithNoBody("arrayBuffer", checkBodyArrayBuffer);
|
||||
checkResponseWithNoBody("json (error case)", checkBodyJSON);
|
||||
checkResponseWithNoBody("formData with correct multipart type (error case)", checkBodyFormDataError, [["Content-Type", 'multipart/form-data; boundary="boundary"']]);
|
||||
checkResponseWithNoBody("formData with correct urlencoded type", checkBodyFormData, [["Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"]]);
|
||||
checkResponseWithNoBody("formData without correct type (error case)", checkBodyFormDataError);
|
||||
|
||||
function checkResponseWithEmptyBody(bodyType, body, asText) {
|
||||
promise_test(function(test) {
|
||||
var response = new Response(body);
|
||||
assert_false(response.bodyUsed, "bodyUsed is false at init");
|
||||
if (asText) {
|
||||
return response.text().then(function(bodyAsString) {
|
||||
assert_equals(bodyAsString.length, 0, "Resolved value should be empty");
|
||||
assert_true(response.bodyUsed, "bodyUsed is true after being consumed");
|
||||
});
|
||||
}
|
||||
return response.arrayBuffer().then(function(bodyAsArrayBuffer) {
|
||||
assert_equals(bodyAsArrayBuffer.byteLength, 0, "Resolved value should be empty");
|
||||
assert_true(response.bodyUsed, "bodyUsed is true after being consumed");
|
||||
});
|
||||
}, "Consume empty " + bodyType + " response body as " + (asText ? "text" : "arrayBuffer"));
|
||||
}
|
||||
|
||||
checkResponseWithEmptyBody("blob", new Blob([], { "type" : "text/plain" }), false);
|
||||
checkResponseWithEmptyBody("text", "", false);
|
||||
checkResponseWithEmptyBody("blob", new Blob([], { "type" : "text/plain" }), true);
|
||||
checkResponseWithEmptyBody("text", "", true);
|
||||
checkResponseWithEmptyBody("URLSearchParams", new URLSearchParams(""), true);
|
||||
checkResponseWithEmptyBody("FormData", new FormData(), true);
|
||||
checkResponseWithEmptyBody("ArrayBuffer", new ArrayBuffer(), true);
|
|
@ -0,0 +1,317 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Response consume</title>
|
||||
<meta name="help" href="https://fetch.spec.whatwg.org/#response">
|
||||
<meta name="help" href="https://fetch.spec.whatwg.org/#body-mixin">
|
||||
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../resources/utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function blobToFormDataResponse(name, blob) {
|
||||
var formData = new FormData();
|
||||
formData.append(name, blob);
|
||||
return new Response(formData);
|
||||
}
|
||||
|
||||
function readBlobAsArrayBuffer(blob) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(evt) {
|
||||
resolve(reader.result);
|
||||
};
|
||||
reader.onerror = function(evt) {
|
||||
reject("Blob's reader failed");
|
||||
};
|
||||
reader.readAsArrayBuffer(blob);
|
||||
});
|
||||
}
|
||||
|
||||
function blobToTypeViaFetch(blob) {
|
||||
var url = URL.createObjectURL(blob);
|
||||
return fetch(url).then(function(response) {
|
||||
return response.headers.get('Content-Type');
|
||||
});
|
||||
}
|
||||
|
||||
function responsePromise(body, responseInit) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(new Response(body, responseInit));
|
||||
});
|
||||
}
|
||||
|
||||
function responseStringToMultipartFormTextData(response, name, value) {
|
||||
assert_true(response.headers.has("Content-Type"), "Response contains Content-Type header");
|
||||
var boundaryMatches = response.headers.get("Content-Type").match(/;\s*boundary=("?)([^";\s]*)\1/);
|
||||
assert_true(!!boundaryMatches, "Response contains boundary parameter");
|
||||
return stringToMultipartFormTextData(boundaryMatches[2], name, value);
|
||||
}
|
||||
|
||||
function streamResponsePromise(streamData, responseInit) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var stream = new ReadableStream({
|
||||
start: function(controller) {
|
||||
controller.enqueue(stringToArray(streamData));
|
||||
controller.close();
|
||||
}
|
||||
});
|
||||
resolve(new Response(stream, responseInit));
|
||||
});
|
||||
}
|
||||
|
||||
function stringToMultipartFormTextData(multipartBoundary, name, value) {
|
||||
return ('--' + multipartBoundary + '\r\n' +
|
||||
'Content-Disposition: form-data;name="' + name + '"\r\n' +
|
||||
'\r\n' +
|
||||
value + '\r\n' +
|
||||
'--' + multipartBoundary + '--\r\n');
|
||||
}
|
||||
|
||||
function checkBodyText(test, response, expectedBody) {
|
||||
return response.text().then( function(bodyAsText) {
|
||||
assert_equals(bodyAsText, expectedBody, "Retrieve and verify response's body");
|
||||
assert_true(response.bodyUsed, "body as text: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyBlob(test, response, expectedBody, expectedType) {
|
||||
return response.blob().then(function(bodyAsBlob) {
|
||||
assert_equals(bodyAsBlob.type, expectedType || "text/plain", "Blob body type should be computed from the response Content-Type");
|
||||
|
||||
var promise = blobToTypeViaFetch(bodyAsBlob).then(function(type) {
|
||||
assert_equals(type, expectedType || "text/plain", 'Type via blob URL');
|
||||
return new Promise( function (resolve, reject) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(evt) {
|
||||
resolve(reader.result)
|
||||
};
|
||||
reader.onerror = function () {
|
||||
reject("Blob's reader failed");
|
||||
};
|
||||
reader.readAsText(bodyAsBlob);
|
||||
});
|
||||
});
|
||||
return promise.then(function(body) {
|
||||
assert_equals(body, expectedBody, "Retrieve and verify response's body");
|
||||
assert_true(response.bodyUsed, "body as blob: bodyUsed turned true");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyArrayBuffer(test, response, expectedBody) {
|
||||
return response.arrayBuffer().then( function(bodyAsArrayBuffer) {
|
||||
validateBufferFromString(bodyAsArrayBuffer, expectedBody, "Retrieve and verify response's body");
|
||||
assert_true(response.bodyUsed, "body as arrayBuffer: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyJSON(test, response, expectedBody) {
|
||||
return response.json().then(function(bodyAsJSON) {
|
||||
var strBody = JSON.stringify(bodyAsJSON)
|
||||
assert_equals(strBody, expectedBody, "Retrieve and verify response's body");
|
||||
assert_true(response.bodyUsed, "body as json: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormDataMultipart(test, response, expectedBody) {
|
||||
return response.formData().then(function(bodyAsFormData) {
|
||||
assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
|
||||
var entryName = "name";
|
||||
var strBody = responseStringToMultipartFormTextData(response, entryName, bodyAsFormData.get(entryName));
|
||||
assert_equals(strBody, expectedBody, "Retrieve and verify response's body");
|
||||
assert_true(response.bodyUsed, "body as formData: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormDataUrlencoded(test, response, expectedBody) {
|
||||
return response.formData().then(function(bodyAsFormData) {
|
||||
assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
|
||||
var entryName = "name";
|
||||
var strBody = entryName + "=" + bodyAsFormData.get(entryName);
|
||||
assert_equals(strBody, expectedBody, "Retrieve and verify response's body");
|
||||
assert_true(response.bodyUsed, "body as formData: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormDataError(test, response, expectedBody) {
|
||||
return promise_rejects_js(test, TypeError, response.formData()).then(function() {
|
||||
assert_true(response.bodyUsed, "body as formData: bodyUsed turned true");
|
||||
});
|
||||
}
|
||||
|
||||
function checkResponseBody(responsePromise, expectedBody, checkFunction, bodyTypes) {
|
||||
promise_test(function(test) {
|
||||
return responsePromise.then(function(response) {
|
||||
assert_false(response.bodyUsed, "bodyUsed is false at init");
|
||||
return checkFunction(test, response, expectedBody);
|
||||
});
|
||||
}, "Consume response's body: " + bodyTypes);
|
||||
}
|
||||
|
||||
var textData = JSON.stringify("This is response's body");
|
||||
var textResponseInit = { "headers": [["Content-Type", "text/PLAIN"]] };
|
||||
var blob = new Blob([textData], { "type": "application/octet-stream" });
|
||||
var multipartBoundary = "boundary-" + Math.random();
|
||||
var formData = new FormData();
|
||||
var formTextResponseInit = { "headers": [["Content-Type", 'multipart/FORM-data; boundary="' + multipartBoundary + '"']] };
|
||||
var formTextData = stringToMultipartFormTextData(multipartBoundary, "name", textData);
|
||||
var formBlob = new Blob([formTextData]);
|
||||
var urlSearchParamsData = "name=value";
|
||||
var urlSearchParams = new URLSearchParams(urlSearchParamsData);
|
||||
var urlSearchParamsType = "application/x-www-form-urlencoded;charset=UTF-8";
|
||||
var urlSearchParamsResponseInit = { "headers": [["Content-Type", urlSearchParamsType]] };
|
||||
var urlSearchParamsBlob = new Blob([urlSearchParamsData], { "type": urlSearchParamsType });
|
||||
formData.append("name", textData);
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-body-package-data
|
||||
// "UTF-8 decoded without BOM" is used for formData(), either in
|
||||
// "multipart/form-data" and "application/x-www-form-urlencoded" cases,
|
||||
// so BOMs in the values should be kept.
|
||||
// (The "application/x-www-form-urlencoded" cases are tested in
|
||||
// url/urlencoded-parser.any.js)
|
||||
var textDataWithBom = "\uFEFFquick\uFEFFfox\uFEFF";
|
||||
var formTextDataWithBom = stringToMultipartFormTextData(multipartBoundary, "name", textDataWithBom);
|
||||
var formTextDataWithBomExpectedForMultipartFormData = stringToMultipartFormTextData(multipartBoundary, "name", textDataWithBom);
|
||||
|
||||
checkResponseBody(responsePromise(textData, textResponseInit), textData, checkBodyText, "from text to text");
|
||||
checkResponseBody(responsePromise(textData, textResponseInit), textData, checkBodyBlob, "from text to blob");
|
||||
checkResponseBody(responsePromise(textData, textResponseInit), textData, checkBodyArrayBuffer, "from text to arrayBuffer");
|
||||
checkResponseBody(responsePromise(textData, textResponseInit), textData, checkBodyJSON, "from text to json");
|
||||
checkResponseBody(responsePromise(formTextData, formTextResponseInit), formTextData, checkBodyFormDataMultipart, "from text with correct multipart type to formData");
|
||||
checkResponseBody(responsePromise(formTextDataWithBom, formTextResponseInit), formTextDataWithBomExpectedForMultipartFormData, checkBodyFormDataMultipart, "from text with correct multipart type to formData with BOM");
|
||||
checkResponseBody(responsePromise(formTextData, textResponseInit), undefined, checkBodyFormDataError, "from text without correct multipart type to formData (error case)");
|
||||
checkResponseBody(responsePromise(urlSearchParamsData, urlSearchParamsResponseInit), urlSearchParamsData, checkBodyFormDataUrlencoded, "from text with correct urlencoded type to formData");
|
||||
checkResponseBody(responsePromise(urlSearchParamsData, textResponseInit), undefined, checkBodyFormDataError, "from text without correct urlencoded type to formData (error case)");
|
||||
|
||||
checkResponseBody(responsePromise(blob, textResponseInit), textData, checkBodyBlob, "from blob to blob");
|
||||
checkResponseBody(responsePromise(blob), textData, checkBodyText, "from blob to text");
|
||||
checkResponseBody(responsePromise(blob), textData, checkBodyArrayBuffer, "from blob to arrayBuffer");
|
||||
checkResponseBody(responsePromise(blob), textData, checkBodyJSON, "from blob to json");
|
||||
checkResponseBody(responsePromise(formBlob, formTextResponseInit), formTextData, checkBodyFormDataMultipart, "from blob with correct multipart type to formData");
|
||||
checkResponseBody(responsePromise(formBlob, textResponseInit), undefined, checkBodyFormDataError, "from blob without correct multipart type to formData (error case)");
|
||||
checkResponseBody(responsePromise(urlSearchParamsBlob, urlSearchParamsResponseInit), urlSearchParamsData, checkBodyFormDataUrlencoded, "from blob with correct urlencoded type to formData");
|
||||
checkResponseBody(responsePromise(urlSearchParamsBlob, textResponseInit), undefined, checkBodyFormDataError, "from blob without correct urlencoded type to formData (error case)");
|
||||
|
||||
function checkFormDataResponseBody(responsePromise, expectedName, expectedValue, checkFunction, bodyTypes) {
|
||||
promise_test(function(test) {
|
||||
return responsePromise.then(function(response) {
|
||||
assert_false(response.bodyUsed, "bodyUsed is false at init");
|
||||
var expectedBody = responseStringToMultipartFormTextData(response, expectedName, expectedValue);
|
||||
return Promise.resolve().then(function() {
|
||||
if (checkFunction === checkBodyFormDataMultipart)
|
||||
return expectedBody;
|
||||
// Modify expectedBody to use the same spacing for
|
||||
// Content-Disposition parameters as Response and FormData does.
|
||||
var response2 = new Response(formData);
|
||||
return response2.text().then(function(formDataAsText) {
|
||||
var reName = /[ \t]*;[ \t]*name=/;
|
||||
var nameMatches = formDataAsText.match(reName);
|
||||
return expectedBody.replace(reName, nameMatches[0]);
|
||||
});
|
||||
}).then(function(expectedBody) {
|
||||
return checkFunction(test, response, expectedBody);
|
||||
});
|
||||
});
|
||||
}, "Consume response's body: " + bodyTypes);
|
||||
}
|
||||
|
||||
checkFormDataResponseBody(responsePromise(formData), "name", textData, checkBodyFormDataMultipart, "from FormData to formData");
|
||||
checkResponseBody(responsePromise(formData, textResponseInit), undefined, checkBodyFormDataError, "from FormData without correct type to formData (error case)");
|
||||
checkFormDataResponseBody(responsePromise(formData), "name", textData, function(test, response, expectedBody) { return checkBodyBlob(test, response, expectedBody, response.headers.get('Content-Type').toLowerCase()); }, "from FormData to blob");
|
||||
checkFormDataResponseBody(responsePromise(formData), "name", textData, checkBodyText, "from FormData to text");
|
||||
checkFormDataResponseBody(responsePromise(formData), "name", textData, checkBodyArrayBuffer, "from FormData to arrayBuffer");
|
||||
|
||||
checkResponseBody(responsePromise(urlSearchParams), urlSearchParamsData, checkBodyFormDataUrlencoded, "from URLSearchParams to formData");
|
||||
checkResponseBody(responsePromise(urlSearchParams, textResponseInit), urlSearchParamsData, checkBodyFormDataError, "from URLSearchParams without correct type to formData (error case)");
|
||||
checkResponseBody(responsePromise(urlSearchParams), urlSearchParamsData, function(test, response, expectedBody) { return checkBodyBlob(test, response, expectedBody, "application/x-www-form-urlencoded;charset=utf-8"); }, "from URLSearchParams to blob");
|
||||
checkResponseBody(responsePromise(urlSearchParams), urlSearchParamsData, checkBodyText, "from URLSearchParams to text");
|
||||
checkResponseBody(responsePromise(urlSearchParams), urlSearchParamsData, checkBodyArrayBuffer, "from URLSearchParams to arrayBuffer");
|
||||
|
||||
checkResponseBody(streamResponsePromise(textData, textResponseInit), textData, checkBodyBlob, "from stream to blob");
|
||||
checkResponseBody(streamResponsePromise(textData), textData, checkBodyText, "from stream to text");
|
||||
checkResponseBody(streamResponsePromise(textData), textData, checkBodyArrayBuffer, "from stream to arrayBuffer");
|
||||
checkResponseBody(streamResponsePromise(textData), textData, checkBodyJSON, "from stream to json");
|
||||
checkResponseBody(streamResponsePromise(formTextData, formTextResponseInit), formTextData, checkBodyFormDataMultipart, "from stream with correct multipart type to formData");
|
||||
checkResponseBody(streamResponsePromise(formTextData), formTextData, checkBodyFormDataError, "from stream without correct multipart type to formData (error case)");
|
||||
checkResponseBody(streamResponsePromise(urlSearchParamsData, urlSearchParamsResponseInit), urlSearchParamsData, checkBodyFormDataUrlencoded, "from stream with correct urlencoded type to formData");
|
||||
checkResponseBody(streamResponsePromise(urlSearchParamsData), urlSearchParamsData, checkBodyFormDataError, "from stream without correct urlencoded type to formData (error case)");
|
||||
|
||||
checkResponseBody(fetch("../resources/top.txt"), "top", checkBodyBlob, "from fetch to blob");
|
||||
checkResponseBody(fetch("../resources/top.txt"), "top", checkBodyText, "from fetch to text");
|
||||
checkResponseBody(fetch("../resources/top.txt"), "top", checkBodyArrayBuffer, "from fetch to arrayBuffer");
|
||||
checkResponseBody(fetch("../resources/top.txt"), "top", checkBodyFormDataError, "from fetch without correct type to formData (error case)");
|
||||
|
||||
promise_test(function(test) {
|
||||
var response = new Response(new Blob([
|
||||
"--boundary\r\n",
|
||||
"Content-Disposition: form-data; name=string\r\n",
|
||||
"\r\nvalue", new Uint8Array([0xC2, 0xA0]), "1\r\n",
|
||||
"--boundary\r\n",
|
||||
"Content-Disposition: form-data; name=string-with-default-charset\r\n",
|
||||
"Content-Type: text/plain; charset=utf-8\r\n",
|
||||
"\r\nvalue", new Uint8Array([0xC2, 0xA0]), "2\r\n",
|
||||
"--boundary\r\n",
|
||||
"Content-Disposition: form-data; name=string-with-non-default-charset\r\n",
|
||||
"Content-Type: text/plain; charset=iso-8859-1\r\n",
|
||||
"\r\nvalue", new Uint8Array([0xC2, 0xA0]), "3\r\n",
|
||||
"--boundary\r\n",
|
||||
"Content-Disposition: form-data; name=string-with-non-default-type\r\n",
|
||||
"Content-Type: application/octet-stream\r\n",
|
||||
"\r\nvalue", new Uint8Array([0xC2, 0xA0]), "4\r\n",
|
||||
"--boundary\r\n",
|
||||
"Content-Disposition: form-data; name=file; filename=file1\r\n",
|
||||
"Content-Type: application/octet-stream; x-param=x-value\r\n",
|
||||
"\r\n", new Uint8Array([5, 0x0, 0xFF]), "\r\n",
|
||||
"--boundary\r\n",
|
||||
"Content-Disposition: form-data; name=\"file-without-type\"; filename=\"file2\"\r\n",
|
||||
"\r\n", new Uint8Array([6, 0x0, 0x7F, 0xFF]), "\r\n",
|
||||
"--boundary--\r\n"
|
||||
]), { "headers": [["Content-Type", 'multipart/form-data; boundary="boundary"']] });
|
||||
return response.formData().then(function(bodyAsFormData) {
|
||||
// Non-file parts must always be decoded using utf-8 encoding.
|
||||
assert_equals(bodyAsFormData.get("string"), "value\u00A01", "Retrieve and verify response's 1st entry value");
|
||||
assert_equals(bodyAsFormData.get("string-with-default-charset"), "value\u00A02", "Retrieve and verify response's 2nd entry value");
|
||||
assert_equals(bodyAsFormData.get("string-with-non-default-charset"), "value\u00A03", "Retrieve and verify response's 3rd entry value");
|
||||
assert_equals(bodyAsFormData.get("string-with-non-default-type"), "value\u00A04", "Retrieve and verify response's 4th entry value");
|
||||
// The name of a File must be taken from the filename parameter in
|
||||
// the Content-Disposition header field.
|
||||
assert_equals(bodyAsFormData.get("file").name, "file1", "Retrieve and verify response's 5th entry name property");
|
||||
assert_equals(bodyAsFormData.get("file-without-type").name, "file2", "Retrieve and verify response's 6th entry name property");
|
||||
// The type of a File must be taken from the Content-Type header field
|
||||
// which defaults to "text/plain".
|
||||
assert_equals(bodyAsFormData.get("file").type, "application/octet-stream; x-param=x-value", "Retrieve and verify response's 5th entry type property");
|
||||
assert_equals(bodyAsFormData.get("file-without-type").type, "text/plain", "Retrieve and verify response's 6th entry type property");
|
||||
|
||||
return Promise.resolve().then(function() {
|
||||
return blobToFormDataResponse("file", bodyAsFormData.get("file")).text().then(function(bodyAsText) {
|
||||
// Verify that filename, name and type are preserved.
|
||||
assert_regexp_match(bodyAsText, /\r\nContent-Disposition: *form-data;([^\r\n]*;)* *filename=("?)file1\2[;\r]/i, "Retrieve and verify response's 5th entry filename parameter");
|
||||
assert_regexp_match(bodyAsText, /\r\nContent-Disposition: *form-data;([^\r\n]*;)* *name=("?)file\2[;\r]/i, "Retrieve and verify response's 5th entry name parameter");
|
||||
assert_regexp_match(bodyAsText, /\r\nContent-Type: *application\/octet-stream; x-param=x-value\r\n/i, "Retrieve and verify response's 5th entry type field");
|
||||
// Verify that the content is preserved.
|
||||
return readBlobAsArrayBuffer(bodyAsFormData.get("file")).then(function(arrayBuffer) {
|
||||
assert_array_equals(new Uint8Array(arrayBuffer), new Uint8Array([5, 0x0, 0xFF]), "Retrieve and verify response's 5th entry content");
|
||||
});
|
||||
});
|
||||
}).then(function() {
|
||||
return blobToFormDataResponse("file-without-type", bodyAsFormData.get("file-without-type")).text().then(function(bodyAsText) {
|
||||
// Verify that filename, name and type are preserved.
|
||||
assert_regexp_match(bodyAsText, /\r\nContent-Disposition: *form-data;([^\r\n]*;)* *filename=("?)file2\2[;\r]/i, "Retrieve and verify response's 6th entry filename parameter");
|
||||
assert_regexp_match(bodyAsText, /\r\nContent-Disposition: *form-data;([^\r\n]*;)* *name=("?)file-without-type\2[;\r]/i, "Retrieve and verify response's 6th entry name parameter");
|
||||
assert_regexp_match(bodyAsText, /\r\nContent-Type: *text\/plain\r\n/i, "Retrieve and verify response's 6th entry type field");
|
||||
// Verify that the content is preserved.
|
||||
return readBlobAsArrayBuffer(bodyAsFormData.get("file-without-type")).then(function(arrayBuffer) {
|
||||
assert_array_equals(new Uint8Array(arrayBuffer), new Uint8Array([6, 0x0, 0x7F, 0xFF]), "Retrieve and verify response's 6th entry content");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}, "Consume response's body: from multipart form data blob to formData");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue