summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/custom-elements/form-associated/ElementInternals-setFormValue.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/custom-elements/form-associated/ElementInternals-setFormValue.html')
-rw-r--r--testing/web-platform/tests/custom-elements/form-associated/ElementInternals-setFormValue.html587
1 files changed, 587 insertions, 0 deletions
diff --git a/testing/web-platform/tests/custom-elements/form-associated/ElementInternals-setFormValue.html b/testing/web-platform/tests/custom-elements/form-associated/ElementInternals-setFormValue.html
new file mode 100644
index 0000000000..8a13973f08
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/form-associated/ElementInternals-setFormValue.html
@@ -0,0 +1,587 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="container"></div>
+<script>
+class MyControl extends HTMLElement {
+ static get formAssociated() { return true; }
+
+ constructor() {
+ super();
+ this.internals_ = this.attachInternals();
+ this.value_ = '';
+ }
+
+ get value() {
+ return this.value_;
+ }
+ set value(v) {
+ this.internals_.setFormValue(v);
+ this.value_ = v;
+ }
+ setValues(nameValues) {
+ const formData = new FormData();
+ for (let p of nameValues) {
+ formData.append(p[0], p[1]);
+ }
+ this.internals_.setFormValue(formData);
+ }
+}
+customElements.define('my-control', MyControl);
+const $ = document.querySelector.bind(document);
+
+function submitPromise(t, extractFromIframe) {
+ if (!extractFromIframe) {
+ extractFromIframe = (iframe) => iframe.contentWindow.location.search;
+ }
+ return new Promise((resolve, reject) => {
+ const iframe = $('iframe');
+ iframe.onload = () => resolve(extractFromIframe(iframe));
+ iframe.onerror = () => reject(new Error('iframe onerror fired'));
+ $('form').submit();
+ });
+}
+
+function testSerializedEntry({name, value, expected, description}) {
+ // urlencoded
+ {
+ const {name: expectedName, value: expectedValue} = expected.urlencoded;
+ promise_test(async t => {
+ $('#container').innerHTML = '<form action="/common/blank.html" target="if1">' +
+ '<my-control></my-control>' +
+ '</form>' +
+ '<iframe name="if1"></iframe>';
+ if (name !== undefined) {
+ $('my-control').setAttribute("name", name);
+ }
+ if (Array.isArray(value)) {
+ $('my-control').setValues(value);
+ } else {
+ $('my-control').value = value;
+ }
+ const query = await submitPromise(t);
+ assert_equals(query, `?${expectedName}=${expectedValue}`);
+ }, `${description} (urlencoded)`);
+ }
+
+ // formdata
+ {
+ const {name: expectedName, filename: expectedFilename, value: expectedValue} = expected.formdata;
+ promise_test(async t => {
+ $('#container').innerHTML =
+ '<form action="/FileAPI/file/resources/echo-content-escaped.py" method="post" enctype="multipart/form-data" target="if1">' +
+ '<my-control></my-control>' +
+ '</form>' +
+ '<iframe name="if1"></iframe>';
+ if (name !== undefined) {
+ $('my-control').setAttribute("name", name);
+ }
+ if (Array.isArray(value)) {
+ $('my-control').setValues(value);
+ } else {
+ $('my-control').value = value;
+ }
+ const escaped = await submitPromise(t, iframe => iframe.contentDocument.body.textContent);
+ const formdata = escaped
+ .replace(/\r\n?|\n/g, "\r\n")
+ .replace(
+ /\\x[0-9A-Fa-f]{2}/g,
+ escape => String.fromCodePoint(parseInt(escape.substring(2), 16))
+ );
+ const boundary = formdata.split("\r\n")[0];
+ const expected = [
+ boundary,
+ ...(() => {
+ if (expectedFilename === undefined) {
+ return [`Content-Disposition: form-data; name="${expectedName}"`];
+ } else {
+ return [
+ `Content-Disposition: form-data; name="${expectedName}"; filename="${expectedFilename}"`,
+ "Content-Type: text/plain"
+ ];
+ }
+ })(),
+ "",
+ expectedValue,
+ boundary + "--",
+ ""
+ ].join("\r\n");
+ assert_equals(formdata, expected);
+ }, `${description} (formdata)`);
+ }
+}
+
+promise_test(t => {
+ $('#container').innerHTML = '<form action="/common/blank.html" target="if1">' +
+ '<input name=name-pd1 value="value-pd1">' +
+ '<my-control></my-control>' +
+ '</form>' +
+ '<iframe name="if1"></iframe>';
+ return submitPromise(t).then(query => {
+ assert_equals(query, '?name-pd1=value-pd1');
+ });
+}, 'Single value - name is missing');
+
+promise_test(t => {
+ $('#container').innerHTML = '<form action="/common/blank.html" target="if1">' +
+ '<input name=name-pd1 value="value-pd1">' +
+ '<my-control name=""></my-control>' +
+ '<input name=name-pd2 value="value-pd2">' +
+ '</form>' +
+ '<iframe name="if1"></iframe>';
+ $('my-control').value = 'value-ce1';
+ return submitPromise(t).then(query => {
+ assert_equals(query, '?name-pd1=value-pd1&name-pd2=value-pd2');
+ });
+}, 'Single value - empty name exists');
+
+promise_test(t => {
+ $('#container').innerHTML = '<form action="/common/blank.html" target="if1" accept-charset=utf-8>' +
+ '<input name=name-pd1 value="value-pd1">' +
+ '<my-control name="name-ce1"></my-control>' +
+ '<my-control name="name-usv"></my-control>' +
+ '<my-control name="name-file"></my-control>' +
+ '</form>' +
+ '<iframe name="if1"></iframe>';
+ const USV_INPUT = 'abc\uDC00\uD800def';
+ const USV_OUTPUT = 'abc\uFFFD\uFFFDdef';
+ const FILE_NAME = 'test_file.txt';
+ $('[name=name-usv]').value = USV_INPUT;
+ $('[name=name-file]').value = new File(['file content'], FILE_NAME);
+ return submitPromise(t).then(query => {
+ assert_equals(query, `?name-pd1=value-pd1&name-usv=${encodeURIComponent(USV_OUTPUT)}&name-file=${FILE_NAME}`);
+ });
+}, 'Single value - Non-empty name exists');
+
+promise_test(t => {
+ $('#container').innerHTML = '<form action="/common/blank.html" target="if1">' +
+ '<input name=name-pd1 value="value-pd1">' +
+ '<my-control name="name-ce1"></my-control>' +
+ '<my-control name="name-ce2"></my-control>' +
+ '</form>' +
+ '<iframe name="if1"></iframe>';
+ $('my-control').value = null;
+ return submitPromise(t).then(query => {
+ assert_equals(query, '?name-pd1=value-pd1');
+ });
+}, 'Null value should submit nothing');
+
+promise_test(t => {
+ $('#container').innerHTML = '<form action="/common/blank.html" target="if1">' +
+ '<input name=name-pd1 value="value-pd1">' +
+ '<my-control name=name-ce1></my-control>' +
+ '</form>' +
+ '<iframe name="if1"></iframe>';
+ $('my-control').value = 'value-ce1';
+ $('my-control').setValues([]);
+ $('my-control').setValues([['sub1', 'subvalue1'],
+ ['sub2', 'subvalue2'],
+ ['sub2', 'subvalue3']]);
+ return submitPromise(t).then(query => {
+ assert_equals(query, '?name-pd1=value-pd1&sub1=subvalue1&sub2=subvalue2&sub2=subvalue3');
+ });
+}, 'Multiple values - name content attribute is ignored');
+
+promise_test(t => {
+ $('#container').innerHTML = '<form action="/common/blank.html" target="if1">' +
+ '<input name=name-pd1 value="value-pd1">' +
+ '<my-control name=name-ce1></my-control>' +
+ '</form>' +
+ '<iframe name="if1"></iframe>';
+ $('my-control').value = 'value-ce1';
+ $('my-control').setValues([]);
+ return submitPromise(t).then(query => {
+ assert_equals(query, '?name-pd1=value-pd1');
+ });
+}, 'setFormValue with an empty FormData should submit nothing');
+
+testSerializedEntry({
+ name: 'a\nb',
+ value: 'c',
+ expected: {
+ urlencoded: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ },
+ formdata: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ }
+ },
+ description: 'Newline normalization - \\n in name'
+});
+
+testSerializedEntry({
+ name: 'a\rb',
+ value: 'c',
+ expected: {
+ urlencoded: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ },
+ formdata: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ }
+ },
+ description: 'Newline normalization - \\r in name'
+});
+
+testSerializedEntry({
+ name: 'a\r\nb',
+ value: 'c',
+ expected: {
+ urlencoded: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ },
+ formdata: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ }
+ },
+ description: 'Newline normalization - \\r\\n in name'
+});
+
+testSerializedEntry({
+ name: 'a\n\rb',
+ value: 'c',
+ expected: {
+ urlencoded: {
+ name: 'a%0D%0A%0D%0Ab',
+ value: 'c'
+ },
+ formdata: {
+ name: 'a%0D%0A%0D%0Ab',
+ value: 'c'
+ }
+ },
+ description: 'Newline normalization - \\n\\r in name'
+});
+
+testSerializedEntry({
+ name: 'a',
+ value: 'b\nc',
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ value: 'b\r\nc'
+ }
+ },
+ description: 'Newline normalization - \\n in value'
+});
+
+testSerializedEntry({
+ name: 'a',
+ value: 'b\rc',
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ value: 'b\r\nc'
+ }
+ },
+ description: 'Newline normalization - \\r in value'
+});
+
+testSerializedEntry({
+ name: 'a',
+ value: 'b\r\nc',
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ value: 'b\r\nc'
+ }
+ },
+ description: 'Newline normalization - \\r\\n in value'
+});
+
+testSerializedEntry({
+ name: 'a',
+ value: 'b\n\rc',
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0A%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ value: 'b\r\n\r\nc'
+ }
+ },
+ description: 'Newline normalization - \\n\\r in value'
+});
+
+testSerializedEntry({
+ name: 'a',
+ value: new File([], "b\nc", {type: "text/plain"}),
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ filename: 'b%0Ac',
+ value: ''
+ }
+ },
+ description: 'Newline normalization - \\n in filename'
+});
+
+testSerializedEntry({
+ name: 'a',
+ value: new File([], "b\rc", {type: "text/plain"}),
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ filename: 'b%0Dc',
+ value: ''
+ }
+ },
+ description: 'Newline normalization - \\r in filename'
+});
+
+testSerializedEntry({
+ name: 'a',
+ value: new File([], "b\r\nc", {type: "text/plain"}),
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ filename: 'b%0D%0Ac',
+ value: ''
+ }
+ },
+ description: 'Newline normalization - \\r\\n in filename'
+});
+
+testSerializedEntry({
+ name: 'a',
+ value: new File([], "b\n\rc", {type: "text/plain"}),
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0A%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ filename: 'b%0A%0Dc',
+ value: ''
+ }
+ },
+ description: 'Newline normalization - \\n\\r in filename'
+});
+
+testSerializedEntry({
+ value: [['a\nb', 'c']],
+ expected: {
+ urlencoded: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ },
+ formdata: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ }
+ },
+ description: 'Newline normalization - \\n in FormData name'
+});
+
+testSerializedEntry({
+ value: [['a\rb', 'c']],
+ expected: {
+ urlencoded: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ },
+ formdata: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ }
+ },
+ description: 'Newline normalization - \\r in FormData name'
+});
+
+testSerializedEntry({
+ value: [['a\r\nb', 'c']],
+ expected: {
+ urlencoded: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ },
+ formdata: {
+ name: 'a%0D%0Ab',
+ value: 'c'
+ }
+ },
+ description: 'Newline normalization - \\r\\n in FormData name'
+});
+
+testSerializedEntry({
+ value: [['a\n\rb', 'c']],
+ expected: {
+ urlencoded: {
+ name: 'a%0D%0A%0D%0Ab',
+ value: 'c'
+ },
+ formdata: {
+ name: 'a%0D%0A%0D%0Ab',
+ value: 'c'
+ }
+ },
+ description: 'Newline normalization - \\n\\r in FormData name'
+});
+
+testSerializedEntry({
+ value: [['a', 'b\nc']],
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ value: 'b\r\nc'
+ }
+ },
+ description: 'Newline normalization - \\n in FormData value'
+});
+
+testSerializedEntry({
+ value: [['a', 'b\rc']],
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ value: 'b\r\nc'
+ }
+ },
+ description: 'Newline normalization - \\r in FormData value'
+});
+
+testSerializedEntry({
+ value: [['a', 'b\r\nc']],
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ value: 'b\r\nc'
+ }
+ },
+ description: 'Newline normalization - \\r\\n in FormData value'
+});
+
+testSerializedEntry({
+ value: [['a', 'b\n\rc']],
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0A%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ value: 'b\r\n\r\nc'
+ }
+ },
+ description: 'Newline normalization - \\n\\r in FormData value'
+});
+
+testSerializedEntry({
+ value: [['a', new File([], 'b\nc', {type: "text/plain"})]],
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ filename: 'b%0Ac',
+ value: ''
+ }
+ },
+ description: 'Newline normalization - \\n in FormData filename'
+});
+
+testSerializedEntry({
+ value: [['a', new File([], 'b\rc', {type: "text/plain"})]],
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ filename: 'b%0Dc',
+ value: ''
+ }
+ },
+ description: 'Newline normalization - \\r in FormData filename'
+});
+
+testSerializedEntry({
+ value: [['a', new File([], 'b\r\nc', {type: "text/plain"})]],
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ filename: 'b%0D%0Ac',
+ value: ''
+ }
+ },
+ description: 'Newline normalization - \\r\\n in FormData filename'
+});
+
+testSerializedEntry({
+ value: [['a', new File([], 'b\n\rc', {type: "text/plain"})]],
+ expected: {
+ urlencoded: {
+ name: 'a',
+ value: 'b%0D%0A%0D%0Ac'
+ },
+ formdata: {
+ name: 'a',
+ filename: 'b%0A%0Dc',
+ value: ''
+ }
+ },
+ description: 'Newline normalization - \\n\\r in FormData filename'
+});
+
+test(() => {
+ class NotFormAssociatedElement extends HTMLElement {}
+ customElements.define('not-form-associated-element', NotFormAssociatedElement);
+ const element = new NotFormAssociatedElement();
+ const i = element.attachInternals();
+ assert_throws_dom('NotSupportedError', () => i.setFormValue("test"));
+}, "ElementInternals.setFormValue() should throw NotSupportedError if the target element is not a form-associated custom element");
+
+</script>