summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/fetch/test_formdataparsing.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/tests/mochitest/fetch/test_formdataparsing.js')
-rw-r--r--dom/tests/mochitest/fetch/test_formdataparsing.js368
1 files changed, 368 insertions, 0 deletions
diff --git a/dom/tests/mochitest/fetch/test_formdataparsing.js b/dom/tests/mochitest/fetch/test_formdataparsing.js
new file mode 100644
index 0000000000..5792ddfe01
--- /dev/null
+++ b/dom/tests/mochitest/fetch/test_formdataparsing.js
@@ -0,0 +1,368 @@
+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);
+ }
+ },
+ 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),
+ ]);
+}