summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/FileAPI/support/send-file-formdata-helper.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--testing/web-platform/tests/FileAPI/support/send-file-formdata-helper.js99
1 files changed, 99 insertions, 0 deletions
diff --git a/testing/web-platform/tests/FileAPI/support/send-file-formdata-helper.js b/testing/web-platform/tests/FileAPI/support/send-file-formdata-helper.js
new file mode 100644
index 0000000000..53c8cca7e0
--- /dev/null
+++ b/testing/web-platform/tests/FileAPI/support/send-file-formdata-helper.js
@@ -0,0 +1,99 @@
+"use strict";
+
+const kTestChars = "ABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ";
+
+// formDataPostFileUploadTest - verifies multipart upload structure and
+// numeric character reference replacement for filenames, field names,
+// and field values using FormData and fetch().
+//
+// Uses /fetch/api/resources/echo-content.py to echo the upload
+// POST (unlike in send-file-form-helper.js, here we expect all
+// multipart/form-data request bodies to be UTF-8, so we don't need to
+// escape controls and non-ASCII bytes).
+//
+// Fields in the parameter object:
+//
+// - fileNameSource: purely explanatory and gives a clue about which
+// character encoding is the source for the non-7-bit-ASCII parts of
+// the fileBaseName, or Unicode if no smaller-than-Unicode source
+// contains all the characters. Used in the test name.
+// - fileBaseName: the not-necessarily-just-7-bit-ASCII file basename
+// used for the constructed test file. Used in the test name.
+const formDataPostFileUploadTest = ({
+ fileNameSource,
+ fileBaseName,
+}) => {
+ promise_test(async (testCase) => {
+ const formData = new FormData();
+ let file = new Blob([kTestChars], { type: "text/plain" });
+ try {
+ // Switch to File in browsers that allow this
+ file = new File([file], fileBaseName, { type: file.type });
+ } catch (ignoredException) {
+ }
+
+ // Used to verify that the browser agrees with the test about
+ // field value replacement and encoding independently of file system
+ // idiosyncracies.
+ formData.append("filename", fileBaseName);
+
+ // Same, but with name and value reversed to ensure field names
+ // get the same treatment.
+ formData.append(fileBaseName, "filename");
+
+ formData.append("file", file, fileBaseName);
+
+ const formDataText = await (await fetch(
+ `/fetch/api/resources/echo-content.py`,
+ {
+ method: "POST",
+ body: formData,
+ },
+ )).text();
+ const formDataLines = formDataText.split("\r\n");
+ if (formDataLines.length && !formDataLines[formDataLines.length - 1]) {
+ --formDataLines.length;
+ }
+ assert_greater_than(
+ formDataLines.length,
+ 2,
+ `${fileBaseName}: multipart form data must have at least 3 lines: ${
+ JSON.stringify(formDataText)
+ }`,
+ );
+ const boundary = formDataLines[0];
+ assert_equals(
+ formDataLines[formDataLines.length - 1],
+ boundary + "--",
+ `${fileBaseName}: multipart form data must end with ${boundary}--: ${
+ JSON.stringify(formDataText)
+ }`,
+ );
+
+ const asValue = fileBaseName.replace(/\r\n?|\n/g, "\r\n");
+ const asName = asValue.replace(/[\r\n"]/g, encodeURIComponent);
+ const asFilename = fileBaseName.replace(/[\r\n"]/g, encodeURIComponent);
+ const expectedText = [
+ boundary,
+ 'Content-Disposition: form-data; name="filename"',
+ "",
+ asValue,
+ boundary,
+ `Content-Disposition: form-data; name="${asName}"`,
+ "",
+ "filename",
+ boundary,
+ `Content-Disposition: form-data; name="file"; ` +
+ `filename="${asFilename}"`,
+ "Content-Type: text/plain",
+ "",
+ kTestChars,
+ boundary + "--",
+ ].join("\r\n");
+
+ assert_true(
+ formDataText.startsWith(expectedText),
+ `Unexpected multipart-shaped form data received:\n${formDataText}\nExpected:\n${expectedText}`,
+ );
+ }, `Upload ${fileBaseName} (${fileNameSource}) in fetch with FormData`);
+};