blob: 4c6bb50f61260b129846f2c5229b9592f617b821 [file] [log] [blame]
<!DOCTYPE html>
<body>
<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();
}
get i() { return this.internals_; }
}
customElements.define('my-control', MyControl);
test(() => {
const control = new MyControl();
assert_true(control.i.willValidate, 'default value is true');
const datalist = document.createElement('datalist');
datalist.appendChild(control);
assert_false(control.i.willValidate, 'false in DATALIST');
const fieldset = document.createElement('fieldset');
fieldset.appendChild(control);
assert_true(control.i.willValidate, 'In enabled FIELDSET');
fieldset.disabled = true;
assert_false(control.i.willValidate, 'In disabled FIELDSET');
fieldset.removeChild(control);
control.setAttribute('disabled', '');
assert_false(control.i.willValidate, 'with disabled attribute');
}, 'willValidate');
test(() => {
const control = document.createElement('my-control');
const validity = control.i.validity;
assert_false(validity.valueMissing, 'default valueMissing');
assert_false(validity.typeMismatch, 'default typeMismatch');
assert_false(validity.patternMismatch, 'default patternMismatch');
assert_false(validity.tooLong, 'default tooLong');
assert_false(validity.tooShort, 'default tooShort');
assert_false(validity.rangeUnderflow, 'default rangeUnderflow');
assert_false(validity.rangeOverflow, 'default rangeOverflow');
assert_false(validity.stepMismatch, 'default stepMismatch');
assert_false(validity.badInput, 'default badInput');
assert_false(validity.customError, 'default customError');
assert_true(validity.valid, 'default valid');
control.i.setValidity({valueMissing: true}, 'valueMissing message');
assert_true(validity.valueMissing);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'valueMissing message');
control.i.setValidity({typeMismatch: true}, 'typeMismatch message');
assert_true(validity.typeMismatch);
assert_false(validity.valueMissing);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'typeMismatch message');
control.i.setValidity({patternMismatch: true}, 'patternMismatch message');
assert_true(validity.patternMismatch);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'patternMismatch message');
control.i.setValidity({tooLong: true}, 'tooLong message');
assert_true(validity.tooLong);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'tooLong message');
control.i.setValidity({tooShort: true}, 'tooShort message');
assert_true(validity.tooShort);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'tooShort message');
control.i.setValidity({rangeUnderflow: true}, 'rangeUnderflow message');
assert_true(validity.rangeUnderflow);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'rangeUnderflow message');
control.i.setValidity({rangeOverflow: true}, 'rangeOverflow message');
assert_true(validity.rangeOverflow);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'rangeOverflow message');
control.i.setValidity({stepMismatch: true}, 'stepMismatch message');
assert_true(validity.stepMismatch);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'stepMismatch message');
control.i.setValidity({badInput: true}, 'badInput message');
assert_true(validity.badInput);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'badInput message');
control.i.setValidity({customError: true}, 'customError message');
assert_true(validity.customError, 'customError should be true.');
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'customError message');
// Set multiple flags
control.i.setValidity({badInput: true, customError: true}, 'multiple errors');
assert_true(validity.badInput);
assert_true(validity.customError);
assert_false(validity.valid);
assert_equals(control.i.validationMessage, 'multiple errors');
// Clear flags
control.i.setValidity({}, 'unnecessary message');
assert_false(validity.badInput);
assert_false(validity.customError);
assert_true(validity.valid);
assert_equals(control.i.validationMessage, '');
assert_throws("TypeMismatchError", () => { control.i.setValidity({valueMissing: true}); },
'setValidity() requires the second argument if the first argument contains true');
}, 'validity and setValidity()');
test(() => {
const control = document.createElement('my-control');
let invalidCount = 0;
control.addEventListener('invalid', e => {
assert_equals(e.target, control);
assert_true(e.cancelable);
++invalidCount;
});
assert_true(control.i.checkValidity(), 'default state');
assert_equals(invalidCount, 0);
control.i.setValidity({customError:true}, 'foo');
assert_false(control.i.checkValidity());
assert_equals(invalidCount, 1);
}, 'checkValidity()');
test(() => {
const control = document.createElement('my-control');
document.body.appendChild(control);
control.tabIndex = 0;
let invalidCount = 0;
control.addEventListener('invalid', e => {
assert_equals(e.target, control);
assert_true(e.cancelable);
++invalidCount;
});
assert_true(control.i.reportValidity(), 'default state');
assert_equals(invalidCount, 0);
assert_not_equals(document.activeElement, control);
control.i.setValidity({customError:true}, 'foo');
assert_false(control.i.reportValidity());
assert_equals(invalidCount, 1);
assert_equals(document.activeElement, control);
control.blur();
control.addEventListener('invalid', e => e.preventDefault());
assert_false(control.i.reportValidity());
assert_not_equals(document.activeElement, control);
}, 'reportValidity()');
test(() => {
const container = document.getElementById('container');
container.innerHTML = '<form><input type=submit><my-control>';
const form = container.querySelector('form');
const control = container.querySelector('my-control');
control.tabIndex = 0;
assert_true(control.i.checkValidity());
assert_true(form.checkValidity());
control.i.setValidity({valueMissing: true}, 'Please fill out this field');
assert_false(form.checkValidity());
assert_false(form.reportValidity());
assert_equals(document.activeElement, control);
control.blur();
container.querySelector('input[type=submit]').click();
assert_equals(document.activeElement, control);
}, 'Custom control affects validation at the owner form');
function isValid(element, comment) {
assert_true(element.matches(':valid'), comment ? (comment + ' - :valid') : undefined);
assert_false(element.matches(':invalid'), comment ? (comment + ' - :invalid') : undefined);
}
function isInvalid(element, comment) {
assert_false(element.matches(':valid'), comment ? (comment + ' - :valid') : undefined);
assert_true(element.matches(':invalid'), comment ? (comment + ' - :invalid') : undefined);
}
test(() => {
const container = document.getElementById('container');
container.innerHTML = '<form><fieldset><my-control>';
const form = container.querySelector('form');
const fieldset = container.querySelector('fieldset');
const control = container.querySelector('my-control');
isValid(control);
isValid(form);
isValid(fieldset);
control.i.setValidity({typeMismatch: true}, 'Invalid format');
isInvalid(control);
isInvalid(form);
isInvalid(fieldset);
control.remove();
isValid(form);
isValid(fieldset);
fieldset.appendChild(control);
isInvalid(form);
isInvalid(fieldset);
control.i.setValidity({});
isValid(control);
isValid(form);
isValid(fieldset);
}, ':valid :invalid for FORM and FIELDSET');
</script>
</body>