| <!DOCTYPE html> |
| <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) { |
| return new Promise((resolve, reject) => { |
| const iframe = $('iframe'); |
| iframe.onload = () => resolve(iframe.contentWindow.location.search); |
| iframe.onerror = () => reject(new Error('iframe onerror fired')); |
| $('form').submit(); |
| }); |
| } |
| |
| function testSerializedEntry({name, expectedName, value, expectedValue, description}) { |
| 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); |
| } |
| |
| 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', |
| expectedName: 'a%0D%0Ab', |
| expectedValue: 'c', |
| description: 'Newline normalization - \\n in name' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a\rb', |
| value: 'c', |
| expectedName: 'a%0D%0Ab', |
| expectedValue: 'c', |
| description: 'Newline normalization - \\r in name' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a\r\nb', |
| value: 'c', |
| expectedName: 'a%0D%0Ab', |
| expectedValue: 'c', |
| description: 'Newline normalization - \\r\\n in name' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a\n\rb', |
| value: 'c', |
| expectedName: 'a%0D%0A%0D%0Ab', |
| expectedValue: 'c', |
| description: 'Newline normalization - \\n\\r in name' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a', |
| value: 'b\nc', |
| expectedName: 'a', |
| expectedValue: 'b%0D%0Ac', |
| description: 'Newline normalization - \\n in value' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a', |
| value: 'b\rc', |
| expectedName: 'a', |
| expectedValue: 'b%0D%0Ac', |
| description: 'Newline normalization - \\r in value' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a', |
| value: 'b\r\nc', |
| expectedName: 'a', |
| expectedValue: 'b%0D%0Ac', |
| description: 'Newline normalization - \\r\\n in value' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a', |
| value: 'b\n\rc', |
| expectedName: 'a', |
| expectedValue: 'b%0D%0A%0D%0Ac', |
| description: 'Newline normalization - \\n\\r in value' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a', |
| value: new File([], "b\nc"), |
| expectedName: 'a', |
| expectedValue: 'b%0D%0Ac', |
| description: 'Newline normalization - \\n in filename' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a', |
| value: new File([], "b\rc"), |
| expectedName: 'a', |
| expectedValue: 'b%0D%0Ac', |
| description: 'Newline normalization - \\r in filename' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a', |
| value: new File([], "b\r\nc"), |
| expectedName: 'a', |
| expectedValue: 'b%0D%0Ac', |
| description: 'Newline normalization - \\r\\n in filename' |
| }); |
| |
| testSerializedEntry({ |
| name: 'a', |
| value: new File([], "b\n\rc"), |
| expectedName: 'a', |
| expectedValue: 'b%0D%0A%0D%0Ac', |
| description: 'Newline normalization - \\n\\r in filename' |
| }); |
| |
| testSerializedEntry({ |
| value: [['a\nb', 'c']], |
| expectedName: 'a%0Ab', |
| expectedValue: 'c', |
| description: 'Newline normalization - \\n in FormData name' |
| }); |
| |
| testSerializedEntry({ |
| value: [['a\rb', 'c']], |
| expectedName: 'a%0Db', |
| expectedValue: 'c', |
| description: 'Newline normalization - \\r in FormData name' |
| }); |
| |
| testSerializedEntry({ |
| value: [['a\r\nb', 'c']], |
| expectedName: 'a%0D%0Ab', |
| expectedValue: 'c', |
| description: 'Newline normalization - \\r\\n in FormData name' |
| }); |
| |
| testSerializedEntry({ |
| value: [['a\n\rb', 'c']], |
| expectedName: 'a%0A%0Db', |
| expectedValue: 'c', |
| description: 'Newline normalization - \\n\\r in FormData name' |
| }); |
| |
| testSerializedEntry({ |
| value: [['a', 'b\nc']], |
| expectedName: 'a', |
| expectedValue: 'b%0Ac', |
| description: 'Newline normalization - \\n in FormData value' |
| }); |
| |
| testSerializedEntry({ |
| value: [['a', 'b\rc']], |
| expectedName: 'a', |
| expectedValue: 'b%0Dc', |
| description: 'Newline normalization - \\r in FormData value' |
| }); |
| |
| testSerializedEntry({ |
| value: [['a', 'b\r\nc']], |
| expectedName: 'a', |
| expectedValue: 'b%0D%0Ac', |
| description: 'Newline normalization - \\r\\n in FormData value' |
| }); |
| |
| testSerializedEntry({ |
| value: [['a', 'b\n\rc']], |
| expectedName: 'a', |
| expectedValue: 'b%0A%0Dc', |
| description: 'Newline normalization - \\n\\r in FormData value' |
| }); |
| </script> |