blob: 66ff8841a6966ca2790d486bf5d8208e3fe31195 [file] [log] [blame]
<!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>