| <!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> |