369 lines
8.4 KiB
JavaScript
369 lines
8.4 KiB
JavaScript
var boundary = "1234567891011121314151617";
|
|
|
|
// fn(body) should create a Body subclass with content body treated as
|
|
// FormData and return it.
|
|
function testFormDataParsing(fn) {
|
|
function makeTest(shouldPass, input, testFn) {
|
|
var obj = fn(input);
|
|
return obj.formData().then(
|
|
function (fd) {
|
|
ok(shouldPass, "Expected test to be valid FormData for " + input);
|
|
if (testFn) {
|
|
return testFn(fd);
|
|
}
|
|
return undefined;
|
|
},
|
|
function (e) {
|
|
if (shouldPass) {
|
|
ok(false, "Expected test to pass for " + input);
|
|
} else {
|
|
ok(e.name == "TypeError", "Error should be a TypeError.");
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
// [shouldPass?, input, testFn]
|
|
var tests = [
|
|
[
|
|
true,
|
|
|
|
boundary +
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
|
|
function (fd) {
|
|
is(fd.get("greeting"), '"hello"');
|
|
},
|
|
],
|
|
[
|
|
false,
|
|
|
|
// Invalid disposition.
|
|
boundary +
|
|
'\r\nContent-Disposition: form-datafoobar; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
true,
|
|
|
|
"--" +
|
|
boundary +
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
|
|
function (fd) {
|
|
is(fd.get("greeting"), '"hello"');
|
|
},
|
|
],
|
|
[false, boundary + "\r\n\r\n" + boundary + "-"],
|
|
[
|
|
false,
|
|
// No valid ending.
|
|
boundary + "\r\n\r\n" + boundary,
|
|
],
|
|
[
|
|
false,
|
|
|
|
// One '-' prefix is not allowed. 2 or none.
|
|
"-" +
|
|
boundary +
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
"invalid" +
|
|
boundary +
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
"suffix" +
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
"suffix" +
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
// Partial boundary
|
|
boundary.substr(3) +
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
// Missing '\n' at beginning.
|
|
'\rContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
// No form-data.
|
|
'\r\nContent-Disposition: mixed; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
// No headers.
|
|
'\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
// No content-disposition.
|
|
'\r\nContent-Dispositypo: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
// No name.
|
|
'\r\nContent-Disposition: form-data;\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
// Missing empty line between headers and body.
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
// Empty entry followed by valid entry.
|
|
boundary +
|
|
"\r\n\r\n" +
|
|
boundary +
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
|
|
boundary +
|
|
// Header followed by empty line, but empty body not followed by
|
|
// newline.
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
true,
|
|
|
|
boundary +
|
|
// Empty body followed by newline.
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n\r\n' +
|
|
boundary +
|
|
"-",
|
|
|
|
function (fd) {
|
|
is(fd.get("greeting"), "", "Empty value is allowed.");
|
|
},
|
|
],
|
|
[
|
|
false,
|
|
boundary +
|
|
// Value is boundary itself.
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n' +
|
|
boundary +
|
|
"\r\n" +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
false,
|
|
boundary +
|
|
// Variant of above with no valid ending boundary.
|
|
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n' +
|
|
boundary,
|
|
],
|
|
[
|
|
true,
|
|
boundary +
|
|
// Unquoted filename with empty body.
|
|
'\r\nContent-Disposition: form-data; name="file"; filename=file1.txt\r\n\r\n\r\n' +
|
|
boundary +
|
|
"-",
|
|
|
|
function (fd) {
|
|
var f = fd.get("file");
|
|
ok(
|
|
f instanceof File,
|
|
"Entry with filename attribute should be read as File."
|
|
);
|
|
is(f.name, "file1.txt", "Filename should match.");
|
|
is(f.type, "text/plain", "Default content-type should be text/plain.");
|
|
return readAsText(f).then(function (text) {
|
|
is(text, "", "File should be empty.");
|
|
});
|
|
},
|
|
],
|
|
[
|
|
true,
|
|
boundary +
|
|
// Quoted filename with empty body.
|
|
'\r\nContent-Disposition: form-data; name="file"; filename="file1.txt"\r\n\r\n\r\n' +
|
|
boundary +
|
|
"-",
|
|
|
|
function (fd) {
|
|
var f = fd.get("file");
|
|
ok(
|
|
f instanceof File,
|
|
"Entry with filename attribute should be read as File."
|
|
);
|
|
is(f.name, "file1.txt", "Filename should match.");
|
|
is(f.type, "text/plain", "Default content-type should be text/plain.");
|
|
return readAsText(f).then(function (text) {
|
|
is(text, "", "File should be empty.");
|
|
});
|
|
},
|
|
],
|
|
[
|
|
false,
|
|
boundary +
|
|
// Invalid filename
|
|
'\r\nContent-Disposition: form-data; name="file"; filename="[\n@;xt"\r\n\r\n\r\n' +
|
|
boundary +
|
|
"-",
|
|
],
|
|
[
|
|
true,
|
|
boundary +
|
|
'\r\nContent-Disposition: form-data; name="file"; filename="[@;xt"\r\n\r\n\r\n' +
|
|
boundary +
|
|
"-",
|
|
|
|
function (fd) {
|
|
var f = fd.get("file");
|
|
ok(
|
|
f instanceof File,
|
|
"Entry with filename attribute should be read as File."
|
|
);
|
|
is(f.name, "[@", "Filename should match.");
|
|
},
|
|
],
|
|
[
|
|
true,
|
|
boundary +
|
|
'\r\nContent-Disposition: form-data; name="file"; filename="file with spaces"\r\n\r\n\r\n' +
|
|
boundary +
|
|
"-",
|
|
|
|
function (fd) {
|
|
var f = fd.get("file");
|
|
ok(
|
|
f instanceof File,
|
|
"Entry with filename attribute should be read as File."
|
|
);
|
|
is(f.name, "file with spaces", "Filename should match.");
|
|
},
|
|
],
|
|
[
|
|
true,
|
|
boundary +
|
|
"\r\n" +
|
|
'Content-Disposition: form-data; name="file"; filename="xml.txt"\r\n' +
|
|
"content-type : application/xml\r\n" +
|
|
"\r\n" +
|
|
"<body>foobar\r\n\r\n</body>\r\n" +
|
|
boundary +
|
|
"-",
|
|
|
|
function (fd) {
|
|
var f = fd.get("file");
|
|
ok(
|
|
f instanceof File,
|
|
"Entry with filename attribute should be read as File."
|
|
);
|
|
is(f.name, "xml.txt", "Filename should match.");
|
|
is(
|
|
f.type,
|
|
"application/xml",
|
|
"content-type should be application/xml."
|
|
);
|
|
return readAsText(f).then(function (text) {
|
|
is(
|
|
text,
|
|
"<body>foobar\r\n\r\n</body>",
|
|
"File should have correct text."
|
|
);
|
|
});
|
|
},
|
|
],
|
|
];
|
|
|
|
var promises = [];
|
|
for (var i = 0; i < tests.length; ++i) {
|
|
var test = tests[i];
|
|
promises.push(makeTest(test[0], test[1], test[2]));
|
|
}
|
|
|
|
return Promise.all(promises);
|
|
}
|
|
|
|
function makeRequest(body) {
|
|
var req = new Request("", {
|
|
method: "post",
|
|
body,
|
|
headers: {
|
|
"Content-Type": "multipart/form-data; boundary=" + boundary,
|
|
},
|
|
});
|
|
return req;
|
|
}
|
|
|
|
function makeResponse(body) {
|
|
var res = new Response(body, {
|
|
headers: {
|
|
"Content-Type": "multipart/form-data; boundary=" + boundary,
|
|
},
|
|
});
|
|
return res;
|
|
}
|
|
|
|
function runTest() {
|
|
return Promise.all([
|
|
testFormDataParsing(makeRequest),
|
|
testFormDataParsing(makeResponse),
|
|
]);
|
|
}
|