summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/semantics/forms
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/html/semantics/forms
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/html/semantics/forms')
-rw-r--r--testing/web-platform/tests/html/semantics/forms/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/contains.json34
-rw-r--r--testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr-iframe.html4
-rw-r--r--testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html29
-rw-r--r--testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl-manual.html26
-rw-r--r--testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/disabled-elements-01.html84
-rw-r--r--testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address.html74
-rw-r--r--testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/formaction.html42
-rw-r--r--testing/web-platform/tests/html/semantics/forms/categories/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/contains.json18
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-checkValidity.html145
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-reportValidity.html145
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validate.html127
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-badInput.html46
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-customError.html48
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-patternMismatch.html27
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-rangeOverflow.html115
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-rangeUnderflow.html113
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-stepMismatch.html77
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooLong.html50
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html52
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-typeMismatch.html41
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-valid.html130
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-valueMissing.html168
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/form-validation-willValidate.html90
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/inputwillvalidate.html26
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/support/validator.js377
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-email-delete-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-password-delete-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-search-delete-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-tel-delete-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-text-delete-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-url-delete-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/constraints/tooLong-textarea-delete-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/contains.json14
-rw-r--r--testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form.html97
-rw-r--r--testing/web-platform/tests/html/semantics/forms/form-submission-0/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/form-submission-0/contains.json30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/form-submission-0/getactionurl.html39
-rw-r--r--testing/web-platform/tests/html/semantics/forms/form-submission-0/submit-entity-body.html113
-rw-r--r--testing/web-platform/tests/html/semantics/forms/form-submission-0/url-encoded.html46
-rw-r--r--testing/web-platform/tests/html/semantics/forms/historical.html85
-rw-r--r--testing/web-platform/tests/html/semantics/forms/introduction-1/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/introduction-1/contains.json34
-rw-r--r--testing/web-platform/tests/html/semantics/forms/resetting-a-form/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/resetting-a-form/reset-form.html105
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/original-id.json1
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/select-event.html45
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-after-content-change.html18
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-not-application-textarea.html20
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-not-application.html48
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/selection.html145
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html120
-rw-r--r--testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html274
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-button-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-button-element/button-activate-frame.html3
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-button-element/button-activate.html17
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-button-element/button-events.html66
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-button-element/button-validation.html29
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-datalist-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-datalist-element/datalistoptions.html43
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-fieldset-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html54
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-001.html71
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-002.xhtml25
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/form-autocomplete.html59
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-interfaces-01.html20
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-matches.html46
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-nameditem-01.html43
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-nameditem-02.html28
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-sameobject.html20
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/form-indexed-element.html45
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-form-element/form-nameditem.html330
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/button.html66
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/checkbox.html149
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/checked.xhtml19
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/clone.html150
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/cloning-steps.html53
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/color.html45
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/contains.json154
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/date.html90
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/datetime-local.html36
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/datetime.html106
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/email.html58
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/file-manual.html30
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/files.html48
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/hidden.html74
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/image01-ref.html5
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/image01.html7
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/input-type-button.html51
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/input-type-checkbox.html60
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/maxlength-manual.html37
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/maxlength.html55
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/minlength.html55
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/month.html65
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/number.html53
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/password.html79
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/pattern_attribute.html34
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/radio-groupname-case.html75
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/radio.html144
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/range-2.html43
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/range.html276
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/required_attribute.html34
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/reset.html113
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/search_input.html35
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/selection.html135
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/telephone.html84
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/text.html104
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/time-2.html42
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/time.html207
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/type-change-state.html62
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/url.html59
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/valueMode.html72
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-input-element/week.html38
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-keygen-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-label-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-label-element/label-attributes.html137
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-label-element/labelable-elements.html156
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-legend-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-legend-element/legend-form.html33
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-meter-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-meter-element/meter.html250
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-optgroup-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-optgroup-element/optgroup-disabled-manual.html35
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-disabled-manual.html28
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-form.html32
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-label-value.js82
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-label.html12
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-selected.html61
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-backslash.html15
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-label.html23
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-recurse.html92
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-spaces.html75
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-option-element/option-value.html12
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-output-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-output-element/output.html39
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-progress-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-progress-element/progress-2.html34
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-progress-element/progress.html74
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection-namedItem.html54
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html70
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-ask-for-reset.html97
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-named-getter.html46
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-remove.html64
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/.gitkeep0
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/cloning-steps.html34
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html19
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html23
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-placeholder-manual.html14
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-select-event-manual.html31
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-select-manual.html13
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-type.html16
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1-ref.html5
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1a.html9
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1b.html9
163 files changed, 9227 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/forms/.gitkeep b/testing/web-platform/tests/html/semantics/forms/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/.gitkeep b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/contains.json b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/contains.json
new file mode 100644
index 000000000..357a1e6a7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/contains.json
@@ -0,0 +1,34 @@
+[
+ {
+ "id": "naming-form-controls-the-name-attribute",
+ "original_id": "naming-form-controls:-the-name-attribute"
+ },
+ {
+ "id": "submitting-element-directionality-the-dirname-attribute",
+ "original_id": "submitting-element-directionality:-the-dirname-attribute"
+ },
+ {
+ "id": "limiting-user-input-length-the-maxlength-attribute",
+ "original_id": "limiting-user-input-length:-the-maxlength-attribute"
+ },
+ {
+ "id": "enabling-and-disabling-form-controls-the-disabled-attribute",
+ "original_id": "enabling-and-disabling-form-controls:-the-disabled-attribute"
+ },
+ {
+ "id": "form-submission",
+ "original_id": "form-submission"
+ },
+ {
+ "id": "autofocusing-a-form-control-the-autofocus-attribute",
+ "original_id": "autofocusing-a-form-control:-the-autofocus-attribute"
+ },
+ {
+ "id": "input-modalities-the-inputmode-attribute",
+ "original_id": "input-modalities:-the-inputmode-attribute"
+ },
+ {
+ "id": "autofilling-form-controls-the-autocomplete-attribute",
+ "original_id": "autofilling-form-controls:-the-autocomplete-attribute"
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr-iframe.html b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr-iframe.html
new file mode 100644
index 000000000..b5ed7e3d9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr-iframe.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Submitting element directionality: the dirname attribute support</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
diff --git a/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html
new file mode 100644
index 000000000..28d1c150b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Submitting element directionality: the dirname attribute</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#submitting-element-directionality:-the-dirname-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form action="dirname-ltr-iframe.html" method=get target="iframe">
+ <p><label>Comment: <input type=text name="comment" dirname="comment.dir" required></label></p>
+ <p><button type=submit>Post Comment</button></p>
+</form>
+<iframe name="iframe"></iframe>
+<script>
+ function getParameterByName(name) {
+ name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
+ var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
+ results = regex.exec(document.querySelector("iframe").contentWindow.location.search);
+ return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
+ }
+
+ var t = async_test("submit element directionality");
+ document.querySelector("input").value="foobar";
+ document.querySelector("button").click();
+
+ document.querySelector("iframe").onload = t.step_func_done(function() {
+ assert_equals(getParameterByName("comment.dir"), "ltr");
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl-manual.html b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl-manual.html
new file mode 100644
index 000000000..cb00f6972
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl-manual.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Submitting element directionality: the dirname attribute (rtl)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#submitting-element-directionality:-the-dirname-attribute">
+<form action="dirname-rtl-manual.html" method=get>
+ <p><label>Comment: <input type=text name="comment" dirname="comment.dir" required></label></p>
+ <p><button type=submit>Post Comment</button></p>
+</form>
+<p>Switch to a right-to-left writing direction, enter a text in the input and submit the form.</p>
+<p>Test passes if the word "PASS" appears below</p>
+<script>
+ function getParameterByName(name) {
+ name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
+ var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
+ results = regex.exec(location.search);
+ return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
+ }
+
+ var commentDir = getParameterByName("comment.dir");
+ if (commentDir) {
+ var p = document.createElement("p");
+ p.textContent = (commentDir == "rtl") ? "PASS" : "FAIL";
+ document.body.appendChild(p);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/disabled-elements-01.html b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/disabled-elements-01.html
new file mode 100644
index 000000000..14443e409
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/disabled-elements-01.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<title>HTMLFormElement: the disabled attribute</title>
+<link rel="author" title="Eric Casler" href="mailto:ericorange@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#enabling-and-disabling-form-controls:-the-disabled-attribute">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<div id="root"></div>
+<script>
+// Elements tested for in this file
+var types = ["button", "input", "select", "textarea"];
+// no tests for: optgroup, option, fieldset
+
+var root = document.getElementById("root");
+for (var element_type = 0; element_type < types.length; element_type++) {
+ test(function() {
+ root.innerHTML = "<"+types[element_type]+" + id='elem'></"+types[element_type]+">";
+
+ var elem = document.getElementById("elem");
+ assert_false(elem.disabled);
+ },
+ "Test ["+types[element_type]+"]: default behaviour is NOT disabled");
+
+ test(function() {
+ var formats = ["disabled",
+ "disabled=disabled", "disabled='disabled'",
+ "disabled='true'", "disabled=true",
+ "disabled='false'", "disabled=false"];
+
+ for (var f = 0; f < formats.length; f++) {
+ root.innerHTML = "<"+types[element_type]+" id='elem' " + formats[f] + "></"+types[element_type]+">";
+
+ var elem = document.getElementById("elem");
+ assert_true(elem.disabled);
+ }
+ },
+ "Test ["+types[element_type]+"]: verify disabled acts as boolean attribute");
+
+ test(function() {
+ root.innerHTML = "<"+types[element_type]+" id='elem'></"+types[element_type]+"><input id='other' value='no event dispatched'></input>";
+ var elem = document.getElementById("elem"),
+ other = document.getElementById("other");
+
+ assert_equals(other.value, "no event dispatched");
+
+ elem.disabled = true;
+ assert_true(elem.disabled);
+
+ elem.onclick = function () {
+ // change value of other element, to avoid *.value returning "" for disabled elements
+ document.getElementById("other").value = "event dispatched";
+ };
+
+ // Check if dispatched event executes
+ var evObj = document.createEvent('Events');
+ evObj.initEvent("click", true, false);
+ elem.dispatchEvent(evObj);
+ assert_equals(other.value, "event dispatched");
+ },
+ "Test ["+types[element_type]+"]: synthetic click events should be dispatched");
+
+ test(function() {
+ root.innerHTML = "<"+types[element_type]+" id='elem'></"+types[element_type]+"><input id='other' value='no event dispatched'></input>";
+ var elem = document.getElementById("elem"),
+ other = document.getElementById("other");
+
+ assert_equals(other.value, "no event dispatched");
+
+ elem.disabled = true;
+ assert_true(elem.disabled);
+
+ elem.onclick = function () {
+ // change value of other element, to avoid *.value returning "" for disabled elements
+ document.getElementById("other").value = "event dispatched";
+ };
+
+ // Check that click() on a disabled element doesn't dispatch a click event.
+ elem.click();
+ assert_equals(other.value, "no event dispatched");
+ },
+ "Test ["+types[element_type]+"]: click() should not dispatch a click event");
+}
+root.innerHTML = "";
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address.html b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address.html
new file mode 100644
index 000000000..d14cad532
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: formAction_document_address</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-fs-formaction">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-document's-address">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-button-element">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <meta name="assert" content="On getting the formAction IDL attribute, when the content attribute is missing or its value is the empty string, the document's address must be returned instead.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <div id="missing" style="display:none">
+ <button type="submit">Submit</button>
+ <input type="submit">
+ </div>
+
+ <div id="empty_string" style="display:none">
+ <button type="submit" formaction="">Submit</button>
+ <input type="submit" formaction="">
+ </div>
+
+ <div id="no_assigned_value" style="display:none">
+ <button type="submit" formaction>Submit</button>
+ <input type="submit" formaction>
+ </div>
+
+ <script>
+ // formaction content attribute is missing
+ test(function() {
+ var formAction = document.querySelector('#missing button').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if button.formAction is the document's address when formaction content attribute is missing");
+
+ test(function() {
+ var formAction = document.querySelector('#missing input').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if input.formAction is the document's address when formaction content attribute is missing");
+
+ // formaction content attribute value is empty string
+ test(function() {
+ var formAction = document.querySelector('#empty_string button').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if button.formAction is the document's address when formaction content attribute value is empty string");
+
+ test(function() {
+ var formAction = document.querySelector('#empty_string input').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if input.formAction is the document's address when formaction content attribute value is empty string");
+
+ // formaction content attribute value is not assigned, just for comparison with empty string above
+ test(function() {
+ var formAction = document.querySelector('#no_assigned_value button').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if button.formAction is the document's address when formaction content attribute value is not assigned");
+
+ test(function() {
+ var formAction = document.querySelector('#no_assigned_value input').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if input.formAction is the document's address when formaction content attribute value is not assigned");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/formaction.html b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/formaction.html
new file mode 100644
index 000000000..82798eaa8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/attributes-common-to-form-controls/formaction.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html><head>
+ <title>formaction on button element</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="content-type">
+ <meta content="formaction on button element" name="description">
+ <link href="https://html.spec.whatwg.org/multipage/#dom-fs-formaction" rel="help">
+</head>
+ <body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <div id="log"></div>
+ <button formaction="http://www.example.com/" style="display: none" type="submit">Submit</button>
+ <input formaction="http://www.example.com/" style="display: none" type="submit" value="submit">
+ <input style="display: none" type="submit" value="submit">
+ <input formaction="" style="display: none" type="submit" value="submit">
+
+ <script type="text/javascript">
+ function relativeToAbsolute(relativeURL) {
+ var a = document.createElement('a');
+ a.href = relativeURL;
+ return a.href;
+ }
+ test(function() {assert_equals(document.getElementsByTagName("button")[0].formAction, "http://www.example.com/")}, "formAction on button support");
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].formAction, "http://www.example.com/")}, "formAction on input support");
+
+ var testElem = document.getElementsByTagName("input")[0];
+ testElem.formAction = "http://www.example.com/page2.html";
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].formAction, "http://www.example.com/page2.html")}, "formaction absolute URL value on input reflects correct value after being updated by the DOM");
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].getAttribute("formaction"), "http://www.example.com/page2.html")}, "formAction absolute URL value is correct using getAttribute");
+
+ var testElem = document.getElementsByTagName("input")[0];
+ testElem.formAction = "../page3.html";
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].formAction, relativeToAbsolute('../page3.html'))}, "formAction relative URL value on input reflects correct value after being updated by the DOM");
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].getAttribute("formaction"), "../page3.html")}, "formAction relative URL value is correct using getAttribute");
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].formAction, document.URL)}, "On getting, when formaction is missing, the document's address must be returned");
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].formAction, document.URL)}, "On getting, when formaction value is the empty string, the document's address must be returned");
+ </script>
+</body></html>
diff --git a/testing/web-platform/tests/html/semantics/forms/categories/.gitkeep b/testing/web-platform/tests/html/semantics/forms/categories/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/categories/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/.gitkeep b/testing/web-platform/tests/html/semantics/forms/constraints/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/contains.json b/testing/web-platform/tests/html/semantics/forms/constraints/contains.json
new file mode 100644
index 000000000..67e4c3b12
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/contains.json
@@ -0,0 +1,18 @@
+[
+ {
+ "id": "definitions",
+ "original_id": "definitions"
+ },
+ {
+ "id": "constraint-validation",
+ "original_id": "constraint-validation"
+ },
+ {
+ "id": "the-constraint-validation-api",
+ "original_id": "the-constraint-validation-api"
+ },
+ {
+ "id": "security-forms",
+ "original_id": "security-forms"
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-checkValidity.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-checkValidity.html
new file mode 100644
index 000000000..2e790c75d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-checkValidity.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.checkValidity()</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-cva-checkvalidity">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "password"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "4", value: "abcdef"}, expected: true, name: "[target] not suffering from being too long", dirty: true},
+ {conditions: {pattern: "[A-Z]", value: "abc"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["url"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "20", value: "http://www.example.com"}, expected: true, name: "[target] suffering from being too long", dirty: true},
+ {conditions: {pattern: "http://www.example.com", value: "http://www.example.net"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] suffering from a type mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "10", value: "test@example.com"}, expected: true, name: "[target] not suffering from being too long", dirty: true},
+ {conditions: {pattern: "test@example.com", value: "test@example.net"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] suffering from a type mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01-01T12:00:00", value: "2001-01-01T12:00:00"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01-01T12:00:00", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 60 * 1000, value: "2001-01-01T12:03:00"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01-01", value: "2001-01-01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01-01", value: "2000-01-01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 86400000, value: "2001-01-03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01", value: "2001-01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01", value: "2000-01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 3 * 1 * 1, value: "2001-03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-W01", value: "2001-W01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-W01", value: "2000-W01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 604800000, value: "2001-W03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "12:00:00", value: "11:00:00"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 60 * 1000, value: "12:03:00"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {max: "5", value: "6"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "5", value: "4"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 1, value: "3"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["checkbox", "radio"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, checked: false, name: "test1"}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["file"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, files: null}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "checkValidity");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-reportValidity.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-reportValidity.html
new file mode 100644
index 000000000..c68e21c9d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-reportValidity.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.reportValidity()</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "password"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "4", value: "abcdef"}, expected: true, name: "[target] not suffering from being too long", dirty: true},
+ {conditions: {pattern: "[A-Z]", value: "abc"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["url"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "20", value: "http://www.example.com"}, expected: true, name: "[target] not suffering from being too long", dirty: true},
+ {conditions: {pattern: "http://www.example.com", value: "http://www.example.net"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] suffering from a type mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "10", value: "test@example.com"}, expected: true, name: "[target] not suffering from being too long", dirty: true},
+ {conditions: {pattern: "test@example.com", value: "test@example.net"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] suffering from a type mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01-01T12:00:00", value: "2001-01-01T12:00:00"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01-01T12:00:00", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 60 * 1000, value: "2001-01-01T12:03:00"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01-01", value: "2001-01-01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01-01", value: "2000-01-01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 86400000, value: "2001-01-03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01", value: "2001-01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01", value: "2000-01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 3 * 1 * 1, value: "2001-03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-W01", value: "2001-W01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-W01", value: "2000-W01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 604800000, value: "2001-W03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "12:00:00", value: "11:00:00"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 60 * 1000, value: "12:03:00"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {max: "5", value: "6"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "5", value: "4"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 1, value: "3"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["checkbox", "radio"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, checked: false, name: "test1"}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["file"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, files: null}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "reportValidity");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validate.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validate.html
new file mode 100644
index 000000000..47b41ffeb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validate.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Constraint validation</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#constraint-validation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id="fm1" style="display:none">
+ <fieldset id="test0">
+ <input type="text" required value="" id="test1">
+ </fieldset>
+ <input type="email" value="abc" id="test2">
+ <button id="test3">TEST</button>
+ <select id="test4"></select>
+ <textarea id="test5"></textarea>
+ <output id="test6"></output>
+</form>
+<form id="fm2" style="display:none">
+ <fieldset>
+ <input type="text" required value="abc">
+ </fieldset>
+ <input type="email" value="test@example.com">
+ <button>TEST</button>
+ <select></select>
+ <textarea></textarea>
+ <output></output>
+</form>
+<form id="fm3" style="display:none">
+ <fieldset id="fs">
+ <legend><input type="text" id="inp1"></legend>
+ <input type="text" required value="" id="inp2">
+ </fieldset>
+</form>
+
+<script>
+ var cancelable = true,
+ times1 = 0,
+ times2 = 0,
+ invalidList1 = [],
+ invalidList2 = [],
+ test1,
+ test2,
+ fm1,
+ fm2,
+ fm3;
+
+ setup(function () {
+ fm1 = document.getElementById("fm1");
+ fm2 = document.getElementById("fm2");
+ fm3 = document.getElementById("fm3");
+ test1 = document.getElementById("test1");
+ test2 = document.getElementById("test2");
+ for (var index = 0; index < fm1.elements.length; index++) {
+ var ele = fm1.elements.item(index);
+ ele.addEventListener("invalid", function (e) {
+ times1++;
+ invalidList1.push(e.target);
+ if (!e.cancelable)
+ cancelable = e.cancelable;
+ }, false);
+ }
+
+ for (var index = 0; index < fm1.elements.length; index++) {
+ var ele = fm2.elements.item(index);
+ ele.addEventListener("invalid", function (e) {
+ times2++;
+ invalidList2.push(ele);
+ }, false);
+ }
+ });
+
+ test(function(){
+ assert_false(fm1.checkValidity(), "The checkValidity method should be false.");
+ }, "If there is any invalid submittable element whose form owner is the form, the form.checkValidity must be false");
+
+ test(function(){
+ assert_true("reportValidity" in fm1, "The reportValidity method is not supported");
+ assert_false(fm1.reportValidity(), "The reportValidity method should be false.");
+ }, "If there is any invalid submittable element whose form owner is the form, the form.reportValidity must be false");
+
+ test(function(){
+ assert_true(fm2.checkValidity(), "The checkValidity method should be true.");
+ }, "If all of the submittable elements whose form owner is the form are valid, the form.checkValidity must be true");
+
+ test(function(){
+ assert_true("reportValidity" in fm2, "The reportValidity method is not supported.");
+ assert_true(fm2.reportValidity(), "The reportValidity method should be true.");
+ }, "If all of the submittable elements whose form owner is the form are valid, the form.reportValidity must be true");
+
+ test(function(){
+ assert_false(fm3.checkValidity(), "The checkValidity method should be false.");
+ document.getElementById("fs").disabled = true;
+ assert_true(fm3.checkValidity(), "The checkValidity method should be true.");
+
+ document.getElementById("inp1").value = "aaa";
+ document.getElementById("inp1").type = "url";
+ assert_false(fm3.checkValidity(), "The checkValidity method should be false.");
+ }, "Check the checkValidity method of the form element when it has a fieldset child");
+
+ test(function(){
+ // Restore the condition to default which was modified during the previous test.
+ document.getElementById("fs").disabled = false;
+ document.getElementById("inp1").value = "";
+ document.getElementById("inp1").type = "text";
+
+ assert_true("reportValidity" in fm3, "The reportValidity method is not supported.");
+ assert_false(fm3.reportValidity(), "The reportValidity method should be false.");
+ document.getElementById("fs").disabled = true;
+ assert_true(fm3.reportValidity(), "The reportValidity method should be true.");
+
+ document.getElementById("inp1").value = "aaa";
+ document.getElementById("inp1").type = "url";
+ assert_false(fm3.reportValidity(), "The reportValidity method should be false.");
+ }, "Check the reportValidity method of the form element when it has a fieldset child");
+
+ test(function () {
+ assert_equals(times1, 4, "The invalid event will be fired if the checkValidity or reportValidity method are called.");
+ assert_array_equals(invalidList1, [test1, test2, test1, test2], "The invalid event must be fired at the invalid control");
+ assert_true(cancelable, "The invalid event is cancelable.");
+ }, "The invalid event must be fired at the invalid controls");
+
+ test(function () {
+ assert_equals(times2, 0, "The invalid event should not be fired, times should be 0.");
+ assert_array_equals(invalidList2, [], "The invalid event should not be fired, invalid list should be empty");
+ }, "The invalid event must not be fired at the invalid controls");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-badInput.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-badInput.html
new file mode 100644
index 000000000..8f6153b92
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-badInput.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.badInput</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/association-of-controls-and-forms.html#suffering-from-bad-input">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/the-button-element.html#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+var testElements = [
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ {conditions: {multiple: false, value: ""}, expected: false, name: "[target] The multiple attribute is false and the value attribute is empty"},
+ {conditions: {multiple: false, value: "test1@example.com"}, expected: false, name: "[target] The multiple attribute is false and the value attribute is a valid e-mail address"},
+ {conditions: {multiple: true, value: "test1@example.com,test2@eample.com"}, expected: false, name: "[target] The multiple attribute is true and the value contains valid e-mail addresses"},
+ {conditions: {multiple: true, value: "test,1@example.com"}, expected: false, name: "[target] The multiple attribute is true and the value attribute contains a ','"}
+ //TODO, the value contains characters that cannot be converted to punycode.
+ //Can not find a character that cannot be converted to punycode.
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {value: ""}, expected: false, name: "[target] The value attribute is empty"},
+ {conditions: {value: "2000-01-01T12:00:00"}, expected: false, name: "[target] The value attribute is a valid date and time string"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] The value attribute cannot convert to a valid normalized forced-UTC global date and time string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["color"],
+ testData: [
+ {conditions: {value: ""}, expected: false, name: "[target] The value attribute is empty"},
+ {conditions: {value: "#000000"}, expected: false, name: "[target] The value attribute is a valid sample color"},
+ {conditions: {value: "#FFFFFF"}, expected: false, name: "[target] The value attribute is not a valid lowercase sample color"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] The value attribute cannot convert to a valid sample color"}
+ ]
+ },
+ ];
+ validator.run_test (testElements, "badInput");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-customError.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-customError.html
new file mode 100644
index 000000000..16e642147
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-customError.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.customError</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-customerror">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+var testElements = [
+ {
+ tag: "input",
+ types: [],
+ testData: [
+ {conditions: {message: "My custom error"}, expected: true, name: "[target] The validity.customError must be true if the custom validity error message is not empty"},
+ {conditions: {message: ""}, expected: false, name: "[target] The validity.customError must be false if the custom validity error message is empty"}
+ ]
+ },
+ {
+ tag: "button",
+ types: [],
+ testData: [
+ {conditions: {message: "My custom error"}, expected: true, name: "[target] The validity.customError must be true if the custom validity error message is not empty"},
+ {conditions: {message: ""}, expected: false, name: "[target] The validity.customError must be false if the custom validity error message is empty"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {message: "My custom error"}, expected: true, name: "[target] The validity.customError must be true if the custom validity error message is not empty"},
+ {conditions: {message: ""}, expected: false, name: "[target] The validity.customError must be false i the custom validity error message is empty"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {message: "My custom error"}, expected: true, name: "[target] The validity.customError must be true if the custom validity error message is not empty"},
+ {conditions: {message: ""}, expected: false, name: "[target] The validity.customError must be false if the custom validity error message is empty"}
+ ]
+ }
+ ]
+
+ validator.run_test(testElements, "customError");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-patternMismatch.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-patternMismatch.html
new file mode 100644
index 000000000..5a0012b0e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-patternMismatch.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.patternMismatch</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-patternmismatch">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password"],
+ testData: [
+ {conditions: {pattern: null, value: "abc"}, expected: false, name: "[target] The pattern attribute is not set"},
+ {conditions: {pattern: "[A-Z]+", value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {pattern: "[A-Z]{1}", value: "A"}, expected: false, name: "[target] The value attribute matches the pattern attribute"},
+ {conditions: {pattern: "[A-Z]+", value: "\u0041\u0042\u0043"}, expected: false, name: "[target] The value(ABC) in unicode attribute matches the pattern attribute"},
+ {conditions: {pattern: "[a-z]{3,}", value: "ABCD"}, expected: true, name: "[target] The value attribute mismatches the pattern attribute"}
+ ]
+ }
+ ];
+
+ validator.run_test (testElements, "patternMismatch");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-rangeOverflow.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-rangeOverflow.html
new file mode 100644
index 000000000..ca423ef9e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-rangeOverflow.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.rangeOverflow</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeoverflow">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {max: "", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "2000-01-01T12:00:00", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "2000-01-01 12:00:00", value: "2001-01-01T12:00:00"}, expected: false, name: "[target] The max attribute is an invalid local date time string"},
+ {conditions: {max: "2000-01-01T12:00:00", value: "2000-01-01T11:00:00"}, expected: false, name: "[target] The max attribute is greater than the value attribute"},
+ {conditions: {max: "2000-01-01T23:59:59", value: "2001-01-01T24:00:00"}, expected: false, name: "[target] The value is an invalid local date time string(hour is greater than 23)"},
+ {conditions: {max: "1970-01-01T12:00", value: "80-01-01T12:00"}, expected: false, name: "[target] The value if an invalid local date time string(year is two digits)"},
+ {conditions: {max: "2000-01-01T12:00:00", value: "2001-01-01T13:00:00"}, expected: true, name: "[target] The value is greater than max"},
+ {conditions: {max: "2000-01-01T12:00:00.1", value: "2000-01-01T12:00:00.2"}, expected: true, name: "[target] The value is greater than max(with millisecond in 1 digit)"},
+ {conditions: {max: "2000-01-01T12:00:00.01", value: "2000-01-01T12:00:00.02"}, expected: true, name: "[target] The value is greater than max(with millisecond in 2 digits)"},
+ {conditions: {max: "2000-01-01T12:00:00.001", value: "2000-01-01T12:00:00.002"}, expected: true, name: "[target] The value is greater than max(with millisecond in 3 digits)"},
+ {conditions: {max: "2000-01-01T12:00:00", value: "10000-01-01T12:00:00"}, expected: true, name: "[target] The value is greater than max(Year is 10000 should be valid)"},
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {max: "", value: "2000-01-01"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "2000-01-01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "2000/01/01", value: "2002-01-01"}, expected: false, name: "[target] The max attribute is an invalid date"},
+ {conditions: {max: "2000-01-01", value: "2000-2-2"}, expected: false, name: "[target] The value attribute is an invalid date"},
+ {conditions: {max: "987-01-01", value: "988-01-01"}, expected: false, name: "[target] The value is an invalid date(year is three digits)"},
+ {conditions: {max: "2000-01-01", value: "2000-13-01"}, expected: false, name: "[target] The value is an invalid date(month is greater than 12)"},
+ {conditions: {max: "2000-01-01", value: "2000-02-30"}, expected: false, name: "[target] The value is an invalid date(date is greater than 29 for Feb)"},
+ {conditions: {max: "2000-12-01", value: "2000-01-01"}, expected: false, name: "[target] The max attribute is greater than value attribute"},
+ {conditions: {max: "2000-12-01", value: "2001-01-01"}, expected: true, name: "[target] The value attribute is greater than max attribute"},
+ {conditions: {max: "9999-01-01", value: "10000-01-01"}, expected: true, name: "[target] The value attribute is greater than max attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {max: "", value: "2000-01"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "2000-01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "2000/01", value: "2001-02"}, expected: false, name: "[target] The max attribute is an invalid month string"},
+ {conditions: {max: "2000-01", value: "2000-1"}, expected: false, name: "[target] The value attribute is an invalid month string"},
+ {conditions: {max: "987-01", value: "988-01"}, expected: false, name: "[target] The value is an invalid month string(year is three digits)"},
+ {conditions: {max: "2000-01", value: "2000-13"}, expected: false, name: "[target] The value is an invalid month string(month is greater than 12)"},
+ {conditions: {max: "2000-12", value: "2000-01"}, expected: false, name: "[target] The max attribute is greater than value attribute"},
+ {conditions: {max: "2000-01", value: "2000-12"}, expected: true, name: "[target] The value attribute is greater than max attribute"},
+ {conditions: {max: "9999-01", value: "10000-01"}, expected: true, name: "[target] The value attribute is greater than max attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {max: "", value: "2000-W01"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "2000-W01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "2000/W01", value: "2001-W02"}, expected: false, name: "[target] The max attribute is an invalid week string"},
+ {conditions: {max: "2000-W01", value: "2000-W2"}, expected: false, name: "[target] The value attribute is an invalid week string"},
+ {conditions: {max: "2000-W01", value: "2000-w02"}, expected: false, name: "[target] The value attribute is an invalid week string(w is in lowercase)"},
+ {conditions: {max: "987-W01", value: "988-W01"}, expected: false, name: "[target] The value is an invalid week string(year is three digits)"},
+ {conditions: {max: "2000-W01", value: "2000-W57"}, expected: false, name: "[target] The value is an invalid week string(week is too greater)"},
+ {conditions: {max: "2000-W12", value: "2000-W01"}, expected: false, name: "[target] The max attribute is greater than value attribute"},
+ {conditions: {max: "2000-W01", value: "2000-W12"}, expected: true, name: "[target] The value attribute is greater than max attribute"},
+ {conditions: {max: "9999-W01", value: "10000-W01"}, expected: true, name: "[target] The value attribute is greater than max attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {max: "", value: "12:00:00"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "12:00:00", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "12.00.00", value: "12:00:01"}, expected: false, name: "[target] The max attribute is an invalid time string"},
+ {conditions: {max: "12:00:00", value: "12.00.01"}, expected: false, name: "[target] The value attribute is an invalid time string"},
+ {conditions: {max: "23:59:59", value: "24:00:00"}, expected: false, name: "[target] The value attribute is an invalid time string(hour is greater than 23)"},
+ {conditions: {max: "23:59:59", value: "23:60:00"}, expected: false, name: "[target] The value attribute is an invalid time string(minute is greater than 59)"},
+ {conditions: {max: "23:59:59", value: "23:59:60"}, expected: false, name: "[target] The value attribute is an invalid time string(second is greater than 59)"},
+ {conditions: {max: "13:00:00", value: "12:00:00"}, expected: false, name: "[target] The max attribute is greater than value attribute"},
+ {conditions: {max: "12:00:00", value: "13"}, expected: false, name: "[target] The time missing second and minute parts is invalid"},
+ {conditions: {max: "12:00:00", value: "12:00:02"}, expected: true, name: "[target] The value attribute is greater than max attribute"},
+ {conditions: {max: "12:00:00.1", value: "12:00:00.2"}, expected: true, name: "[target] The value is greater than max(with millisecond in 1 digit)"},
+ {conditions: {max: "12:00:00.01", value: "12:00:00.02"}, expected: true, name: "[target] The value is greater than max(with millisecond in 2 digit)"},
+ {conditions: {max: "12:00:00.001", value: "12:00:00.002"}, expected: true, name: "[target] The value is greater than max(with millisecond in 3 digit)"},
+ {conditions: {max: "12:00:00", value: "12:01"}, expected: true, name: "[target] The time missing second part is valid"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {max: "", value: "10"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "5", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "5", value: "4"}, expected: false, name: "[target] The max is greater than value(integer)"},
+ {conditions: {max: "-5.5", value: "-5.6"}, expected: false, name: "[target] The max is greater than value(floating number)"},
+ {conditions: {max: "-0", value: "0"}, expected: false, name: "[target] The max equals to value"},
+ {conditions: {max: "5", value: "1abc"}, expected: false, name: "[target] The value is not a number"},
+ {conditions: {max: "5", value: "6"}, expected: true, name: "[target] The value is greater than max(integer)"},
+ {conditions: {max: "-5.5", value: "-5.4"}, expected: true, name: "[target] The value is greater than max(floating number)"},
+ {conditions: {max: "-5e-1", value: "5e+2"}, expected: true, name: "[target] The value is greater than max(scientific notation)"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "rangeOverflow");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-rangeUnderflow.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-rangeUnderflow.html
new file mode 100644
index 000000000..d6bf86060
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-rangeUnderflow.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.rangeUnderflow</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeunderflow">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {min: "", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "2000-01-01T12:00:00", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "2001-01-01 12:00:00", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] The min attribute is an invalid local date time string"},
+ {conditions: {min: "2000-01-01T11:00:00", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] The min attribute is less than the value attribute"},
+ {conditions: {min: "2001-01-01T23:59:59", value: "2000-01-01T24:00:00"}, expected: false, name: "[target] The value is an invalid local date time string(hour is greater than 23)"},
+ {conditions: {min: "1980-01-01T12:00", value: "79-01-01T12:00"}, expected: false, name: "[target] The value is an invalid local date time string(year is two digits)"},
+ {conditions: {min: "2000-01-01T13:00:00", value: "2000-01-01T12:00:00"}, expected: true, name: "[target] The value is less than min"},
+ {conditions: {min: "2000-01-01T12:00:00.2", value: "2000-01-01T12:00:00.1"}, expected: true, name: "[target] The value is less than min(with millisecond in 1 digit)"},
+ {conditions: {min: "2000-01-01T12:00:00.02", value: "2000-01-01T12:00:00.01"}, expected: true, name: "[target] The value is less than min(with millisecond in 2 digits)"},
+ {conditions: {min: "2000-01-01T12:00:00.002", value: "2000-01-01T12:00:00.001"}, expected: true, name: "[target] The value is less than min(with millisecond in 3 digits)"},
+ {conditions: {min: "10000-01-01T12:00:00", value: "2000-01-01T12:00:00"}, expected: true, name: "[target] The value is less than min(Year is 10000 should be valid)"},
+ {conditions: {max: "8593-01-01T02:09", value: "8592-01-01T02:09"}, expected: false, name: "[target] The value is greater than max"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {min: "", value: "2000-01-01"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "2000-01-01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "2001/01/01", value: "2000-01-01"}, expected: false, name: "[target] The min attribute is an invalid date"},
+ {conditions: {min: "2000-02-02", value: "2000-1-1"}, expected: false, name: "[target] The value attribute is an invalid date"},
+ {conditions: {min: "988-01-01", value: "987-01-01"}, expected: false, name: "[target] The value is an invalid date(year is three digits)"},
+ {conditions: {min: "2001-01-01", value: "2000-13-01"}, expected: false, name: "[target] The value is an invalid date(month is less than 12)"},
+ {conditions: {min: "2001-01-01", value: "2000-02-30"}, expected: false, name: "[target] The value is an invalid date(date is less than 29 for Feb)"},
+ {conditions: {min: "2000-01-01", value: "2000-12-01"}, expected: false, name: "[target] The min attribute is less than value attribute"},
+ {conditions: {min: "2000-12-01", value: "2000-01-01"}, expected: true, name: "[target] The value attribute is less than min attribute"},
+ {conditions: {min: "10000-01-01", value: "9999-01-01"}, expected: true, name: "[target] The value attribute is less than min attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {min: "", value: "2000-01"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "2000-01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "2001/01", value: "2000-02"}, expected: false, name: "[target] The min attribute is an invalid month string"},
+ {conditions: {min: "2000-02", value: "2000-1"}, expected: false, name: "[target] The value attribute is an invalid month string"},
+ {conditions: {min: "988-01", value: "987-01"}, expected: false, name: "[target] The value is an invalid month string(year is three digits)"},
+ {conditions: {min: "2001-01", value: "2000-13"}, expected: false, name: "[target] The value is an invalid month string(month is less than 12)"},
+ {conditions: {min: "2000-01", value: "2000-12"}, expected: false, name: "[target] The min attribute is less than value attribute"},
+ {conditions: {min: "2001-01", value: "2000-12"}, expected: true, name: "[target] The value attribute is less than min attribute"},
+ {conditions: {min: "10000-01", value: "2000-01"}, expected: true, name: "[target] The value attribute is less than min attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {min: "", value: "2000-W01"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "2000-W01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "2001/W02", value: "2000-W01"}, expected: false, name: "[target] The min attribute is an invalid week string"},
+ {conditions: {min: "2001-W02", value: "2000-W1"}, expected: false, name: "[target] The value attribute is an invalid week string"},
+ {conditions: {min: "2001-W02", value: "2000-w01"}, expected: false, name: "[target] The value attribute is an invalid week string(w is in lowercase)"},
+ {conditions: {min: "988-W01", value: "987-W01"}, expected: false, name: "[target] The value is an invalid week string(year is three digits)"},
+ {conditions: {min: "2001-W01", value: "2000-W57"}, expected: false, name: "[target] The value is an invalid week string(week is too greater)"},
+ {conditions: {min: "2000-W01", value: "2000-W12"}, expected: false, name: "[target] The min attribute is less than value attribute"},
+ {conditions: {min: "2000-W12", value: "2000-W01"}, expected: true, name: "[target] The value attribute is less than min attribute"},
+ {conditions: {min: "10000-W01", value: "2000-W01"}, expected: true, name: "[target] The value attribute is less than min attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {min: "", value: "12:00:00"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "12:00:00", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "12.00.01", value: "12:00:00"}, expected: false, name: "[target] The min attribute is an invalid time string"},
+ {conditions: {min: "12:00:01", value: "12.00.00"}, expected: false, name: "[target] The value attribute is an invalid time string"},
+ {conditions: {min: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] The min attribute is less than value attribute"},
+ {conditions: {min: "13:00:00", value: "12"}, expected: false, name: "[target] The time missing second and minute parts is invalid"},
+ {conditions: {min: "12:00:02", value: "12:00:00"}, expected: true, name: "[target] The value attribute is less than min attribute"},
+ {conditions: {min: "12:00:00.2", value: "12:00:00.1"}, expected: true, name: "[target] The value is less than min(with millisecond in 1 digit)"},
+ {conditions: {min: "12:00:00.02", value: "12:00:00.01"}, expected: true, name: "[target] The value is less than min(with millisecond in 2 digit)"},
+ {conditions: {min: "12:00:00.002", value: "12:00:00.001"}, expected: true, name: "[target] The value is less than min(with millisecond in 3 digit)"},
+ {conditions: {min: "12:00:00", value: "11:59"}, expected: true, name: "[target] The time missing second part is valid"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {min: "", value: "10"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "5", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "4", value: "5"}, expected: false, name: "[target] The min is less than value(integer)"},
+ {conditions: {min: "-5.6", value: "-5.5"}, expected: false, name: "[target] The min is less than value(floating number)"},
+ {conditions: {min: "0", value: "-0"}, expected: false, name: "[target] The min equals to value"},
+ {conditions: {min: "5", value: "6abc"}, expected: false, name: "[target] The value is not a number"},
+ {conditions: {min: "6", value: "5"}, expected: true, name: "[target] The value is less than min(integer)"},
+ {conditions: {min: "-5.4", value: "-5.5"}, expected: true, name: "[target] The value is less than min(floating number)"},
+ {conditions: {min: "5e+2", value: "-5e-1"}, expected: true, name: "[target] The value is less than min(scientific notation)"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "rangeUnderflow");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-stepMismatch.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-stepMismatch.html
new file mode 100644
index 000000000..174ecaf33
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-stepMismatch.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.stepMismatch</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-stepmismatch">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ //set step = 2 * default step * factor
+ var testElements = [
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {step: "", value: "2000-01-01"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2, value: "1970-01-03"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2, value: "1970-01-02"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {step: "", value: "2000-01"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2, value: "1970-03"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2, value: "1970-04"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {step: "", value: "1970-W01"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2, value: "1970-W03"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2, value: "1970-W04"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {step: "", value: "12:00:00"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 60, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 60, value: "12:02:00"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 60, value: "12:03:00"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {step: "", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 60, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 60, value: "1970-01-01T12:02:00"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 60, value: "1970-01-01T12:03:00"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {step: "", value: "1"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 1 * 1, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 1 * 1, value: "2"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 1 * 1, value: "3"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "stepMismatch");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooLong.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooLong.html
new file mode 100644
index 000000000..aa787d471
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooLong.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.tooLong</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-toolong">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password"],
+ testData: [ // Non-dirty value
+ {conditions: {maxLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - maxlength is not set"},
+ {conditions: {maxLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
+ {conditions: {maxLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of value is less than maxlength"},
+ {conditions: {maxLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to maxlength"},
+ {conditions: {maxLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than maxlength"},
+ //Dirty value
+ {conditions: {maxLength: "4", value: "abc"}, expected: false, name: "[target] Dirty value - value is less than maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "\u0041\u0041\u0041"}, expected: false, name: "[target] Dirty value - length of value(AAA) in unicode is less than maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - value equals to maxlength", dirty: true},
+ // False due to lack of required interactive editing by the user
+ {conditions: {maxLength: "4", value: "abcde"}, expected: false, name: "[target] Dirty value - length of value is greater than maxlength", dirty: true}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {maxLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - maxlength is not set"},
+ {conditions: {maxLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
+ {conditions: {maxLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of value is less than maxlength"},
+ {conditions: {maxLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to maxlength"},
+ {conditions: {maxLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than maxlength"},
+ //Dirty value
+ {conditions: {maxLength: "4", value: "abc"}, expected: false, name: "[target] Dirty value - value is less than maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "\u000D\u000A"}, expected: false, name: "[target] Dirty value - length of value(LF, CRLF) in unicode is less than maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - length of value equals to maxlength", dirty: true},
+ // False due to lack of required interactive editing by the user
+ {conditions: {maxLength: "4", value: "abcde"}, expected: false, name: "[target] Dirty value - length of value is greater than maxlength", dirty: true}
+ ]
+ }
+ ];
+
+ validator.run_test (testElements, "tooLong");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html
new file mode 100644
index 000000000..b6c0e4399
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.tooShort</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#suffering-from-being-too-short">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password"],
+ testData: [
+ // Non-dirty value
+ {conditions: {minLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - minLength is not set"},
+ {conditions: {minLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
+ {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than minLength"},
+ {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to minLength"},
+ {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of value is less than minLength"},
+ //Dirty value
+ {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Dirty value - value is greater than minLength", dirty: true},
+ {conditions: {minLength: "4", value: "\u0041\u0041\u0041\u0041\u0041"}, expected: false, name: "[target] Dirty value - length of value(AAAAA) in unicode is greater than minLength", dirty: true},
+ {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - value equals to minLength", dirty: true},
+ // False due to lack of required interactive editing by the user
+ {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Dirty value - length of value is less than minLength", dirty: true}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ // Non-dirty value
+ {conditions: {minLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - minLength is no set"},
+ {conditions: {minLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
+ {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than minLength"},
+ {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to minLength"},
+ {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of length of value is greater than minLength"},
+ //Dirty value
+ {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Dirty value - value is less than minLength", dirty: true},
+ {conditions: {minLength: "4", value: "\u000D\u000A\u000D\u000A\u000D\u000A"}, expected: false, name: "[target] Dirty value - length of value(LF, CRLF) in unicode is less than minLength", dirty: true},
+ {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - length of value equals to minLength", dirty: true},
+ // False due to lack of required interactive editing by the user
+ {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Dirty value - length of value is greater than minLength", dirty: true}
+ ]
+ }
+ ];
+
+ validator.run_test (testElements, "tooShort");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-typeMismatch.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-typeMismatch.html
new file mode 100644
index 000000000..40444277c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-typeMismatch.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.typeMismatch</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-typemismatch">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ // multiple is false
+ {conditions: {multiple: false, value: ""}, expected: false, name: "[target] The value is empty"},
+ {conditions: {multiple: false, value: "test@example.com"}, expected: false, name: "[target] The value is a valid email address"},
+ {conditions: {multiple: false, value: "\u000A\u000D\u0020\u0009 test@example.com \u000A\u000D\u0020\u0009"}, expected: false, name: "[target] The value is a valid email address with some white spaces."},
+ {conditions: {multiple: false, value: "abc"}, expected: true, name: "[target] The value is not an email address"},
+ {conditions: {multiple: false, value: "test1@example.com,test2@example.com"}, expected: true, name: "[target] The value contains multiple email addresses"},
+ //multiple is true
+ {conditions: {multiple: true, value: "test1@example.com,test2@example.com"}, expected: false, name: "[target] The value is valid email addresses"},
+ {conditions: {multiple: true, value: "test1@example.com;test2@example.com"}, expected: true, name: "[target] The value contains invalid separator"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["url"],
+ testData: [
+ {conditions: {multiple: false, value: ""}, expected: false, name: "[target] The value is empty"},
+ {conditions: {multiple: false, value: "http://www.example.com"}, expected: false, name: "[target] The value is a valid url"},
+ {conditions: {multiple: false, value: "\u000A\u000D\u0020\u0009 http://www.example.com \u000A\u000D\u0020\u0009 "}, expected: false, name: "[target] The value is a valid url with some white spaces."},
+ {conditions: {multiple: false, value: "abc"}, expected: true, name: "[target] The value is not an url"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "typeMismatch");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-valid.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-valid.html
new file mode 100644
index 000000000..5dacfeae3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-valid.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.valid</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-valid">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "password"],
+ testData: [
+ {conditions: {pattern: "[A-Z]", value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["url"],
+ testData: [
+ {conditions: {pattern: "http://www.example.com", value: "http://www.example.net"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.typeMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ {conditions: {pattern: "test@example.com", value: "test@example.net"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.typeMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {max: "2000-01-01T12:00:00", value: "2001-01-01T12:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "2001-01-01T12:00:00", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 60 * 1000, value: "2001-01-01T12:03:00"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {max: "2000-01-01", value: "2001-01-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "2001-01-01", value: "2000-01-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 1 * 86400000, value: "2000-01-03"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {max: "2000-01", value: "2001-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "2001-01", value: "2000-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 1 * 1, value: "2001-03"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {max: "2000-W01", value: "2001-W01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "2001-W01", value: "2000-W01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 1 * 604800000, value: "2001-W03"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {max: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "12:00:00", value: "11:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 60 * 1000, value: "12:03:00"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {max: "5", value: "6"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "5", value: "4"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 1 * 1, value: "3"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["checkbox", "radio"],
+ testData: [
+ {conditions: {required: true, checked: false, name: "test1"}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["file"],
+ testData: [
+ {conditions: {required: true, files: null}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "isValid");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-valueMissing.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
new file mode 100644
index 000000000..3c9e4c4cb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.valueMissing</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-valuemissing">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "abc"}, expected: false, name: "[target] The value is not empty and required is true"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value is empty and required is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "2000-12-10T12:00:00"}, expected: false, name: "[target] Valid local date and time string(2000-12-10T12:00:00)"},
+ {conditions: {required: true, value: "2000-12-10 12:00"}, expected: false, name: "[target] Valid local date and time string(2000-12-10 12:00)"},
+ {conditions: {required: true, value: "1979-10-14T12:00:00.001"}, expected: false, name: "[target] Valid local date and time string(1979-10-14T12:00:00.001)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
+ {conditions: {required: true, value: "1979-10-99 99:99"}, expected: true, name: "[target] Invalid local date and time string(1979-10-99 99:99)"},
+ {conditions: {required: true, value: "1979-10-14 12:00:00"}, expected: false, name: "[target] Valid local date and time string(1979-10-14 12:00:00)"},
+ {conditions: {required: true, value: "2001-12-21 12:00"}, expected: true, name: "[target] Invalid local date and time string(2001-12-21 12:00)-two white space"},
+ {conditions: {required: true, value: "abc"}, expected: true, name: "[target] the value attribute is a string(abc)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "2000-12-10"}, expected: false, name: "[target] Valid date string(2000-12-10)"},
+ {conditions: {required: true, value: "9999-01-01"}, expected: false, name: "[target] Valid date string(9999-01-01)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
+ {conditions: {required: true, value: "9999-99-99"}, expected: true, name: "[target] Invalid date string(9999-99-99)"},
+ {conditions: {required: true, value: "37/01/01"}, expected: true, name: "[target] Invalid date string(37-01-01)"},
+ {conditions: {required: true, value: "2000/01/01"}, expected: true, name: "[target] Invalid date string(2000/01/01)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "2000-12"}, expected: false, name: "[target] Valid month string(2000-12)"},
+ {conditions: {required: true, value: "9999-01"}, expected: false, name: "[target] Valid month string(9999-01)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
+ {conditions: {required: true, value: "2000-99"}, expected: true, name: "[target] Invalid month string(2000-99)"},
+ {conditions: {required: true, value: "37-01"}, expected: true, name: "[target] Invalid month string(37-01)"},
+ {conditions: {required: true, value: "2000/01"}, expected: true, name: "[target] Invalid month string(2000/01)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "2000-W12"}, expected: false, name: "[target] Valid week string(2000-W12)"},
+ {conditions: {required: true, value: "9999-W01"}, expected: false, name: "[target] Valid week string(9999-W01)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
+ {conditions: {required: true, value: "2000-W99"}, expected: true, name: "[target] Invalid week string(2000-W99)"},
+ {conditions: {required: true, value: "2000-W00"}, expected: true, name: "[target] invalid week string(2000-W00)"},
+ {conditions: {required: true, value: "2000-w01"}, expected: true, name: "[target] invalid week string(2000-w01)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "12:00:00"}, expected: false, name: "[target] Validtime string(12:00:00)"},
+ {conditions: {required: true, value: "12:00"}, expected: false, name: "[target] Validtime string(12:00)"},
+ {conditions: {required: true, value: "12:00:00.001"}, expected: false, name: "[target] Valid time string(12:00:60.001)"},
+ {conditions: {required: true, value: "12:00:00.01"}, expected: false, name: "[target] Valid time string(12:00:60.01)"},
+ {conditions: {required: true, value: "12:00:00.1"}, expected: false, name: "[target] Valid time string(12:00:60.1)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a time object"},
+ {conditions: {required: true, value: "25:00:00"}, expected: true, name: "[target] Invalid time string(25:00:00)"},
+ {conditions: {required: true, value: "12:60:00"}, expected: true, name: "[target] Invalid time string(12:60:00)"},
+ {conditions: {required: true, value: "12:00:60"}, expected: true, name: "[target] Invalid time string(12:00:60)"},
+ {conditions: {required: true, value: "12:00:00:001"}, expected: true, name: "[target] Invalid time string(12:00:00:001)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "123"}, expected: false, name: "[target] Value is an integer with a leading symbol '+'"},
+ {conditions: {required: true, value: "-123.45"}, expected: false, name: "[target] Value is a number with a '-' symbol"},
+ {conditions: {required: true, value: "123.01e-10"}, expected: false, name: "[target] Value is a number in scientific notation form(e is in lowercase)"},
+ {conditions: {required: true, value: "123.01E+10"}, expected: false, name: "[target] Value is a number in scientific notation form(E is in uppercase)"},
+ {conditions: {required: true, value: "-0"}, expected: false, name: "[target] Value is -0"},
+ {conditions: {required: true, value: " 123 "}, expected: true, name: "[target] Value is a number with some white spaces"},
+ {conditions: {required: true, value: Math.pow(2, 1024)}, expected: true, name: "[target] Value is Math.pow(2, 1024)"},
+ {conditions: {required: true, value: Math.pow(-2, 1024)}, expected: true, name: "[target] Value is Math.pow(-2, 1024)"},
+ {conditions: {required: true, value: "abc"}, expected: true, name: "[target] Value is a string that cannot be converted to a number"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["checkbox"],
+ testData: [
+ {conditions: {required: false, checked: false, name: "test1"}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, checked: true, name: "test2"}, expected: false, name: "[target] The checked attribute is true"},
+ {conditions: {required: true, checked: false, name: "test3"}, expected: true, name: "[target] The checked attribute is false"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["radio"],
+ testData: [
+ {conditions: {required: false, checked: false, name: "test4"}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, checked: true, name: "test5"}, expected: false, name: "[target] The checked attribute is true"},
+ {conditions: {required: true, checked: false, name: "test6"}, expected: true, name: "[target] The checked attribute is false"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["file"],
+ testData: [
+ {conditions: {required: false, files: null}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, files: null}, expected: true, name: "[target] The Files attribute is null"}
+ //ToDo: Add a case to test the files is not null
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: 1}, expected: false, name: "[target] Selected the option with value equals to 1"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] Selected the option with value equals to empty"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "abc"}, expected: false, name: "[target] The value is not empty"},
+ {conditions: {required: true, value: ""}, expected: true , name: "[target] The value is empty"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "valueMissing");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-willValidate.html b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-willValidate.html
new file mode 100644
index 000000000..237572b0f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-willValidate.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.willValidate</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-cva-willvalidate">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ //input in hidden, button and reset status must be barred from the constraint validation
+ {
+ tag: "input",
+ types: ["hidden", "button", "reset"],
+ testData: [{conditions: {}, expected: false, name: "[target] Must be barred from the constraint validation"}]
+ },
+ //button in button and reset status must be barred from the constraint validation
+ {
+ tag: "button",
+ types: ["button", "reset"],
+ testData: [{conditions: {}, expected: false, name: "[target] Must be barred from the constraint validation"}]
+ },
+ //FIELDSET, OUTPUT elements should not be barred from the constraint validation
+ {
+ tag: "fieldset",
+ types: [],
+ testData: [{conditions: {}, expected: true, name: "[target] Must not be barred from the constraint validation"}]
+ },
+ {
+ tag: "output",
+ types: [],
+ testData: [{conditions: {}, expected: true, name: "[target] Must not be barred from the constraint validation"}]
+ },
+ //OBJECT, KEYGEN, elements must be barred from the constraint validation
+ {
+ tag: "object",
+ types: [],
+ testData: [{conditions: {}, expected: false, name: "[target] Must be barred from the constraint validation"}]
+ },
+ {
+ tag: "keygen",
+ types: [],
+ testData: [{conditions: {}, expected: false, name: "[target] Must be barred from the constraint validation"}]
+ },
+ //If an element is disabled, it is barred from constraint validation.
+ //The willValidate attribute must be true if an element is mutable
+ //If the readonly attribute is specified on an INPUT element, the element is barred from constraint validation.
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password", "datetime-local", "date", "month", "week", "time", "color", "file", "submit"],
+ testData: [
+ {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation if it is disabled"},
+ {conditions: {disabled: false, readOnly: false}, expected: true, name: "[target] The willValidate attribute must be true if an element is mutable"},
+ {conditions: {readOnly: true}, expected: false, name: "[target] Must be barred from the constraint validation if it is readonly"},
+ {conditions: {disabled: false, readOnly: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"},
+ ]
+ },
+ {
+ tag: "button",
+ types: ["submit"],
+ testData: [
+ {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation"},
+ {conditions: {disabled: false}, expected: true, name: "[target] The willValidate attribute must be true if an element is mutable"},
+ {conditions: {disabled: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation"},
+ {conditions: {disabled: false}, expected: true, name: "[target] The willValidate attribute must be true if an element is mutable"},
+ {conditions: {disabled: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [,
+ {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation"},
+ {conditions: {disabled: false}, expected: true, name: "[target] The willValidate attribute must be true if an element is mutable"},
+ {conditions: {disabled: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "willValidate");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/inputwillvalidate.html b/testing/web-platform/tests/html/semantics/forms/constraints/inputwillvalidate.html
new file mode 100644
index 000000000..909fd889b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/inputwillvalidate.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title>willValidate property on the input element</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="content-type">
+ <meta content="willValidate property on the input element" name="description">
+ <link href="https://html.spec.whatwg.org/multipage/#dom-cva-willvalidate" rel="help">
+ </head>
+ <body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <div id="log"></div>
+
+ <form action="http://www.example.com/" style="display : none">
+ <input required="" type="text">
+ <input disabled="" type="text">
+ </form>
+
+ <script type="text/javascript">
+
+ test(function() {assert_true(document.getElementsByTagName("input")[0].willValidate)}, "willValidate property returns true when required attribute exists");
+ test(function() {assert_false(document.getElementsByTagName("input")[1].willValidate)}, "willValidate property returns false when disabled attribute exists");
+
+ </script>
+
+</body></html>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/support/validator.js b/testing/web-platform/tests/html/semantics/forms/constraints/support/validator.js
new file mode 100644
index 000000000..e969ce460
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/support/validator.js
@@ -0,0 +1,377 @@
+var validator = {
+ test_tooLong: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "tooLong");
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ if (data.expected)
+ assert_true(ctl.validity.tooLong, "The validity.tooLong should be true.");
+ else
+ assert_false(ctl.validity.tooLong, "The validity.tooLong should be false.");
+ }, data.name);
+ },
+
+ test_tooShort: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "tooShort");
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ if (data.expected)
+ assert_true(ctl.validity.tooShort, "The validity.tooShort should be true.");
+ else
+ assert_false(ctl.validity.tooShort, "The validity.tooShort should be false.");
+ }, data.name);
+ },
+
+ test_patternMismatch: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "patternMismatch");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.patternMismatch, "The validity.patternMismatch should be true.");
+ else
+ assert_false(ctl.validity.patternMismatch, "The validity.patternMismatch should be false.");
+ }, data.name);
+ },
+
+ test_valueMissing: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "valueMissing");
+ self.set_conditions(ctl, data.conditions);
+ if (data.expected)
+ assert_true(ctl.validity.valueMissing, "The validity.valueMissing should be true.");
+ else
+ assert_false(ctl.validity.valueMissing, "The validity.valueMissing should be false.");
+ }, data.name);
+ },
+
+ test_typeMismatch: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "typeMismatch");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.typeMismatch, "The validity.typeMismatch should be true.");
+ else
+ assert_false(ctl.validity.typeMismatch, "The validity.typeMismatch should be false.");
+ }, data.name);
+ },
+
+ test_rangeOverflow: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "rangeOverflow");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.rangeOverflow, "The validity.rangeOverflow should be true.");
+ else
+ assert_false(ctl.validity.rangeOverflow, "The validity.rangeOverflow should be false.");
+ }, data.name);
+ },
+
+ test_rangeUnderflow: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "rangeUnderflow");
+ self.set_conditions(ctl, data.conditions);
+ if (data.expected)
+ assert_true(ctl.validity.rangeUnderflow, "The validity.rangeUnderflow should be true.");
+ else
+ assert_false(ctl.validity.rangeUnderflow, "The validity.rangeUnderflow should be false.");
+ }, data.name);
+ },
+
+ test_stepMismatch: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "stepMismatch");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.stepMismatch, "The validity.stepMismatch should be true.");
+ else
+ assert_false(ctl.validity.stepMismatch, "The validity.stepMismatch should be false.");
+ }, data.name);
+ },
+
+ test_badInput: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "badInput");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.badInput, "The validity.badInput should be true.");
+ else
+ assert_false(ctl.validity.badInput, "The validity.badInput should be false.");
+ }, data.name);
+ },
+
+ test_customError: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "customError");
+ ctl.setCustomValidity(data.conditions.message);
+
+ if (data.expected) {
+ assert_true(ctl.validity.customError, "The validity.customError attribute should be true.");
+ assert_equals(ctl.validationMessage, data.conditions.message,
+ "The validationMessage attribute should be '" + data.conditions.message + "'.");
+ } else {
+ assert_false(ctl.validity.customError, "The validity.customError attribute should be false.");
+ assert_equals(ctl.validationMessage, "", "The validationMessage attribute must be empty.");
+ }
+ }, data.name);
+ },
+
+ test_isValid: function (ctl, data) {
+ var self = this;
+ test(function () {
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ if (data.expected)
+ assert_true(ctl.validity.valid, "The validity.valid should be true.");
+ else
+ assert_false(ctl.validity.valid, "The validity.valid should be false.");
+ }, data.name);
+ },
+
+ test_willValidate: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "willValidate");
+ self.set_conditions(ctl, data.conditions);
+ if (data.ancestor) {
+ var dl = document.createElement("datalist");
+ dl.appendChild(ctl);
+ }
+
+ if (data.expected)
+ assert_true(ctl.willValidate, "The willValidate attribute should be true.");
+ else
+ assert_false(ctl.willValidate, "The willValidate attribute should be false.");
+ }, data.name);
+ },
+
+ test_checkValidity: function (ctl, data) {
+ var self = this;
+ test(function () {
+ var eventFired = false;
+ self.pre_check(ctl, "checkValidity");
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ on_event(ctl, "invalid", function(e){
+ assert_equals(e.type, "invalid", "The invalid event should be fired.");
+ eventFired = true;
+ });
+
+ if (data.expected) {
+ assert_true(ctl.checkValidity(), "The checkValidity method should be true.");
+ assert_false(eventFired, "The invalid event should not be fired.");
+ } else {
+ assert_false(ctl.checkValidity(), "The checkValidity method should be false.");
+ assert_true(eventFired, "The invalid event should be fired.");
+ }
+ }, data.name);
+
+ test(function () {
+ var fm = document.createElement("form");
+ var ctl2 = ctl.cloneNode(true);
+
+ self.pre_check(ctl, "checkValidity");
+ self.set_conditions(ctl2, data.conditions);
+ fm.appendChild(ctl2);
+ document.body.appendChild(fm);
+ if (data.dirty)
+ self.set_dirty(ctl2);
+
+ var result = fm.checkValidity();
+ document.body.removeChild(fm);
+
+ if (data.expected)
+ assert_true(result, "The checkValidity method of the element's form owner should return true.");
+ else
+ assert_false(result, "The checkValidity method of the element's form owner should return false.");
+ }, data.name + " (in a form)");
+ },
+
+ test_reportValidity: function (ctl, data) {
+ var self = this;
+ test(function () {
+ var eventFired = false;
+
+ self.pre_check(ctl, "reportValidity");
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ on_event(ctl, "invalid", function(e){
+ assert_equals(e.type, "invalid", "The invalid event should be fired.");
+ eventFired = true;
+ });
+
+ if (data.expected) {
+ assert_true(ctl.reportValidity(), "The reportValidity method should be true.");
+ assert_false(eventFired, "The invalid event should not be fired.");
+ } else {
+ assert_false(ctl.reportValidity(), "The reportValidity method should be false.");
+ assert_true(eventFired, "The invalid event should be fired.");
+ }
+ }, data.name);
+
+ test(function () {
+ var fm = document.createElement("form");
+ var ctl2 = ctl.cloneNode(true);
+
+ self.pre_check(ctl, "reportValidity");
+ self.set_conditions(ctl2, data.conditions);
+ fm.appendChild(ctl2);
+ document.body.appendChild(fm);
+ if (data.dirty)
+ self.set_dirty(ctl2);
+
+ var result = fm.reportValidity();
+ document.body.removeChild(fm);
+
+ if (data.expected)
+ assert_true(result, "The reportValidity method of the element's form owner should return true.");
+ else
+ assert_false(result, "The reportValidity method of the element's form owner should return false.");
+ }, data.name + " (in a form)");
+ },
+
+ test_support_type: function (ctl, typ, testName) {
+ test(function () {
+ assert_equals(ctl.type, typ, "The " + typ + " type should be supported.");
+ }, testName);
+ },
+
+ set_conditions: function (ctl, obj) {
+ [
+ "checked",
+ "disabled",
+ "max",
+ "maxlength",
+ "min",
+ "minlength",
+ "multiple",
+ "pattern",
+ "required",
+ "selected",
+ "step",
+ "value"
+ ].forEach(function(item) {
+ ctl.removeAttribute(item);
+ });
+ for (var attr in obj) {
+ if (attr === "checked" || obj[attr] || obj[attr] === "")
+ ctl[attr] = obj[attr];
+ }
+ },
+
+ set_dirty: function(ctl) {
+ ctl.focus();
+ var old_value = ctl.value;
+ ctl.value = "a";
+ ctl.value = old_value;
+ },
+
+ pre_check: function(ctl, item) {
+ switch (item) {
+ case "willValidate":
+ assert_true(item in ctl, "The " + item + " attribute doesn't exist.");
+ break;
+ case "checkValidity":
+ case "reportValidity":
+ assert_true(item in ctl, "The " + item + " method doesn't exist.");
+ break;
+ case "tooLong":
+ case "tooShort":
+ case "patternMismatch":
+ case "typeMismatch":
+ case "stepMismatch":
+ case "rangeOverflow":
+ case "rangeUnderflow":
+ case "valueMissing":
+ case "badInput":
+ case "valid":
+ assert_true("validity" in ctl, "The validity attribute doesn't exist.");
+ assert_true(item in ctl.validity, "The " + item + " attribute doesn't exist.");
+ break;
+ case "customError":
+ assert_true("validity" in ctl, "The validity attribute doesn't exist.");
+ assert_true("setCustomValidity" in ctl, "The validity attribute doesn't exist.");
+ assert_true("validationMessage" in ctl, "The validity attribute doesn't exist.");
+ assert_true(item in ctl.validity, "The " + item + " attribute doesn't exist.");
+ break;
+ }
+ },
+
+ run_test: function (testee, method) {
+ var testMethod = "test_" + method;
+ if (typeof this[testMethod] !== "function") {
+ return false;
+ }
+
+ var ele = null,
+ prefix = "";
+
+ for (var i = 0; i < testee.length; i++) {
+ if (testee[i].types.length > 0) {
+ for (var typ in testee[i].types) {
+ ele = document.createElement(testee[i].tag);
+ document.body.appendChild(ele);
+ try {
+ ele.type = testee[i].types[typ];
+ } catch (e) {
+ //Do nothing, avoid the runtime error breaking the test
+ }
+
+ prefix = "[" + testee[i].tag.toUpperCase() + " in " + testee[i].types[typ].toUpperCase() + " status] ";
+ if (ele.type != testee[i].types[typ]) {
+ this.test_support_type(
+ ele,
+ testee[i].types[typ],
+ prefix + "The " + testee[i].types[typ] + " type must be supported."
+ );
+ continue;
+ }
+
+ for (var j = 0; j < testee[i].testData.length; j++) {
+ testee[i].testData[j].name = testee[i].testData[j].name.replace(/\[.*\]\s/g, prefix);
+ this[testMethod](ele, testee[i].testData[j]);
+ }
+ }
+ } else {
+ ele = document.createElement(testee[i].tag);
+ document.body.appendChild(ele);
+ prefix = "[" + testee[i].tag + "] ";
+
+ if (testElements[i].tag === "select") {
+ ele.add(new Option("test1", ""));
+ ele.add(new Option("test2", 1));
+ }
+
+ for (var item in testee[i].testData) {
+ testee[i].testData[item].name = testee[i].testData[item].name.replace("[target]", prefix);
+ this[testMethod](ele, testee[i].testData[item]);
+ }
+ }
+ }
+ }
+}
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-email-delete-manual.html b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-email-delete-manual.html
new file mode 100644
index 000000000..008089f39
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-email-delete-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>input[type="email"], ValidityState.tooLong and user editing</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#limiting-user-input-length:-the-maxlength-attribute">
+ <meta name="flags" content="interact">
+ <meta name="assert" content="Per the 'Constraint validation' definition in the referenced section, an input whose value was edited by the user but still exceeds the input's maxlength should suffer from being too long.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>Delete one character from the following text input:</p>
+ <input type="email" value="jane.doe@example.com" maxlength="5" autocomplete="off" id="testinput">
+
+ <div id="log"></div>
+ <script>
+var input = document.getElementById('testinput');
+setup({explicit_timeout: true, explicit_done: true});
+on_event(input, "input", function () {
+ test(function() {
+ assert_class_string(input.validity, 'ValidityState', 'HTMLInputElement.validity must be a ValidityState instance');
+ assert_true(input.validity.tooLong, "tooLong must be true since the user just changed the input's value and the value exceeds the maxlength");
+ });
+ done();
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-password-delete-manual.html b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-password-delete-manual.html
new file mode 100644
index 000000000..353d9466d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-password-delete-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>input[type="password"], ValidityState.tooLong and user editing</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#limiting-user-input-length:-the-maxlength-attribute">
+ <meta name="flags" content="interact">
+ <meta name="assert" content="Per the 'Constraint validation' definition in the referenced section, an input whose value was edited by the user but still exceeds the input's maxlength should suffer from being too long.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>Delete one character from the following text input:</p>
+ <input type="password" value="swordfish" maxlength="5" autocomplete="off" id="testinput">
+
+ <div id="log"></div>
+ <script>
+var input = document.getElementById('testinput');
+setup({explicit_timeout: true, explicit_done: true});
+on_event(input, "input", function () {
+ test(function() {
+ assert_class_string(input.validity, 'ValidityState', 'HTMLInputElement.validity must be a ValidityState instance');
+ assert_true(input.validity.tooLong, "tooLong must be true since the user just changed the input's value and the value exceeds the maxlength");
+ });
+ done();
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-search-delete-manual.html b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-search-delete-manual.html
new file mode 100644
index 000000000..73be3b6d8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-search-delete-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>input[type="search"], ValidityState.tooLong and user editing</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#limiting-user-input-length:-the-maxlength-attribute">
+ <meta name="flags" content="interact">
+ <meta name="assert" content="Per the 'Constraint validation' definition in the referenced section, an input whose value was edited by the user but still exceeds the input's maxlength should suffer from being too long.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>Delete one character from the following text input:</p>
+ <input type="search" value="abcdefghi" maxlength="5" autocomplete="off" id="testinput">
+
+ <div id="log"></div>
+ <script>
+var input = document.getElementById('testinput');
+setup({explicit_timeout: true, explicit_done: true});
+on_event(input, "input", function () {
+ test(function() {
+ assert_class_string(input.validity, 'ValidityState', 'HTMLInputElement.validity must be a ValidityState instance');
+ assert_true(input.validity.tooLong, "tooLong must be true since the user just changed the input's value and the value exceeds the maxlength");
+ });
+ done();
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-tel-delete-manual.html b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-tel-delete-manual.html
new file mode 100644
index 000000000..bf7682af3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-tel-delete-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>input[type="tel"], ValidityState.tooLong and user editing</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#limiting-user-input-length:-the-maxlength-attribute">
+ <meta name="flags" content="interact">
+ <meta name="assert" content="Per the 'Constraint validation' definition in the referenced section, an input whose value was edited by the user but still exceeds the input's maxlength should suffer from being too long.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>Delete one character from the following text input:</p>
+ <input type="tel" value="123-456-7890" maxlength="7" autocomplete="off" id="testinput">
+
+ <div id="log"></div>
+ <script>
+var input = document.getElementById('testinput');
+setup({explicit_timeout: true, explicit_done: true});
+on_event(input, "input", function () {
+ test(function() {
+ assert_class_string(input.validity, 'ValidityState', 'HTMLInputElement.validity must be a ValidityState instance');
+ assert_true(input.validity.tooLong, "tooLong must be true since the user just changed the input's value and the value exceeds the maxlength");
+ });
+ done();
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-text-delete-manual.html b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-text-delete-manual.html
new file mode 100644
index 000000000..2eea2b724
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-text-delete-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>input[type="text"], ValidityState.tooLong and user editing</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#limiting-user-input-length:-the-maxlength-attribute">
+ <meta name="flags" content="interact">
+ <meta name="assert" content="Per the 'Constraint validation' definition in the referenced section, an input whose value was edited by the user but still exceeds the input's maxlength should suffer from being too long.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>Delete one character from the following text input:</p>
+ <input type="text" value="0123456789" maxlength="5" autocomplete="off" id="testinput">
+
+ <div id="log"></div>
+ <script>
+var input = document.getElementById('testinput');
+setup({explicit_timeout: true, explicit_done: true});
+on_event(input, "input", function () {
+ test(function() {
+ assert_class_string(input.validity, 'ValidityState', 'HTMLInputElement.validity must be a ValidityState instance');
+ assert_true(input.validity.tooLong, "tooLong must be true since the user just changed the input's value and the value exceeds the maxlength");
+ });
+ done();
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-url-delete-manual.html b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-url-delete-manual.html
new file mode 100644
index 000000000..17039a71a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-input-url-delete-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>input[type="url"], ValidityState.tooLong and user editing</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#limiting-user-input-length:-the-maxlength-attribute">
+ <meta name="flags" content="interact">
+ <meta name="assert" content="Per the 'Constraint validation' definition in the referenced section, an input whose value was edited by the user but still exceeds the input's maxlength should suffer from being too long.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>Delete one character from the following text input:</p>
+ <input type="url" value="http://example.com/foo" maxlength="12" autocomplete="off" id="testinput">
+
+ <div id="log"></div>
+ <script>
+var input = document.getElementById('testinput');
+setup({explicit_timeout: true, explicit_done: true});
+on_event(input, "input", function () {
+ test(function() {
+ assert_class_string(input.validity, 'ValidityState', 'HTMLInputElement.validity must be a ValidityState instance');
+ assert_true(input.validity.tooLong, "tooLong must be true since the user just changed the input's value and the value exceeds the maxlength");
+ });
+ done();
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-textarea-delete-manual.html b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-textarea-delete-manual.html
new file mode 100644
index 000000000..2212a1ca9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/tooLong-textarea-delete-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>textarea, ValidityState.tooLong and user editing</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#limiting-user-input-length:-the-maxlength-attribute">
+ <meta name="flags" content="interact">
+ <meta name="assert" content="Per the 'Constraint validation' definition in the referenced section, a textarea whose value was edited by the user but still exceeds the textarea's maxlength should suffer from being too long.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>Delete one character from the following text area:</p>
+ <textarea maxlength="5" autocomplete="off" id="testinput">0123456789</textarea>
+
+ <div id="log"></div>
+ <script>
+var input = document.getElementById('testinput');
+setup({explicit_timeout: true, explicit_done: true});
+on_event(input, "input", function () {
+ test(function() {
+ assert_class_string(input.validity, 'ValidityState', 'HTMLTextAreaElement.validity must be a ValidityState instance');
+ assert_true(input.validity.tooLong, "tooLong must be true since the user just changed the input's value and the value exceeds the maxlength");
+ });
+ done();
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/.gitkeep b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/contains.json b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/contains.json
new file mode 100644
index 000000000..754a6901d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/contains.json
@@ -0,0 +1,14 @@
+[
+ {
+ "id": "a-form-control-s-value",
+ "original_id": "a-form-control's-value"
+ },
+ {
+ "id": "mutability",
+ "original_id": "mutability"
+ },
+ {
+ "id": "association-of-controls-and-forms",
+ "original_id": "association-of-controls-and-forms"
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form.html b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form.html
new file mode 100644
index 000000000..29a14ca57
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/form-control-infrastructure/form.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLInputElement#form</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id="form">
+<p><button id="button">button</button>
+<p><fieldset id="fieldset">fieldset</fieldset>
+<p><input id="input">
+<p><keygen id="keygen">
+<p><object id="object">object</object>
+<p><output id="output">output</output>
+<p><select id="select"><option>select</option></select>
+<p><textarea id="textarea">textarea</textarea>
+
+<!-- label is special: label.form is an alias for label.control.form -->
+<p><label id="label">label</label>
+<p><label id="label-form" form="form">label-form</label>
+<p><label id="label-form-form2" form="form2">label-form-form2</label>
+<p><label id="label-with-control">label-with-control <input></label>
+<p><label id="label-for" for="control-for-label">label-for</label> <input id="control-for-label">
+<p><label id="label-with-progress">label-with-progress <progress></progress></label>
+<p><label id="label-with-meter">label-with-meter <meter></meter></label>
+<p>
+ <input id="input-with-form-attr-in-form" form="form2">
+ <label id="label-for-control-form-in-form" for="input-with-form-attr-in-form">label-for-control-form-in-form</label>
+</p>
+</form>
+<form id="form2"></form>
+<p>
+ <input id="input-with-form-attr" form="form2">
+ <label id="label-for-control-form" for="input-with-form-attr">label-for-control-form</label>
+</p>
+<!-- misnested tags where form-association is set by the HTML parser -->
+<table>
+ <form id="form3"><!-- self-closes but sets the form element pointer -->
+ <tr>
+ <td><label id="label-in-table">label-in-table</label>
+ <td><label id="label-in-table-with-control">label-in-table <input></label>
+ <td><label id="label-in-table-for" for="input-in-table">label-in-table-for</label>
+ <td><input id="input-in-table"><!-- is associated with form3 -->
+ </tr>
+ </form>
+</table>
+<script>
+var form;
+setup(function() {
+ form = document.getElementById("form");
+ form2 = document.getElementById("form2");
+ form3 = document.getElementById("form3");
+ if (!form || !form2 || !form3) {
+ throw new TypeError("Didn't find all forms");
+ }
+});
+
+var listedElements = [
+ "button",
+ "fieldset",
+ "input",
+ "keygen",
+ "object",
+ "output",
+ "select",
+ "textarea",
+];
+
+listedElements.forEach(function(localName) {
+ test(function() {
+ var control = document.getElementById(localName);
+ assert_equals(control.form, form);
+ }, localName + ".form");
+});
+
+// label
+function testLabel(id, expected) {
+ test(function() {
+ var label = document.getElementById(id);
+ assert_equals(label.control && label.control.form, expected, 'Sanity check: label.control.form');
+ assert_equals(label.form, expected, 'label.form');
+ }, id + ".form");
+}
+
+testLabel("label", null);
+testLabel("label-form", null);
+testLabel("label-form-form2", null);
+testLabel("label-with-control", form);
+testLabel("label-for", form);
+testLabel("label-with-progress", null);
+testLabel("label-with-meter", null);
+testLabel("label-for-control-form-in-form", form2);
+testLabel("label-for-control-form", form2);
+testLabel("label-in-table", null);
+testLabel("label-in-table-with-control", form3);
+testLabel("label-in-table-for", form3);
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/form-submission-0/.gitkeep b/testing/web-platform/tests/html/semantics/forms/form-submission-0/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/form-submission-0/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/form-submission-0/contains.json b/testing/web-platform/tests/html/semantics/forms/form-submission-0/contains.json
new file mode 100644
index 000000000..f9d0d63bf
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/form-submission-0/contains.json
@@ -0,0 +1,30 @@
+[
+ {
+ "id": "introduction-2",
+ "original_id": "introduction-2"
+ },
+ {
+ "id": "implicit-submission",
+ "original_id": "implicit-submission"
+ },
+ {
+ "id": "form-submission-algorithm",
+ "original_id": "form-submission-algorithm"
+ },
+ {
+ "id": "constructing-form-data-set",
+ "original_id": "constructing-form-data-set"
+ },
+ {
+ "id": "url-encoded-form-data",
+ "original_id": "url-encoded-form-data"
+ },
+ {
+ "id": "multipart-form-data",
+ "original_id": "multipart-form-data"
+ },
+ {
+ "id": "plain-text-form-data",
+ "original_id": "plain-text-form-data"
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/forms/form-submission-0/getactionurl.html b/testing/web-platform/tests/html/semantics/forms/form-submission-0/getactionurl.html
new file mode 100644
index 000000000..83de22026
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/form-submission-0/getactionurl.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe id=testframe src="/common/blank.html"></iframe>
+<script>
+var tests = [
+ {
+ name: "Navigating to URL with a data scheme",
+ action: "data:,hello%20world",
+ output: "hello world"
+ }
+];
+tests.forEach(function(test_obj) {
+ test_obj.test = async_test(test_obj.name);
+});
+
+function run_test() {
+ if (tests.length == 0) {
+ return;
+ }
+ var test_obj = tests.pop();
+ var t = test_obj.test;
+ var testframe = document.getElementById("testframe");
+ var testdocument = testframe.contentWindow.document;
+ testdocument.body.innerHTML =
+ "<form id=testform method=get action=\"" + test_obj.action +"\"></form>";
+ testframe.onload = function() {
+ t.step(function() {
+ var body_text = testframe.contentWindow.document.textContent;
+ assert_equals(body_text, test_obj.output);
+ });
+ t.done();
+ run_test();
+ };
+ testdocument.getElementById("testform").submit();
+};
+document.getElementById("testframe").onload = run_test;
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/form-submission-0/submit-entity-body.html b/testing/web-platform/tests/html/semantics/forms/form-submission-0/submit-entity-body.html
new file mode 100644
index 000000000..0edc0f3df
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/form-submission-0/submit-entity-body.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var simple_tests = [
+ {
+ name: "form submission from form should navigate to url with x-www-form-urlencoded",
+ input: "<input name=foo value=bara>",
+ enctype: "application/x-www-form-urlencoded",
+ submitelement: "",
+ submitaction: function(doc) { doc.getElementById("testform").submit(); }
+ },
+ {
+ name: "form submission from form should navigate to url with multipart/form-data",
+ input: "<textarea name=foo>bar</textarea>",
+ enctype: "multipart/form-data",
+ submitelement: "",
+ submitaction: function(doc) { doc.getElementById("testform").submit(); }
+ },
+ {
+ name: "form submission from form should navigate to url with text/plain",
+ input: "<textarea name=qux>baz</textarea>",
+ enctype: "text/plain",
+ submitelement: "",
+ submitaction: function(doc) { doc.getElementById("testform").submit(); }
+ },
+ {
+ name: "form submission from button should navigate to url with x-www-form-urlencoded",
+ input: "<input name=foo value=bara>",
+ enctype: "application/x-www-form-urlencoded",
+ submitelement: "<button id=buttonsubmit type=\"submit\">Submit</button>",
+ submitaction: function(doc) { doc.getElementById("buttonsubmit").click(); }
+ },
+ {
+ name: "form submission from button should navigate to url with multipart/form-data",
+ input: "<textarea name=foo>bar</textarea>",
+ enctype: "multipart/form-data",
+ submitelement: "<button id=buttonsubmit type=\"submit\">Submit</button>",
+ submitaction: function(doc) { doc.getElementById("buttonsubmit").click(); }
+ },
+ {
+ name: "form submission from button should navigate to url with text/plain",
+ input: "<textarea name=qux>baz</textarea>",
+ enctype: "text/plain",
+ submitelement: "<button id=buttonsubmit type=\"submit\">Submit</button>",
+ submitaction: function(doc) { doc.getElementById("buttonsubmit").click(); }
+ },
+ {
+ name: "form submission from input should navigate to url with x-www-form-urlencoded",
+ input: "<input name=foo value=bara>",
+ enctype: "application/x-www-form-urlencoded",
+ submitelement: "<input id=inputsubmit type=\"submit\">Submit</input>",
+ submitaction: function(doc) { doc.getElementById("inputsubmit").click(); }
+ },
+ {
+ name: "form submission from input should navigate to url with multipart/form-data",
+ input: "<textarea name=foo>bar</textarea>",
+ enctype: "multipart/form-data",
+ submitelement: "<input id=inputsubmit type=\"submit\">Submit</input>",
+ submitaction: function(doc) { doc.getElementById("inputsubmit").click(); }
+ },
+ {
+ name: "form submission from input should navigate to url with text/plain",
+ input: "<input name=qux value=baz>",
+ enctype: "text/plain",
+ submitelement: "<input id=inputsubmit type=\"submit\">Submit</input>",
+ submitaction: function(doc) { doc.getElementById("inputsubmit").click(); }
+ },
+ {
+ name: "form submission from submit input should contain submit button value",
+ input: "<button type=submit name=notclicked value=nope>not clicked</button>",
+ enctype: "application/x-www-form-urlencoded",
+ submitelement: "<button id=inputsubmit type=\"submit\" name=foo value=bara>Submit</button>",
+ submitaction: function(doc) { doc.getElementById("inputsubmit").click(); }
+ }
+,
+ {
+ name: "form submission from submit button should contain submit button value",
+ input: "<input type=submit name=notclicked value=nope/>",
+ enctype: "application/x-www-form-urlencoded",
+ submitelement: "<input id=inputsubmit type=\"submit\" name=foo value=bara >",
+ submitaction: function(doc) { doc.getElementById("inputsubmit").click(); }
+ }
+];
+simple_tests.forEach(function(test_obj) {
+ test_obj.test = async_test(test_obj.name);
+});
+function run_simple_test() {
+ if (simple_tests.length == 0) {
+ return;
+ }
+ var test_obj = simple_tests.pop();
+ var t = test_obj.test;
+ var testframe = document.getElementById("testframe");
+ var testdocument = testframe.contentWindow.document;
+ testdocument.body.innerHTML =
+ "<form id=testform method=post action=\"form-submission.py\" enctype=\"" + test_obj.enctype + "\">" +
+ test_obj.input +
+ test_obj.submitelement +
+ "</form>";
+ testframe.onload = function() {
+ t.step(function (){
+ var response = testframe.contentDocument.documentElement.textContent;
+ assert_equals(response, "OK");
+ });
+ t.done();
+ run_simple_test();
+ };
+ test_obj.submitaction(testdocument);
+}
+</script>
+<iframe id=testframe src="/common/blank.html" onload="run_simple_test();"></iframe>
diff --git a/testing/web-platform/tests/html/semantics/forms/form-submission-0/url-encoded.html b/testing/web-platform/tests/html/semantics/forms/form-submission-0/url-encoded.html
new file mode 100644
index 000000000..5965b6633
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/form-submission-0/url-encoded.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe id=testframe src="/common/blank.html"></iframe>
+<script>
+var simple_tests = [
+ {
+ name: "text.simple",
+ input: "<input name=foo value=bara>",
+ output: "foo=bara"
+ },
+ {
+ name: "textarea.simple",
+ input: "<textarea name=foo>bar</textarea>",
+ output: "foo=bar"
+ },
+];
+simple_tests.forEach(function(test_obj) {
+ test_obj.test = async_test(test_obj.name);
+});
+function run_simple_test() {
+ if (simple_tests.length == 0) {
+ return;
+ }
+ test_obj = simple_tests.pop();
+ var t = test_obj.test;
+ var testframe = document.getElementById("testframe");
+ var testdocument = testframe.contentWindow.document;
+ testdocument.body.innerHTML =
+ "<form id=testform action=\"/common/blank.html\">" +
+ test_obj.input +
+ "</form>";
+ testframe.onload = function() {
+ t.step(function (){
+ var get_url = testframe.contentWindow.location.toString();
+ var encoded = get_url.substr(get_url.indexOf("?") + 1);
+ assert_equals(encoded, test_obj.output);
+ });
+ t.done();
+ run_simple_test();
+ };
+ testdocument.getElementById("testform").submit();
+}
+document.getElementById("testframe").onload = run_simple_test;
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/historical.html b/testing/web-platform/tests/html/semantics/forms/historical.html
new file mode 100644
index 000000000..6873ecd25
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/historical.html
@@ -0,0 +1,85 @@
+<!doctype html>
+<title>Historical forms features should not be supported</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<form id=form hidden>
+ <label id=label></label>
+ <input id=input>
+ <button id=button></button>
+ <select id=select>
+ <optgroup id=optgroup>
+ <option id=option>
+ </select>
+ <datalist id=datalist></datalist>
+ <textarea id=textarea></textarea>
+ <progress id=progress></progress>
+ <meter id=meter></meter>
+ <fieldset id=fieldset>
+ <legend id=legend></legend>
+ </fieldset>
+</form>
+
+<form hidden action="isindex-support.txt" target=isindex_iframe id=isindex_form>
+ <input name=isindex value=x>
+ <iframe name=isindex_iframe id=isindex_iframe></iframe>
+</form>
+<script>
+var tags = ['form', 'label', 'input', 'button', 'select', 'datalist',
+'optgroup', 'option', 'textarea', 'progress', 'meter', 'fieldset', 'legend'];
+
+function t(property, tagName) {
+ var tagNames = tagName ? [tagName] : tags;
+ tagNames.forEach(function(tagName) {
+ test(function() {
+ assert_false(property in document.getElementById(tagName));
+ }, tagName + '.' + property + ' should not be supported');
+ });
+}
+
+function inputType(type) {
+ test(function() {
+ var input = document.createElement('input');
+ input.type = type;
+ assert_equals(input.type, 'text');
+ }, '<input type=' + type + '> should not be supported');
+}
+
+// <input type=range multiple>
+// added in https://github.com/whatwg/html/commit/1efac390abb3f95df61f2d2ac6c0feb47349d97b
+// removed in https://github.com/whatwg/html/commit/b598d4f873fb8c27d4b23b033837108edfbc3d75
+t('valueLow', 'input');
+t('valueHigh', 'input');
+
+// requestAutoComplete()
+// added in https://github.com/whatwg/html/commit/321659e4db11228857632487ab72b6959db1ba86
+// removed in https://github.com/whatwg/html/commit/6a257aae619f85390eee20b47767f34887450fcd
+t('requestAutocomplete', 'form');
+t('onautocomplete', 'form');
+t('onautocompleteerror', 'form');
+
+// <input type=datetime>
+// added in WF2
+// removed in https://github.com/whatwg/html/commit/80ba4fa24e5d3d81a10aa1bbd8a2f72f4bcc3f7c
+inputType('datetime');
+
+// <progress form>, <meter form>
+// removed in https://github.com/whatwg/html/commit/3814376a311837ddfac229d9a631cd10adf53157
+t('form', 'progress');
+t('form', 'meter');
+
+// form.item(), form.namedItem()
+// removed in https://github.com/whatwg/html/commit/da87ab9009d5aeca95a602e718439e35b00d0731
+t('item', 'form');
+t('namedItem', 'form');
+
+// <input name=isindex>
+// removed in https://github.com/whatwg/html/commit/5c44abc734eb483f9a7ec79da5844d2fe63d9c3b
+async_test(function() {
+ var iframe = document.getElementById('isindex_iframe');
+ iframe.onload = this.step_func_done(function() {
+ assert_regexp_match(iframe.contentWindow.location.href, /\?isindex=x$/);
+ });
+ document.getElementById('isindex_form').submit();
+}, '<input name=isindex> should not be supported');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/introduction-1/.gitkeep b/testing/web-platform/tests/html/semantics/forms/introduction-1/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/introduction-1/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/introduction-1/contains.json b/testing/web-platform/tests/html/semantics/forms/introduction-1/contains.json
new file mode 100644
index 000000000..12a866813
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/introduction-1/contains.json
@@ -0,0 +1,34 @@
+[
+ {
+ "id": "writing-a-form-s-user-interface",
+ "original_id": "writing-a-form's-user-interface"
+ },
+ {
+ "id": "implementing-the-server-side-processing-for-a-form",
+ "original_id": "implementing-the-server-side-processing-for-a-form"
+ },
+ {
+ "id": "configuring-a-form-to-communicate-with-a-server",
+ "original_id": "configuring-a-form-to-communicate-with-a-server"
+ },
+ {
+ "id": "client-side-form-validation",
+ "original_id": "client-side-form-validation"
+ },
+ {
+ "id": "enabling-client-side-automatic-filling-of-form-controls",
+ "original_id": "enabling-client-side-automatic-filling-of-form-controls"
+ },
+ {
+ "id": "improving-the-user-experience-on-mobile-devices",
+ "original_id": "improving-the-user-experience-on-mobile-devices"
+ },
+ {
+ "id": "the-difference-between-the-field-type-the-autofill-field-name-and-the-input-modality",
+ "original_id": "the-difference-between-the-field-type,-the-autofill-field-name,-and-the-input-modality"
+ },
+ {
+ "id": "input-author-notes",
+ "original_id": "input-author-notes"
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/forms/resetting-a-form/.gitkeep b/testing/web-platform/tests/html/semantics/forms/resetting-a-form/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/resetting-a-form/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/resetting-a-form/reset-form.html b/testing/web-platform/tests/html/semantics/forms/resetting-a-form/reset-form.html
new file mode 100644
index 000000000..b74b52c46
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/resetting-a-form/reset-form.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Resetting a form</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#concept-form-reset">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#category-reset">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form name="fm1" style="display:none">
+ <input value="abc" id="ipt1" />
+ <input id="ipt2" />
+ <input type="radio" id="rd1" checked="checked" />
+ <input type="radio" id="rd2"/>
+ <input type="checkbox" id="cb1" checked="checked" />
+ <input type="checkbox" id="cb2" />
+ <textarea id="ta">abc</textarea>
+ <!--<keygen id="kg"></keygen>-->
+ <output id="opt">5</output>
+ <select id="slt1">
+ <option value="1">ITEM1</option>
+ <option value="2">ITEM2</option>
+ </select>
+ <select id="slt2">
+ <option value="1">ITEM1</option>
+ <option value="2" selected>ITEM2</option>
+ </select>
+ <select id="slt3" multiple>
+ <option value="1">ITEM1</option>
+ <option value="2" selected>ITEM2</option>
+ <option value="3" selected>ITEM3</option>
+ </select>
+ <button id="rst1" type="reset">Reset1</button>
+ <input id="rst2" type="reset" value="Reset2" />
+</form>
+<script>
+
+runTest(function() {
+ document.forms.fm1.reset();
+}, "by calling the reset() method");
+
+runTest(function() {
+ document.getElementById("rst1").click();
+}, "by clicking the button in reset status");
+
+runTest(function() {
+ document.getElementById("rst2").click();
+}, "by clicking the input in reset status");
+
+function setPreconditions (arg) {
+ document.getElementById("ipt1").value = "123";
+ document.getElementById("ipt2").value = "123";
+ document.getElementById("rd1").checked = false;
+ document.getElementById("rd2").checked = true;
+ document.getElementById("cb1").checked = false;
+ document.getElementById("cb2").checked = true;
+ document.getElementById("ta").value = "123";
+ document.getElementById("opt").textContent = "abc";
+ document.getElementById("slt1").value = "2";
+ document.getElementById("slt2").value = "1";
+ document.getElementById("slt3").options[0].selected = true;
+ document.getElementById("slt3").options[1].selected = false;
+ document.getElementById("slt3").options[2].selected = false;
+
+ assert_equals(document.getElementById("ipt1").value, "123", "Precondition 1");
+ assert_equals(document.getElementById("ipt2").value, "123", "Precondition 2");
+ assert_false(document.getElementById("rd1").checked, "Precondition 3");
+ assert_true(document.getElementById("rd2").checked, "Precondition 4");
+ assert_false(document.getElementById("cb1").checked, "Precondition 5");
+ assert_true(document.getElementById("cb2").checked, "Precondition 6");
+ assert_equals(document.getElementById("ta").value, "123", "Precondition 17");
+ assert_equals(document.getElementById("opt").textContent, "abc", "Precondition 8");
+ assert_true(document.getElementById("slt1").options[1].selected, "Precondition 9");
+ assert_true(document.getElementById("slt2").options[0].selected, "Precondition 10");
+ assert_true(document.getElementById("slt3").options[0].selected, "Precondition 11");
+ assert_false(document.getElementById("slt3").options[1].selected, "Precondition 12");
+ assert_false(document.getElementById("slt3").options[2].selected, "Precondition 13");
+}
+
+function runTest(reset, description) {
+ test(function() {
+ setPreconditions("Setting preconditions for resetting " + description);
+ reset();
+ assert_equals(document.getElementById("ipt1").value, "abc", "The value of the input element in text status should be 'abc'.");
+ assert_equals(document.getElementById("ipt2").value, "", "The value of the input element in text status should be empty string.");
+ assert_true(document.getElementById("rd1").checked, "The checked attribute of the input element in radio should be true.");
+ assert_false(document.getElementById("rd2").checked, "The checked attribute of the input element in radio should be false.");
+ assert_true(document.getElementById("cb1").checked, "The checked attribute of the input element in checkbox should be true.");
+ assert_false(document.getElementById("cb2").checked, "The checked attribute of the input element in checkbox should be false.");
+ assert_equals(document.getElementById("ta").value, document.getElementById("ta").textContent, "The value attribute of the textarea element should be reset.");
+ assert_equals(document.getElementById("ta").value, "abc", "The value attribute of the textarea element should be 'abc'.");
+ assert_equals(document.getElementById("opt").textContent, document.getElementById("opt").defaultValue, "The textContent of the output element should be reset.");
+ assert_equals(document.getElementById("opt").textContent, "abc", "The textContent of the output element should be 'abc'.");
+ assert_true(document.getElementById("slt1").options[0].selected, "The first option in the select element should be selected.");
+ assert_false(document.getElementById("slt1").options[1].selected, "The second option in the select element should not be selected.");
+ assert_false(document.getElementById("slt2").options[0].selected, "The first option in the select element should not be selected.");
+ assert_true(document.getElementById("slt2").options[1].selected, "The second option in the select element should be selected.");
+ assert_false(document.getElementById("slt3").options[0].selected, "The first option in the select element with multiple attribute should not be selected.");
+ assert_true(document.getElementById("slt3").options[1].selected, "The second option in the select element with multiple attribute should be selected.");
+ assert_true(document.getElementById("slt3").options[2].selected, "The third option in the select element with multiple attribute should be selected.");
+ //TODO: The keygen reset algorithm
+ }, "Resetting the form " + description);
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/.gitkeep b/testing/web-platform/tests/html/semantics/forms/textfieldselection/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/original-id.json b/testing/web-platform/tests/html/semantics/forms/textfieldselection/original-id.json
new file mode 100644
index 000000000..d9fe43585
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/original-id.json
@@ -0,0 +1 @@
+{"original_id":"textFieldSelection"} \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/select-event.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/select-event.html
new file mode 100644
index 000000000..92a12d12e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/select-event.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>text field selection: select()</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<textarea>foobar</textarea>
+<script>
+ var input_types = ["text", "search", "tel", "url", "password"],
+ t1 = async_test("select() on textarea queues select event"),
+ q1 = false;
+
+ input_types.forEach(function(type) {
+ var input = document.createElement("input"),
+ t = async_test("select() on input type " + type + " queues select event"),
+ q = false;
+ t.step(function() {
+ input.type = type;
+ input.value = "foobar";
+ document.body.appendChild(input);
+ input.onselect = t.step_func_done(function(e) {
+ assert_true(q, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_true(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ });
+ input.select();
+ q=true;
+ });
+ });
+
+ document.querySelector("textarea").onselect = t1.step_func_done(function(e) {
+ assert_true(q1, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_true(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ });
+
+ t1.step(function() {
+ document.querySelector("textarea").select();
+ q1=true;
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-after-content-change.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-after-content-change.html
new file mode 100644
index 000000000..90ebc28a2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-after-content-change.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Selection indices after content change</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ test(function() {
+ var input = document.createElement("input");
+ input.focus();
+ input.value = "something something something dark side";
+ input.setSelectionRange(4,20);
+ assert_equals(input.selectionStart, 4);
+ assert_equals(input.selectionEnd, 20);
+ input.value = "It's a trap!";
+ assert_equals(input.selectionStart, input.value.length);
+ assert_equals(input.selectionEnd, input.value.length);
+}, "Selection indices after reseting content");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-not-application-textarea.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-not-application-textarea.html
new file mode 100644
index 000000000..c17ad3232
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-not-application-textarea.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>text field selection (textarea)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ test(function() {
+ var el = document.createElement("textarea");
+ assert_equals(el.selectionStart, 0);
+ assert_equals(el.selectionEnd, 0);
+ el.selectionStart = 1;
+ el.selectionEnd = 1;
+ el.selectionDirection = "forward";
+ el.setRangeText("foobar");
+ el.setSelectionRange(0, 1);
+ }, "text field selection for the input textarea");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-not-application.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-not-application.html
new file mode 100644
index 000000000..576e6d125
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-not-application.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>text field selection</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var types = ["hidden", "email", "datetime-local", "date", "month", "week", "time", "number", "range", "color", "checkbox", "radio", "file", "submit", "image", "reset", "button"]; //types for which the API doesn't apply
+ var types2 = ["text", "search", "tel", "url", "password"]; //types for which the API applies
+
+ types.forEach(function(type){
+ test(function(){
+ var el = document.createElement("input");
+ el.type = type;
+ assert_throws("InvalidStateError", function(){
+ el.selectionStart;
+ });
+ assert_throws("InvalidStateError", function(){
+ el.selectionEnd;
+ });
+ assert_throws("InvalidStateError", function(){
+ el.selectionDirection;
+ });
+ assert_throws("InvalidStateError", function(){
+ el.setRangeText("foobar");
+ });
+ assert_throws("InvalidStateError", function(){
+ el.setSelectionRange(0, 1);
+ });
+ }, "text field selection for the input " + type);
+ });
+
+ types2.forEach(function(type) {
+ test(function() {
+ var el = document.createElement("input");
+ el.type = type;
+ assert_equals(el.selectionStart, 0);
+ assert_equals(el.selectionEnd, 0);
+ el.selectionStart = 1;
+ el.selectionEnd = 1;
+ el.selectionDirection = "forward";
+ el.setRangeText("foobar");
+ el.setSelectionRange(0, 1);
+ }, "text field selection for the input " + type);
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection.html
new file mode 100644
index 000000000..709d26e86
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML>
+<title>test if select() API returns correct attributes</title>
+<meta charset="UTF-8">
+<meta name="timeout" content="long">
+<link rel="author" title="Koji Tashiro" href="mailto:koji.tashiro@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/association-of-controls-and-forms.html#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<script>
+ var body = document.getElementsByTagName("body").item(0);
+ var dirs = ['forward', 'backward', 'none'];
+ var sampleText = "0123456789";
+
+ var createInputElement = function(value) {
+ var el = document.createElement("input");
+ el.type = "text";
+ el.value = value;
+ body.appendChild(el);
+ return el;
+ };
+
+ var createTextareaElement = function(value) {
+ var el = document.createElement("textarea");
+ el.value = value;
+ body.appendChild(el);
+ return el;
+ };
+
+
+ test(function() {
+ var text = 'a';
+ for (var i=0; i<255; i++) {
+ var el = createInputElement(text);
+ el.select();
+ var selectionText = el.value.substring(el.selectionStart, el.selectionEnd);
+ assert_equals(selectionText, text, "Selection text mismatched");
+ el.parentNode.removeChild(el);
+ text += 'a';
+ }
+ }, "test if selection text is correct for input");
+
+
+ test(function() {
+ var text = 'a';
+ for (var i=0; i<255; i++) {
+ var el = createTextareaElement(text);
+ el.select();
+ var selectionText = el.value.substring(el.selectionStart, el.selectionEnd);
+ assert_equals(selectionText, text, "Selection text mismatched");
+ el.parentNode.removeChild(el);
+ text += 'a';
+ }
+ }, "test if selection text is correct for textarea");
+
+
+ test(function() {
+ var text = 'あ';
+ for (var i=0; i<255; i++) {
+ var el = createInputElement(text);
+ el.select();
+ var selectionText = el.value.substring(el.selectionStart, el.selectionEnd);
+ assert_equals(selectionText, text, "Selection text mismatched");
+ el.parentNode.removeChild(el);
+ text += 'あ';
+ }
+ }, "test if non-ascii selection text is correct for input");
+
+
+ test(function() {
+ var text = 'あ';
+ for (var i=0; i<255; i++) {
+ var el = createTextareaElement(text);
+ el.select();
+ var selectionText = el.value.substring(el.selectionStart, el.selectionEnd);
+ assert_equals(selectionText, text, "Selection text mismatched");
+ el.parentNode.removeChild(el);
+ text += 'あ';
+ }
+ }, "test if non-ascii selection text is correct for textarea");
+
+
+ test(function() {
+ var el = createInputElement(sampleText);
+ // If there is no selection, then it must return the offset(in logical order)
+ // to the character that immediately follows the text entry cursor.
+ assert_equals(el.selectionStart, el.value.length, "SelectionStart offset without selection");
+ el.select();
+ assert_equals(el.selectionStart, 0, "SelectionStart offset");
+ el.parentNode.removeChild(el);
+ }, "test SelectionStart offset for input");
+
+
+ test(function() {
+ var el = createTextareaElement(sampleText);
+ // If there is no selection, then it must return the offset(in logical order)
+ // to the character that immediately follows the text entry cursor.
+ assert_equals(el.selectionStart, el.value.length, "SelectionStart offset without selection");
+ el.select();
+ assert_equals(el.selectionStart, 0, "SelectionStart offset");
+ el.parentNode.removeChild(el);
+ }, "test SelectionStart offset for textarea");
+
+
+ test(function() {
+ var el = createInputElement(sampleText);
+ // If there is no selection, then it must return the offset(in logical order)
+ // to the character that immediately follows the text entry cursor.
+ assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset without selection");
+ el.select();
+ assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset");
+ el.parentNode.removeChild(el);
+ }, "test SelectionEnd offset for input");
+
+
+ test(function() {
+ var el = createTextareaElement(sampleText);
+ // If there is no selection, then it must return the offset(in logical order)
+ // to the character that immediately follows the text entry cursor.
+ assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset without selection");
+ el.select();
+ assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset");
+ el.parentNode.removeChild(el);
+ }, "test SelectionEnd offset for textarea");
+
+
+ test(function() {
+ var el = createInputElement(sampleText);
+ assert_in_array(el.selectionDirection, dirs, "SelectionDirection");
+ el.select();
+ assert_in_array(el.selectionDirection, dirs, "SelectionDirection");
+ el.parentNode.removeChild(el);
+ }, "test SelectionDirection for input");
+
+
+ test(function() {
+ var el = createInputElement(sampleText);
+ assert_in_array(el.selectionDirection, dirs, "SelectionDirection");
+ el.select();
+ assert_in_array(el.selectionDirection, dirs, "SelectionDirection");
+ el.parentNode.removeChild(el);
+ }, "test SelectionDirection for textarea");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html
new file mode 100644
index 000000000..edc8f2a86
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>text field selection: setRangeText</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #display_none {display:none;}
+</style>
+<div id="log"></div>
+<input type=text id=text value="foobar">
+<input type=search id=search value="foobar">
+<input type=tel id=tel value="foobar">
+<input type=url id=url value="foobar">
+<input type=password id=password value="foobar">
+<input id=display_none value="foobar">
+<textarea id=textarea>foobar</textarea>
+<script>
+ var input = document.createElement("input");
+ input.id = "input_not_in_doc";
+ input.value = "foobar";
+
+ var elements = [
+ document.getElementById("text"),
+ document.getElementById("search"),
+ document.getElementById("tel"),
+ document.getElementById("url"),
+ document.getElementById("password"),
+ document.getElementById("display_none"),
+ document.getElementById("textarea"),
+ input,
+ ]
+
+ elements.forEach(function(element) {
+ test(function() {
+ element.value = "foobar";
+ element.selectionStart = 0;
+ element.selectionEnd = 3;
+ assert_equals(element.selectionStart, 0);
+ assert_equals(element.selectionEnd, 3);
+ element.setRangeText("foobar2");
+ assert_equals(element.value, "foobar2bar");
+ assert_equals(element.selectionStart, 0);
+ assert_equals(element.selectionEnd, 7);
+ element.setRangeText("foobar3", 7, 10);
+ assert_equals(element.value, "foobar2foobar3");
+ }, element.id + " setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments");
+
+ test(function(){
+ element.value = "foobar";
+ element.selectionStart = 0;
+ element.selectionEnd = 0;
+
+ element.setRangeText("foobar2", 0, 3); // no 4th arg, default "preserve"
+ assert_equals(element.value, "foobar2bar");
+ assert_equals(element.selectionStart, 0);
+ assert_equals(element.selectionEnd, 0);
+ }, element.id + " selectionMode missing");
+
+ test(function(){
+ element.value = "foobar"
+ element.setRangeText("foo", 3, 6, "select");
+ assert_equals(element.value, "foofoo");
+ assert_equals(element.selectionStart, 3);
+ assert_equals(element.selectionEnd, 6);
+ }, element.id + " selectionMode 'select'");
+
+ test(function(){
+ element.value = "foobar"
+ element.setRangeText("foo", 3, 6, "start");
+ assert_equals(element.value, "foofoo");
+ assert_equals(element.selectionStart, 3);
+ assert_equals(element.selectionEnd, 3);
+ }, element.id + " selectionMode 'start'");
+
+ test(function(){
+ element.value = "foobar"
+ element.setRangeText("foobar", 3, 6, "end");
+ assert_equals(element.value, "foofoobar");
+ assert_equals(element.selectionStart, 9);
+ assert_equals(element.selectionEnd, 9);
+ }, element.id + " selectionMode 'end'");
+
+ test(function(){
+ element.value = "foobar"
+ element.selectionStart = 0;
+ element.selectionEnd = 5;
+ assert_equals(element.selectionStart, 0);
+ element.setRangeText("", 3, 6, "preserve");
+ assert_equals(element.value, "foo");
+ assert_equals(element.selectionStart, 0);
+ assert_equals(element.selectionEnd, 3);
+ }, element.id + " selectionMode 'preserve'");
+
+ test(function(){
+ assert_throws("INDEX_SIZE_ERR", function() {
+ element.setRangeText("barfoo", 2, 1);
+ });
+ }, element.id + " setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception");
+
+ test(function(){
+ assert_throws(new TypeError(), function() {
+ element.setRangeText();
+ });
+ }, element.id + " setRangeText without argument throws a type error");
+
+ async_test(function() {
+ var q = false;
+ element.onselect = this.step_func_done(function(e) {
+ assert_true(q, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_false(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ });
+ element.setRangeText("foobar2", 0, 6);
+ q = true;
+ }, element.id + " setRangeText fires a select event");
+ })
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
new file mode 100644
index 000000000..60d591baf
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
@@ -0,0 +1,274 @@
+<!DOCTYPE HTML>
+<title>Test of text field setSelectionRange</title>
+<link rel="author" title="Takeharu.Oshida" href="mailto:georgeosddev@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="hide" style="display: block">
+ <input id="a" type="text" value="abcde">
+ <textarea id="b">abcde</textarea>
+</div>
+<script>
+test(function() {
+ var input = document.getElementById("a");
+ test(function() {
+ assert_equals(typeof(input.setSelectionRange), "function", "element must have 'setSelectionRange' function");
+ },"input typeof(input.setSelectionRange)'");
+
+ test(function() {
+ assert_equals(input.setSelectionRange(0,1,"forward"),undefined,"setSelectionRange is void functuon");
+ },"input setSelectionRange return void");
+
+ test(function() {
+ input.setSelectionRange(0,1)
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(0,1)');
+
+ test(function() {
+ input.setSelectionRange(0,input.value.length+1)
+ assert_equals(input.selectionEnd, input.value.length, "Arguments greater than the length of the value of the text field must be treated as pointing at the end of the text field");
+ },'input setSelectionRange(0,input.value.length+1)');
+
+ test(function() {
+ input.setSelectionRange(input.value.length+1,input.value.length+1)
+ assert_equals(input.selectionStart, input.value.length, "Arguments (start) greater than the length of the value of the text field must be treated as pointing at the end of the text field");
+ assert_equals(input.selectionEnd, input.value.length, "Arguments (end) greater than the length of the value of the text field must be treated as pointing at the end of the text field");
+ },'input setSelectionRange(input.value.length+1,input.value.length+1)');
+
+ test(function() {
+ input.setSelectionRange(input.value.length+1,1)
+ assert_equals(input.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(input.value.length+1,input.value.length+1)');
+
+ test(function() {
+ input.setSelectionRange(2,2)
+ assert_equals(input.selectionStart, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(input.selectionEnd, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ },'input setSelectionRange(2,2)');
+
+ test(function() {
+ input.setSelectionRange(2,1)
+ assert_equals(input.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(input.selectionEnd, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ },'input setSelectionRange(2,1)');
+
+ test(function() {
+ input.setSelectionRange(0,1,"backward")
+ assert_equals(input.selectionDirection, "backward", 'The direction of the selection must be set to backward if direction is a case-sensitive match for the string "backward"');
+ },'input direction of setSelectionRange(0,1,"backward")');
+
+ test(function() {
+ input.setSelectionRange(0,1,"forward")
+ assert_equals(input.selectionDirection, "forward", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "forward"');
+ },'input direction of setSelectionRange(0,1,"forward")');
+
+ test(function() {
+ input.setSelectionRange(0,1,"none")
+ assert_equals(input.selectionDirection, "none", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "none"');
+ },'input direction of setSelectionRange(0,1,"none")');
+
+ test(function() {
+ input.setSelectionRange(0,1,"hoge")
+ assert_equals(input.selectionDirection, "none", "otherwise");
+ },'input direction of setSelectionRange(0,1,"hoge")');
+
+ test(function() {
+ input.setSelectionRange(0,1,"BACKWARD")
+ assert_equals(input.selectionDirection, "none", "selectionDirection should be 'none'");
+ },'input direction of setSelectionRange(0,1,"BACKWARD")');
+
+ test(function() {
+ input.setSelectionRange(0,1)
+ assert_equals(input.selectionDirection, "none", "if the argument is omitted");
+ },'input direction of setSelectionRange(0,1)');
+
+ test(function() {
+ input.setSelectionRange(1,-1);
+ assert_equals(input.selectionStart, 1, "element.selectionStart should be 1");
+ assert_equals(input.selectionEnd, input.value.length, "ECMAScript conversion to unsigned long");
+ },'input setSelectionRange(1,-1)');
+
+ test(function() {
+ input.setSelectionRange(-1,1);
+ assert_equals(input.selectionStart, 1, "ECMAScript conversion to unsigned long + if end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(-1,1)');
+
+ test(function() {
+ input.setSelectionRange("string",1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange("string",1)');
+
+ test(function() {
+ input.setSelectionRange(true,1);
+ assert_equals(input.selectionStart, 1, "element.selectionStart should be 1");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(true,1)');
+
+ test(function() {
+ input.setSelectionRange([],1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange([],1)');
+
+ test(function() {
+ input.setSelectionRange({},1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange({},1)');
+
+ test(function() {
+ input.setSelectionRange(NaN,1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(NaN,1)');
+
+ test(function() {
+ input.setSelectionRange(null,1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(null,1)');
+
+ test(function() {
+ input.setSelectionRange(undefined,1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(undefined,1)');
+},"test of input.setSelectionRange");
+
+async_test(function() {
+ var q = false;
+ var input = document.getElementById("a");
+ input.addEventListener("select", this.step_func_done(function(e) {
+ assert_true(q, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_true(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ }));
+ input.setSelectionRange(0, 1);
+ q = true;
+}, "input setSelectionRange fires a select event");
+
+test(function() {
+ var textarea = document.getElementById("b");
+ test(function() {
+ assert_equals(typeof(textarea.setSelectionRange), "function", "element must have 'setSelectionRange' function");
+ },"textarea typeof(input.setSelectionRange)'");
+
+ test(function() {
+ assert_equals(textarea.setSelectionRange(0,1,"forward"),undefined,"setSelectionRange is void functuon");
+ },"textarea setSelectionRange return void");
+
+ test(function() {
+ textarea.setSelectionRange(0,1)
+ assert_equals(textarea.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'textarea setSelectionRange(0,1)');
+
+ test(function() {
+ textarea.setSelectionRange(0,textarea.value.length+1)
+ assert_equals(textarea.selectionEnd, textarea.value.length, "Arguments greater than the length of the value of the text field must be treated as pointing at the end of the text field");
+ },'textarea setSelectionRange(0,textarea.value.length+1)');
+
+ test(function() {
+ textarea.setSelectionRange(2,2)
+ assert_equals(textarea.selectionStart, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(textarea.selectionEnd, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ },'textarea setSelectionRange(2,2)');
+
+ test(function() {
+ textarea.setSelectionRange(2,1)
+ assert_equals(textarea.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(textarea.selectionEnd, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ },'textarea setSelectionRange(2,1)');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"backward")
+ assert_equals(textarea.selectionDirection, "backward", 'The direction of the selection must be set to backward if direction is a case-sensitive match for the string "backward"');
+ },'textarea direction of setSelectionRange(0,1,"backward")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"forward")
+ assert_equals(textarea.selectionDirection, "forward", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "forward"');
+ },'textarea direction of setSelectionRange(0,1,"forward")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"none")
+ assert_equals(textarea.selectionDirection, "none", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "none"');
+ },'textarea direction of setSelectionRange(0,1,"none")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"hoge")
+ assert_equals(textarea.selectionDirection, "none", "otherwise");
+ },'textarea direction of setSelectionRange(0,1,"hoge")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"BACKWARD")
+ assert_equals(textarea.selectionDirection, "none", "selectionDirection should be 'none'");
+ },'textarea direction of setSelectionRange(0,1,"BACKWARD")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1)
+ assert_equals(textarea.selectionDirection, "none", "if the argument is omitted");
+ },'textarea direction of setSelectionRange(0,1)');
+
+ test(function() {
+ textarea.setSelectionRange("string",1);
+ assert_equals(textarea.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange("string",1)');
+
+ test(function() {
+ textarea.setSelectionRange(true,1);
+ assert_equals(textarea.selectionStart, 1, "element.selectionStart should be 1");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange(true,1)');
+
+ test(function() {
+ textarea.setSelectionRange([],1);
+ assert_equals(textarea.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange([],1)');
+
+ test(function() {
+ textarea.setSelectionRange({},1);
+ assert_equals(textarea.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange({},1)');
+
+ test(function() {
+ textarea.setSelectionRange(NaN,1);
+ assert_equals(textarea.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange(NaN,1)');
+
+ test(function() {
+ textarea.setSelectionRange(null,1);
+ assert_equals(textarea.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange(null,1)');
+
+ test(function() {
+ textarea.setSelectionRange(undefined,1);
+ assert_equals(textarea.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange(undefined,1)');
+},"test of textarea.setSelectionRange");
+
+async_test(function() {
+ var q = false;
+ var textarea = document.getElementById("b");
+ textarea.addEventListener("select", this.step_func_done(function(e) {
+ assert_true(q, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_true(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ }));
+ textarea.setSelectionRange(0, 1);
+ q = true;
+}, "textarea setSelectionRange fires a select event");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-button-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-button-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-button-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-activate-frame.html b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-activate-frame.html
new file mode 100644
index 000000000..37619d791
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-activate-frame.html
@@ -0,0 +1,3 @@
+<form action="about:blank">
+ <button id="submit">Submit</button>
+</form>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-activate.html b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-activate.html
new file mode 100644
index 000000000..43fe96d39
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-activate.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<meta charset="utf-8">
+<title></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="button-activate-frame.html" onload="runTest()"></iframe>
+<script>
+var t = async_test("button activation behaviour submits form");
+function runTest() {
+ var iframe = document.querySelector('iframe');
+ iframe.onload = t.step_func(function() {
+ t.done();
+ });
+ var doc = iframe.contentDocument;
+ doc.querySelector('button').click();
+}
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-events.html b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-events.html
new file mode 100644
index 000000000..9d308bbed
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-events.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Button - events</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-button-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form name="fm1" style="display:none">
+ <button id="btn">BUTTON</button>
+ <button id="menu_btn" type="menu" menu="menu">MENU BUTTON</button>
+ <menu id="menu" label="MENU">
+ <li>Menu item</li>
+ </menu>
+</form>
+<script>
+
+var btn = document.getElementById("btn"),
+ menu_btn = document.getElementById("menu_btn"),
+ t1 = async_test("The submit event must be fired when click a button in submit status"),
+ t2 = async_test("The reset event must be fired when click a button in reset status"),
+ t3 = async_test("The show event must be fired when click a button in menu status");
+
+document.forms.fm1.onsubmit = t1.step_func(function (evt) {
+ evt.preventDefault();
+ assert_true(evt.isTrusted, "The isTrusted attribute of the submit event should be true.");
+ assert_true(evt.bubbles, "The bubbles attribute of the submit event should be true.");
+ assert_true(evt.cancelable, "The cancelable attribute of the submit event should be true.");
+ assert_true(evt instanceof Event, "The submit event is an instance of Event interface.");
+ t1.done();
+});
+
+document.forms.fm1.onreset = t2.step_func(function (evt) {
+ assert_true(evt.isTrusted, "The isTrusted attribute of the reset event should be true.");
+ assert_true(evt.bubbles, "The bubbles attribute of the reset event should be true.");
+ assert_true(evt.cancelable, "The cancelable attribute of the reset event should be true.");
+ assert_true(evt instanceof Event, "The reset event is an instance of Event interface.");
+ t2.done();
+});
+
+document.getElementById("menu").onshow = t3.step_func(function (evt) {
+ assert_true(evt.isTrusted, "The isTrusted attribute of the show event should be true.");
+ assert_equals(evt.relatedTarget, menu_btn, "The relatedTarget attribute should be initialized to the related button element.");
+ assert_true(evt.cancelable, "The cancelable attribute of the show event should be true.");
+ assert_true(evt instanceof RelatedEvent, "The show event is an instance of RelatedEvent interface.");
+ t3.done();
+});
+
+t1.step(function () {
+ btn.type = "submit";
+ assert_equals(btn.type, "submit", "The button type should be 'submit'.");
+ btn.click();
+});
+
+t2.step(function () {
+ btn.type = "reset";
+ assert_equals(btn.type, "reset", "The button type should be 'reset'.");
+ btn.click();
+});
+
+t3.step(function () {
+ assert_equals(menu_btn.type, "menu", "The button type should be 'menu'.");
+ menu_btn.click();
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-validation.html b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-validation.html
new file mode 100644
index 000000000..a153907d7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-validation.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>button element validation</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-button-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<button id=btn1>button</button>
+<button id=btn2 type=submit>button</button>
+<button id=btn3 type=reset>button</button>
+<button id=btn4 type=button>button</button>
+<button id=btn5 type=menu>button</button>
+<button id=btn6 type=foobar>button</button>
+<script>
+ function willValid(element, expectedType, willValidate, desc) {
+ test(function(){
+ assert_equals(element.type, expectedType);
+ assert_equals(element.willValidate, willValidate);
+ }, desc);
+ }
+
+ willValid(document.getElementById('btn1'), "submit", true, "missing type attribute");
+ willValid(document.getElementById('btn2'), "submit", true, "submit type attribute");
+ willValid(document.getElementById('btn3'), "reset", false, "reset type attribute");
+ willValid(document.getElementById('btn4'), "button", false, "button type attribute");
+ willValid(document.getElementById('btn5'), "menu", false, "menu type attribute");
+ willValid(document.getElementById('btn6'), "submit", true, "invalid type attribute");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-datalist-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-datalist-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-datalist-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-datalist-element/datalistoptions.html b/testing/web-platform/tests/html/semantics/forms/the-datalist-element/datalistoptions.html
new file mode 100644
index 000000000..245d43cec
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-datalist-element/datalistoptions.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Datalist element options</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-datalist-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<label>
+ Number:
+ <input list=numbers>
+</label>
+<datalist id=numbers>
+ <label> Select number:
+ <select id=num>
+ <option label="zero" value="0">
+ <option label="one" value="1">
+ <option label="two">2
+ <option label="three" disabled>3
+ <option>
+ </select>
+ </label>
+</datalist>
+<script>
+ test(function(){
+ var datalist = document.getElementById('numbers'),
+ labels = [],
+ values = [];
+ assert_equals(datalist.options.length, 5);
+
+ for (var i = 0, len = datalist.options.length; i < len; i++) {
+ assert_equals(datalist.options[i], datalist.options.item(i));
+ labels.push(datalist.options[i].label);
+ values.push(datalist.options[i].value);
+ }
+ assert_array_equals(labels, ["zero", "one", "two", "three", ""]);
+ assert_array_equals(values, ["0", "1", "2", "3", ""]);
+ }, "options label/value");
+
+ test(function(){
+ assert_false(document.getElementById('num').willValidate);
+ }, "If an element has a datalist element ancestor, it is barred from constraint validation");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html
new file mode 100644
index 000000000..0c394cbed
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: HTMLFieldSetElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-fieldset-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form name="fm1" style="display:none">
+ <fieldset id="fs_outer">
+ <legend><input type="checkbox" name="cb"></legend>
+ <input type=text name="txt" id="ctl1">
+ <button id="ctl2" name="btn">BUTTON</button>
+ <fieldset id="fs_inner">
+ <input type="text" name="txt_inner">
+ <progress name="pg" value="0.5"></progress>
+ </fieldset>
+ </fieldset>
+</form>
+<script>
+
+var fm1,
+ fs_outer,
+ children_outer;
+
+setup(function () {
+ fm1 = document.forms.fm1;
+ fs_outer = document.getElementById("fs_outer");
+ children_outer = fs_outer.elements;
+});
+
+test(function () {
+ assert_equals(fs_outer.type, "fieldset", "The value of type attribute is incorrect.");
+}, "The type attribute must return 'fieldset'");
+
+test(function () {
+ assert_equals(fs_outer.form, fm1, "The fieldset should have a form owner.");
+}, "The form attribute must return the fieldset's form owner");
+
+test(function () {
+ assert_true(children_outer instanceof HTMLFormControlsCollection,
+ "The elements attribute should be an HTMLFormControlsCollection object");
+}, "The elements must return an HTMLFormControlsCollection object");
+
+test(function () {
+ var fs_inner = document.getElementById("fs_inner");
+ var children_inner = fs_inner.elements;
+ assert_array_equals(children_inner, [fm1.txt_inner],
+ "The items in the collection must be children of the inner fieldset element.");
+ assert_array_equals(children_outer, [fm1.cb, fm1.txt, fm1.btn, fm1.fs_inner, fm1.txt_inner],
+ "The items in the collection must be children of the outer fieldset element.");
+}, "The controls must root at the fieldset element");
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-001.html b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-001.html
new file mode 100644
index 000000000..cbbda4ab0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-001.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Fieldset disabled</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-fieldset-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form>
+ <fieldset id=fs disabled>
+ <legend>
+ <input type=checkbox id=clubc_l1>
+ <input type=radio id=clubr_l1>
+ <input type=text id=clubt_l1>
+ </legend>
+ <legend><input type=checkbox id=club_l2></legend>
+ <p><label>Name on card: <input id=clubname required></label></p>
+ <p><label>Card number: <input id=clubnum required pattern="[-0-9]+"></label></p>
+ </fieldset>
+ <fieldset id=fs2 disabled>
+ <p><legend><input type=checkbox id=club2></legend></p>
+ <p><label>Name on card: <input id=clubname2 required></label></p>
+ <p><label>Card number: <input id=clubnum2 required pattern="[-0-9]+"></label></p>
+ </fieldset>
+ <fieldset id=fs3 disabled>
+ <fieldset>
+ <legend><input type=checkbox id=club3></legend>
+ </fieldset>
+ <p><label>Name on card: <input id=clubname3 required></label></p>
+ <p><label>Card number: <input id=clubnum3 required pattern="[-0-9]+"></label></p>
+ </fieldset>
+ <fieldset id=fs4 disabled>
+ <legend>
+ <fieldset><input type=checkbox id=club4></fieldset>
+ </legend>
+ <p><label>Name on card: <input id=clubname4 required></label></p>
+ <p><label>Card number: <input id=clubnum4 required pattern="[-0-9]+"></label></p>
+ </fieldset>
+</form>
+<script>
+ test(function () {
+ assert_true(document.getElementById('fs').disabled, "The fieldset is disabled");
+ assert_false(document.getElementById('clubname').willValidate, "fieldset is disabled so is input 'clubname'");
+ assert_false(document.getElementById('clubnum').willValidate, "fieldset is disabled so is input 'clubnum'");
+ assert_true(document.getElementById('clubc_l1').willValidate, "input 'clubc_l1' is descendant of the first legend child of the fieldset. It should not be disabled");
+ assert_true(document.getElementById('clubr_l1').willValidate, "input 'clubr_l1' is descendant of the first legend child of the fieldset. It should not be disabled");
+ assert_true(document.getElementById('clubt_l1').willValidate, "input 'clubt_l1' is descendant of the first legend child of the fieldset. It should not be disabled");
+ assert_false(document.getElementById('club_l2').willValidate, "input 'club_l2' is a descendant of the second legend child of the fieldset. It should be disabled");
+ }, "The disabled attribute, when specified, causes all the form control descendants of the fieldset element, excluding those that are descendants of the fieldset element's first legend element child, if any, to be disabled.");
+
+ test(function () {
+ assert_true(document.getElementById('fs2').disabled, "The fieldset is disabled");
+ assert_false(document.getElementById('clubname2').willValidate, "fieldset is disabled so is input 'clubname2'");
+ assert_false(document.getElementById('clubnum2').willValidate, "fieldset is disabled so is input 'clubnum2'");
+ assert_false(document.getElementById('club2').willValidate, "the first legend is not a child of the disbled fieldset: input 'club2' is disabled");
+ }, "The first 'legend' element is not a child of the disabled fieldset: Its descendants should be disabled.");
+
+ test(function () {
+ assert_true(document.getElementById('fs3').disabled, "The fieldset is disabled");
+ assert_false(document.getElementById('clubname3').willValidate, "fieldset is disabled so is input 'clubname3'");
+ assert_false(document.getElementById('clubnum3').willValidate, "fieldset is disabled so is input 'clubnum3'");
+ assert_false(document.getElementById('club3').willValidate, "the first legend is not a child of the disbled fieldset: input 'club3' is disabled");
+ }, "The <legend> element is not a child of the disabled fieldset: Its descendants should be disabled.");
+
+ test(function () {
+ assert_true(document.getElementById('fs4').disabled, "The fieldset is disabled");
+ assert_false(document.getElementById('clubname4').willValidate, "fieldset is disabled so is input 'clubname4'");
+ assert_false(document.getElementById('clubnum4').willValidate, "fieldset is disabled so is input 'clubnum4'");
+ assert_true(document.getElementById('club4').willValidate, "the first legend a child of the disbled fieldset: input 'club4' is disabled");
+ }, "The <legend> element is child of the disabled fieldset: Its descendants should be disabled.");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-002.xhtml b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-002.xhtml
new file mode 100644
index 000000000..896d737df
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-002.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>File input descendants of disabled fieldsets</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-fieldset-disabled" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <form>
+ <fieldset id="fs" disabled="disabled">
+ <input id="myfile" type="file" />
+ </fieldset>
+ </form>
+ <script>
+ test(function () {
+ assert_true(document.getElementById('fs').disabled, "disabled fieldset should be disabled");
+ assert_false(document.getElementById('myfile').willValidate, "form control descendant of disabled fieldset that is not also a descendant of a legend should be disabled");
+ }, "A file input without a disabled attribute that is a descendant of a disabled fieldset should be disabled (modulo legend-related complications that don't apply here)");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-form-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-autocomplete.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-autocomplete.html
new file mode 100644
index 000000000..c50ea7317
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-autocomplete.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>form autocomplete attribute</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-form-element">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#attr-fe-autocomplete">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form name="missing_attribute">
+ <input>
+ <input autocomplete="on">
+ <input autocomplete="off">
+ <input autocomplete="foobar">
+</form>
+<form name="autocomplete_on" autocomplete="on">
+ <input>
+ <input autocomplete="on">
+ <input autocomplete="off">
+ <input autocomplete="foobar">
+</form>
+<form name="autocomplete_off" autocomplete="off">
+ <input>
+ <input autocomplete="on">
+ <input autocomplete="off">
+ <input autocomplete="foobar">
+</form>
+<form name="autocomplete_invalid" autocomplete="foobar">
+ <input>
+ <input autocomplete="on">
+ <input autocomplete="off">
+ <input autocomplete="foobar">
+</form>
+<script>
+ function autocompletetest(form, expectedValues, desc) {
+ test(function(){
+ assert_equals(form.autocomplete, expectedValues[0]);
+ assert_equals(form.elements[0].autocomplete, expectedValues[1]);
+ assert_equals(form.elements[1].autocomplete, expectedValues[2]);
+ assert_equals(form.elements[2].autocomplete, expectedValues[3]);
+ assert_equals(form.elements[3].autocomplete, expectedValues[4]);
+ }, desc);
+ }
+
+ autocompletetest(document.forms.missing_attribute, ["on", "on", "on", "off", ""], "form autocomplete attribute missing");
+ autocompletetest(document.forms.autocomplete_on, ["on", "on", "on", "off", ""], "form autocomplete attribute on");
+ autocompletetest(document.forms.autocomplete_off, ["off", "off", "on", "off", ""], "form autocomplete attribute off");
+ autocompletetest(document.forms.autocomplete_invalid, ["on", "on", "on", "off", ""], "form autocomplete attribute invalid");
+
+ var keywords = [ "name", "honorific-prefix", "given-name", "additional-name", "family-name", "honorific-suffix", "nickname", "username", "new-password", "current-password", "organization-title", "organization", "street-address", "address-line1", "address-line2", "address-line3", "address-level4", "address-level3", "address-level2", "address-level1", "country", "country-name", "postal-code", "cc-name", "cc-given-name", "cc-additional-name", "cc-family-name", "cc-number", "cc-exp", "cc-exp-month", "cc-exp-year", "cc-csc", "cc-type", "transaction-currency", "transaction-amount", "language", "bday", "bday-day", "bday-month", "bday-year", "sex", "url", "photo", "tel", "tel-country-code", "tel-national", "tel-area-code", "tel-local", "tel-local-prefix", "tel-local-suffix", "tel-extension", "email", "impp" ];
+
+ keywords.forEach(function(keyword) {
+ test(function(){
+ var input = document.createElement("input");
+ input.setAttribute("autocomplete", keyword);
+ assert_equals(input.autocomplete, keyword);
+ }, keyword + " is an allowed autocomplete field name");
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-interfaces-01.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-interfaces-01.html
new file mode 100644
index 000000000..c8b4a6c71
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-interfaces-01.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>form.elements: interfaces</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#htmlformcontrolscollection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var form = document.createElement("form");
+ ["HTMLFormControlsCollection", "HTMLCollection"].forEach(function(i) {
+ test(function() {
+ assert_true(i in window, "Interface should exist")
+ assert_true(form.elements instanceof window[i],
+ "elements should implement the interface")
+ }, "Testing interface " + i)
+ })
+})
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-matches.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-matches.html
new file mode 100644
index 000000000..792162726
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-matches.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>form.elements: matches</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<form id="form">
+<input type="image">
+</form>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementById("form").elements.length, 0);
+}, "input type=image should not be present in the form.elements collection")
+test(function() {
+ var form = document.getElementById("form");
+ var i = document.createElement("input");
+ i.name = "2";
+ form.appendChild(i);
+ var j = document.createElement("input");
+ j.name = "03";
+ form.appendChild(j);
+ assert_equals(form.elements[-1], undefined, '[-1]');
+ assert_equals(form.elements["-1"], undefined, '["-1"]');
+ assert_equals(form.elements[0], i, '[0]');
+ assert_equals(form.elements["0"], i, '["0"]');
+ assert_equals(form.elements[1], j, '[1]');
+ assert_equals(form.elements["1"], j, '["1"]');
+ assert_equals(form.elements[2], undefined, '[2]');
+ assert_equals(form.elements["2"], undefined, '["2"]');
+ assert_equals(form.elements[03], undefined, '[03]');
+ assert_equals(form.elements["03"], j, '["03"]');
+ assert_equals(form.elements.item(-1), null, 'item(-1)');
+ assert_equals(form.elements.item(0), i, 'item(0)');
+ assert_equals(form.elements.item(1), j, 'item(1)');
+ assert_equals(form.elements.item(2), null, 'item(2)');
+ assert_equals(form.elements.namedItem("2"), i, 'namedItem("2")');
+ assert_equals(form.elements.namedItem("03"), j, 'namedItem("03")');
+ assert_equals(form.elements.namedItem("3"), null, 'namedItem("3")');
+ assert_array_equals(form.elements, [i, j]);
+ form.removeChild(i);
+ form.removeChild(j);
+}, "form.elements should include elements whose name starts with a number");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-nameditem-01.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-nameditem-01.html
new file mode 100644
index 000000000..0b5aeb8ef
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-nameditem-01.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>form.elements: namedItem</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<form id=form>
+<input name=b id=i1>
+<input name=b id=i2>
+</form>
+</div>
+<script>
+test(function() {
+ assert_true("RadioNodeList" in window, "RadioNodeList should exist");
+}, "RadioNodeList should exist")
+test(function() {
+ var nl = document.forms.form.elements["b"];
+ assert_true(nl instanceof NodeList, "Should get a NodeList");
+ if ("RadioNodeList" in window) {
+ assert_true(nl instanceof RadioNodeList, "Should get a RadioNodeList");
+ }
+ assert_array_equals(nl,
+ [document.getElementById("i1"),
+ document.getElementById("i2")]);
+
+ var el = nl[0];
+ el.parentNode.removeChild(el);
+ assert_true(nl instanceof NodeList, "Should get a NodeList");
+ if ("RadioNodeList" in window) {
+ assert_true(nl instanceof RadioNodeList, "Should get a RadioNodeList");
+ }
+ assert_array_equals(nl, [document.getElementById("i2")]);
+ assert_equals(document.forms.form.elements["b"], document.getElementById("i2"));
+}, "elements collection should return elements or RadioNodeLists")
+test(function() {
+ var fs = document.forms.form.appendChild(document.createElement("fieldset"));
+ fs.name = "fs";
+ assert_equals(document.forms.form.elements.fs, fs);
+ fs.parentNode.removeChild(fs);
+}, "elements collection should include fieldsets")
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-nameditem-02.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-nameditem-02.html
new file mode 100644
index 000000000..c25e554de
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-nameditem-02.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>form.elements: parsing</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#parsing-main-intr">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<form id=form>
+<table>
+<tr>
+<td><input type="radio" name="radio1" id="r1" value=1></td>
+<td><input type="radio" name="radio2" id="r2" value=2></td>
+<input type="radio" name="radio0" id="r0" value=0>
+</tr>
+</table>
+</form>
+</div>
+<script>
+test(function() {
+ var form = document.getElementById("form");
+ assert_array_equals(form.elements,
+ [document.getElementById("r0"),
+ document.getElementById("r1"),
+ document.getElementById("r2")]);
+}, "form.elements should work correctly in the face of table syntax errors")
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-sameobject.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-sameobject.html
new file mode 100644
index 000000000..d1ebac07f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-elements-sameobject.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Testing [SameObject] on the 'elements' attribute on the 'form' element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+
+<form>
+ <input>
+</form>
+
+<script>
+test(function() {
+ var form = document.querySelector('form');
+ var elements = form.elements;
+ assert_true(elements === form.elements);
+ form.appendChild(document.createElement('input'));
+ assert_true(elements === form.elements);
+}, "[SameObject] should apply to 'elements' attr on <form>");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-indexed-element.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-indexed-element.html
new file mode 100644
index 000000000..66f00e761
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-indexed-element.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>form.elements: indexed</title>
+<link rel="author" title="Ivan.Yang" href="mailto:jsyangwenjie@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<form id=form>
+<input type="radio" name="radio1" id="r1" value=1>
+<input type="radio" name="radio2" id="r2" value=2>
+</form>
+</div>
+<script>
+test(function() {
+ var form = document.getElementById("form");
+ assert_equals(form[0], document.getElementById("r1"));
+ assert_equals(form[1], document.getElementById("r2"));
+ assert_equals(form[2], undefined);
+ assert_equals(form[-1], undefined);
+}, "form.elements should be accessed correctly by index")
+
+test(function(){
+ var form = document.getElementById("form");
+ var old_item = form[0];
+ var old_desc = Object.getOwnPropertyDescriptor(form, 0);
+ assert_equals(old_desc.value, old_item);
+ assert_true(old_desc.enumerable);
+ assert_true(old_desc.configurable);
+ assert_false(old_desc.writable);
+
+ Object.prototype[0] = 5;
+ this.add_cleanup(function () { delete Object.prototype[0]; });
+ assert_equals(form[0], old_item);
+
+ delete form[0];
+ assert_equals(form[0], old_item);
+
+ assert_throws(new TypeError(), function() {
+ "use strict";
+ delete form[0];
+ });
+ assert_equals(form[0], old_item);
+}, 'Trying to delete an indexed property name should never work');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-form-element/form-nameditem.html b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-nameditem.html
new file mode 100644
index 000000000..3edf903b7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-form-element/form-nameditem.html
@@ -0,0 +1,330 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Form named getter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<!-- XXX Nothing tests id attributes yet. -->
+<!-- XXX Keygen. -->
+<!-- XXX We also need tests for moving inputs and forms in the DOM. -->
+<form>
+<input type=button name=button>
+<input type=radio name=radio value=x>
+<input type=radio name=radio value=y>
+<input type=radio name=radio value=z>
+</form>
+
+<form>
+<button name=l1></button>
+<fieldset name=l2></fieldset>
+<input type=hidden name=l3>
+<input type=text name=l4>
+<input type=search name=l5>
+<input type=tel name=l6>
+<input type=url name=l7>
+<input type=email name=l8>
+<input type=password name=l9>
+<input type=datetime name=l10>
+<input type=date name=l11>
+<input type=month name=l12>
+<input type=week name=l13>
+<input type=time name=l14>
+<input type=datetime-local name=l15>
+<input type=number name=l16>
+<input type=range name=l17>
+<input type=color name=l18>
+<input type=checkbox name=l19>
+<input type=radio name=l20>
+<input type=file name=l21>
+<input type=submit name=l22>
+<input type=image name=l23>
+<input type=reset name=l24>
+<input type=button name=l25>
+<input type=foo name=l26>
+<input name=l27>
+<object name=l28></object>
+<output name=l29></output>
+<select name=l30></select>
+<textarea name=l31></textarea>
+</form>
+
+<form>
+<!-- EventTarget -->
+<input type=radio name=addEventListener>
+<input type=radio name=removeEventListener>
+<input type=radio name=dispatchEvent>
+
+<!-- Node -->
+<input type=radio name=nodeType>
+<input type=radio name=nodeName>
+<input type=radio name=ownerDocument>
+
+<!-- Element -->
+<input type=radio name=namespaceURI>
+<input type=radio name=prefix>
+<input type=radio name=localName>
+
+<!-- HTMLElement -->
+<input type=radio name=title>
+<input type=radio name=lang>
+<input type=radio name=dir>
+
+<!-- HTMLFormElement -->
+<input type=radio name=acceptCharset>
+<input type=radio name=action>
+<input type=radio name=autocomplete>
+<input type=radio name=enctype>
+<input type=radio name=encoding>
+<input type=radio name=method>
+<input type=radio name=name>
+<input type=radio name=noValidate>
+<input type=radio name=target>
+<input type=radio name=elements>
+<input type=radio name=length>
+<input type=radio name=submit>
+<input type=radio name=reset>
+<input type=radio name=checkValidity>
+</form>
+
+<img name=x>
+<form></form><!-- no child nodes -->
+<img name=y>
+<form><!-- a child node --></form>
+<img name=z>
+
+<input form=a name=b>
+<form id=a></form>
+<input form=c name=d>
+<input form=c name=d>
+<form id=c></form>
+<script>
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ assert_equals(form.item, undefined)
+ assert_false("item" in form)
+}, "Forms should not have an item method")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ assert_equals(form.namedItem, undefined)
+ assert_false("namedItem" in form)
+}, "Forms should not have a namedItem method")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ var button = document.getElementsByTagName("input")[0]
+ assert_equals(button.type, "button")
+ assert_equals(form.button, button)
+ var desc = Object.getOwnPropertyDescriptor(form, "button");
+ assert_equals(desc.value, button);
+ assert_false(desc.writable);
+ assert_true(desc.configurable);
+ assert_false(desc.enumerable);
+ assert_equals(form.button.length, undefined)
+}, "Name for a single element should work")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ assert_equals(form.radio.item(-1), null)
+ assert_array_equals([0, 1, 2].map(function(i) {
+ return form.radio.item(i).value
+ }), ["x", "y", "z"])
+ assert_equals(form.radio.item(3), null)
+}, "Calling item() on the NodeList returned from the named getter should work")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ assert_equals(form.radio.length, 3)
+ assert_equals(form.radio[-1], undefined)
+ assert_array_equals([0, 1, 2].map(function(i) {
+ return form.radio[i].value
+ }), ["x", "y", "z"])
+ assert_equals(form.radio[3], undefined)
+}, "Indexed getter on the NodeList returned from the named getter should work")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ var indices = [-1, 0, 1, 2, 3]
+ indices.forEach(function(i) {
+ assert_throws(new TypeError(), function() {
+ form.radio(i)
+ })
+ })
+}, "Invoking a legacycaller on the NodeList returned from the named getter " +
+ "should not work")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[1]
+ for (var i = 1; i <= 31; ++i) {
+ if (i == 23) {
+ // input type=image
+ assert_equals(form["l" + i], undefined)
+ } else {
+ assert_equals(form["l" + i], form.children[i - 1])
+ }
+ }
+}, "All listed elements except input type=image should be present in the form")
+
+test(function() {
+ var names = [
+ // EventTarget
+ "addEventListener", "removeEventListener", "dispatchEvent",
+ // Node
+ "nodeType", "nodeName", "ownerDocument",
+ // Element
+ "namespaceURI", "prefix", "localName",
+ // HTMLElement
+ "title", "lang", "dir",
+ // HTMLFormElement
+ "acceptCharset", "action", "autocomplete", "enctype", "encoding", "method",
+ "name", "noValidate", "target", "elements", "length", "submit", "reset",
+ "checkValidity"
+ ]
+ var form = document.getElementsByTagName("form")[2]
+ names.forEach(function(name, i) {
+ assert_equals(form[name], form.children[i])
+ })
+}, "Named elements should override builtins")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[3]
+ assert_equals(form.x, undefined, "x should not be associated with the form")
+ assert_equals(form.y, undefined, "y should not be associated with the form")
+ assert_equals(form.z, undefined, "z should not be associated with the form")
+ assert_equals(form[0], undefined, "The form should not have supported property indices")
+ assert_equals(form.length, 0)
+}, "Named items outside the form should not be returned (no children)")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[4]
+ assert_equals(form.x, undefined, "x should not be associated with the form")
+ assert_equals(form.y, undefined, "y should not be associated with the form")
+ assert_equals(form.z, undefined, "z should not be associated with the form")
+ assert_equals(form[0], undefined, "The form should not have supported property indices")
+ assert_equals(form.length, 0)
+}, "Named items outside the form should not be returned (one child)")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[5]
+ assert_equals(form.id, "a")
+
+ var input = document.getElementsByName("b")[0]
+ assert_equals(input.localName, "input")
+ assert_equals(input.getAttribute("form"), "a")
+
+ assert_equals(form.b, input);
+}, "The form attribute should be taken into account for named getters (single element)")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[6]
+ assert_equals(form.id, "c")
+
+ var input1 = document.getElementsByName("d")[0]
+ assert_equals(input1.localName, "input")
+ assert_equals(input1.getAttribute("form"), "c")
+
+ var input2 = document.getElementsByName("d")[1]
+ assert_equals(input2.localName, "input")
+ assert_equals(input2.getAttribute("form"), "c")
+
+ var desc = Object.getOwnPropertyDescriptor(form, "d");
+ assert_equals(desc.value, form.d);
+ assert_false(desc.writable);
+ assert_true(desc.configurable);
+ assert_false(desc.enumerable);
+
+ assert_true(form.d instanceof NodeList, "form.d should be a NodeList")
+ assert_array_equals(form.d, [input1, input2])
+}, "The form attribute should be taken into account for named getters (multiple elements)")
+
+test(function() {
+ var f = document.body.appendChild(document.createElement("form"))
+ f.id = "f"
+ var g = f.appendChild(document.createElement("form"))
+ g.id = "g"
+ var input = g.appendChild(document.createElement("input"))
+ input.name = "x"
+ assert_equals(f.x, undefined)
+ assert_equals(g.x, input)
+}, "Input should only be a named property on the innermost form that contains it")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[1];
+ var old_item = form["l1"];
+ var old_desc = Object.getOwnPropertyDescriptor(form, "l1");
+ assert_equals(old_desc.value, old_item);
+ assert_false(old_desc.enumerable);
+ assert_true(old_desc.configurable);
+ assert_false(old_desc.writable);
+
+ form["l1"] = 5;
+ assert_equals(form["l1"], old_item);
+ assert_throws(new TypeError(), function() {
+ "use strict";
+ form["l1"] = 5;
+ });
+ assert_throws(new TypeError(), function() {
+ Object.defineProperty(form, "l1", { value: 5 });
+ });
+
+ delete form["l1"];
+ assert_equals(form["l1"], old_item);
+
+ assert_throws(new TypeError(), function() {
+ "use strict";
+ delete form["l1"];
+ });
+ assert_equals(form["l1"], old_item);
+
+}, 'Trying to set an expando that would shadow an already-existing named property');
+
+test(function() {
+ var form = document.getElementsByTagName("form")[1];
+ var old_item = form["new-name"];
+ var old_desc = Object.getOwnPropertyDescriptor(form, "new-name");
+ assert_equals(old_item, undefined);
+ assert_equals(old_desc, undefined);
+
+ form["new-name"] = 5;
+ assert_equals(form["new-name"], 5);
+
+ var input = document.createElement("input");
+ this.add_cleanup(function () {input.remove();});
+ input.name = "new-name";
+ form.appendChild(input);
+
+ assert_equals(form["new-name"], 5);
+
+ delete form["new-name"];
+ assert_equals(form["new-name"], input);
+}, 'Trying to set an expando that shadows a named property that gets added later');
+
+test(function() {
+ var form = document.getElementsByTagName("form")[1];
+ var old_item = form["new-name2"];
+ var old_desc = Object.getOwnPropertyDescriptor(form, "new-name2");
+ assert_equals(old_item, undefined);
+ assert_equals(old_desc, undefined);
+
+ Object.defineProperty(form, "new-name2", { configurable: false, writable:
+ false, value: 5 });
+ assert_equals(form["new-name2"], 5);
+
+ var input = document.createElement("input");
+ this.add_cleanup(function () {input.remove();});
+ input.name = "new-name2";
+ form.appendChild(input);
+
+ assert_equals(form["new-name2"], 5);
+
+ delete form["new-name2"];
+ assert_equals(form["new-name2"], 5);
+
+ assert_throws(new TypeError(), function() {
+ "use strict";
+ delete form["new-name2"];
+ });
+ assert_equals(form["new-name2"], 5);
+}, 'Trying to set a non-configurable expando that shadows a named property that gets added later');
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-input-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/button.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/button.html
new file mode 100644
index 000000000..3c826a975
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/button.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type button</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#button-state-(type=button)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id=f1>
+ <input type=button id=b1 name=b1>
+</form>
+<form>
+ <input id=i1 value="foo">
+ <input type=button id=b2 name=b2>
+</form>
+<form>
+ <input type=radio id=i2 checked name=b3>
+ <input type=button id=b3 name=b3>
+</form>
+<form>
+ <input type=checkbox id=i3>
+ <input type=button id=b4 name=b4>
+</form>
+
+<script>
+ var t = async_test("clicking on button should not submit a form"),
+ b1 = document.getElementById('b1'),
+ b2 = document.getElementById('b2'),
+ b3 = document.getElementById('b3'),
+ b4 = document.getElementById('b4'),
+ i1 = document.getElementById('i1'),
+ i2 = document.getElementById('i2'),
+ i3 = document.getElementById('i3');
+
+ test(function(){
+ assert_false(b1.willValidate);
+ }, "the element is barred from constraint validation");
+
+ document.getElementById('f1').onsubmit = t.step_func(function(e) {
+ e.preventDefault();
+ assert_unreached("form has been submitted");
+ });
+
+ t.step(function() {
+ b1.click();
+ });
+ t.done();
+
+ test(function(){
+ i1.value = "bar";
+ b2.click();
+ assert_equals(i1.value, "bar");
+ }, "clicking on button should not reset other form fields");
+
+ test(function(){
+ assert_true(i2.checked);
+ b3.click();
+ assert_true(i2.checked);
+ }, "clicking on button should not unchecked radio buttons");
+
+ test(function(){
+ assert_false(i3.indeterminate);
+ b4.click();
+ assert_false(i3.indeterminate);
+ }, "clicking on button should not change its indeterminate IDL attribute");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/checkbox.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/checkbox.html
new file mode 100644
index 000000000..b1ccc64c1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/checkbox.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type checkbox</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox)">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input type=checkbox id=checkbox1>
+<input type=checkbox id=checkbox2 disabled>
+<input type=checkbox id=checkbox3>
+<input type=checkbox id=checkbox4 checked>
+<input type=checkbox id=checkbox5>
+<input type=checkbox id=checkbox6>
+<script>
+ var checkbox1 = document.getElementById('checkbox1'),
+ checkbox2 = document.getElementById('checkbox2'),
+ checkbox3 = document.getElementById('checkbox3'),
+ checkbox4 = document.getElementById('checkbox4'),
+ checkbox5 = document.getElementById('checkbox5'),
+ checkbox6 = document.getElementById('checkbox6'),
+ c1_click_fired = false,
+ c1_input_fired = false,
+ c1_change_fired = false,
+ t1 = async_test("click on mutable checkbox fires a click event, then an input event, then a change event"),
+ t2 = async_test("click on non-mutable checkbox doesn't fire the input or change event"),
+ t3 = async_test("pre-activation steps on unchecked checkbox"),
+ t4 = async_test("pre-activation steps on checked checkbox"),
+ t5 = async_test("canceled activation steps on unchecked checkbox"),
+ t6 = async_test("canceled activation steps on unchecked checkbox (indeterminate=true in onclick)");
+
+ checkbox1.onclick = t1.step_func(function(e) {
+ c1_click_fired = true;
+ assert_false(c1_input_fired, "click event should fire before input event");
+ assert_false(c1_change_fired, "click event should fire before change event");
+ assert_false(e.isTrusted, "click()-initiated click event should not be trusted");
+ });
+ checkbox1.oninput = t1.step_func(function(e) {
+ c1_input_fired = true;
+ assert_true(c1_click_fired, "input event should fire after click event");
+ assert_false(c1_change_fired, "input event should fire before change event");
+ assert_true(e.bubbles, "event should bubble");
+ assert_true(e.isTrusted, "click()-initiated event should be trusted");
+ assert_false(e.cancelable, "event should not be cancelable");
+ assert_true(checkbox1.checked, "checkbox is checked");
+ assert_false(checkbox1.indeterminate, "checkbox is not indeterminate");
+ });
+
+ checkbox1.onchange = t1.step_func(function(e) {
+ c1_change_fired = true;
+ assert_true(c1_click_fired, "change event should fire after click event");
+ assert_true(c1_input_fired, "change event should fire after input event");
+ assert_true(e.bubbles, "event should bubble")
+ assert_true(e.isTrusted, "click()-initiated event should be trusted");
+ assert_false(e.cancelable, "event should not be cancelable");
+ assert_true(checkbox1.checked, "checkbox is checked");
+ assert_false(checkbox1.indeterminate, "checkbox is not indeterminate");
+ });
+
+ checkbox2.oninput= t2.step_func(function(e) {
+ assert_unreached("event input fired");
+ });
+
+ checkbox2.onchange = t2.step_func(function(e) {
+ assert_unreached("event change fired");
+ });
+
+ t1.step(function() {
+ checkbox1.click();
+ assert_true(c1_input_fired);
+ assert_true(c1_change_fired);
+ t1.done();
+ });
+
+ t2.step(function() {
+ checkbox2.click();
+ t2.done();
+ });
+
+ t3.step(function() {
+ checkbox3.indeterminate = true;
+ checkbox3.click();
+ assert_true(checkbox3.checked);
+ assert_false(checkbox3.indeterminate);
+ t3.done();
+ });
+
+ t4.step(function() {
+ checkbox4.indeterminate = true;
+ checkbox4.click();
+ assert_false(checkbox4.checked);
+ assert_false(checkbox4.indeterminate);
+ t4.done();
+ });
+
+ checkbox5.onclick = t5.step_func(function(e) {
+ e.preventDefault();
+ /*
+ The prevention of the click doesn't have an effect until after all the
+ click event handlers have been run.
+ */
+ assert_true(checkbox5.checked);
+ assert_false(checkbox5.indeterminate);
+ window.setTimeout(t5.step_func(function(e) {
+ /*
+ The click event has finished being dispatched, so the checkedness and
+ determinateness have been toggled back by now because the event
+ was preventDefault-ed.
+ */
+ assert_false(checkbox5.checked);
+ assert_false(checkbox5.indeterminate);
+ t5.done();
+ }), 0);
+ });
+
+ t5.step(function(){
+ assert_false(checkbox5.checked);
+ assert_false(checkbox5.indeterminate);
+ checkbox5.click();
+ });
+
+ checkbox6.onclick = t6.step_func(function(e) {
+ checkbox6.indeterminate = true;
+ e.preventDefault();
+ /*
+ The prevention of the click doesn't have an effect until after all the
+ click event handlers have been run.
+ */
+ assert_true(checkbox6.checked);
+ assert_true(checkbox6.indeterminate);
+ window.setTimeout(t6.step_func(function(e) {
+ /*
+ The click event has finished being dispatched, so the checkedness and
+ determinateness have been toggled back by now because the event
+ was preventDefault-ed.
+ */
+ assert_false(checkbox6.checked);
+ assert_false(checkbox6.indeterminate);
+ t6.done();
+ }), 0);
+ });
+
+ t6.step(function(){
+ assert_false(checkbox6.checked);
+ assert_false(checkbox6.indeterminate);
+ checkbox6.click();
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/checked.xhtml b/testing/web-platform/tests/html/semantics/forms/the-input-element/checked.xhtml
new file mode 100644
index 000000000..70aeb5109
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/checked.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>input@checked is immediately reflected to 'checked' IDL attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<input style="display: none" type="checkbox" checked="">
+<script>
+test(function(){
+assert_true(document.querySelector('input').checked, 'Examining "checked" IDL attribute value:')
+});
+</script>
+</input>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/clone.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/clone.html
new file mode 100644
index 000000000..0f7e053ba
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/clone.html
@@ -0,0 +1,150 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test input value retention upon clone</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<style>form {display: none;} </style>
+<form>
+<p><input type=checkbox> This checkbox is initially unchecked.</p>
+<p><input type=checkbox checked="checked"> This checkbox is initially checked.</p>
+<p><input type=radio name=radio> This radiobutton is initially unchecked.</p>
+<p><input type=radio checked="checked" name=radio> This radiobutton is initially checked.</p>
+<p><input type=hidden value="DEFAULT
+DEFAULT"> This hidden field has the initial value "DEFAULT\nDEFAULT".</p>
+<p><input type=text value=DEFAULT> This text field has the initial value "DEFAULT".</p>
+<p><input type=search value=DEFAULT> This search field has the initial value "DEFAULT".</p>
+<p><input type=tel value=DEFAULT> This phone number field has the initial value "DEFAULT".</p>
+<p><input type=url value=https://default.invalid/> This URL field has the initial value "https://default.invalid/".</p>
+<p><input type=email value=default@default.invalid> This email field has the initial value "default@default.invalid".</p>
+<p><input type=password value=DEFAULT> This password field has the initial value "DEFAULT".</p>
+<p><input type=date value=2015-01-01> This date field has the initial value "2015-01-01".</p>
+<p><input type=month value=2015-01> This month field has the initial value "2015-01".</p>
+<p><input type=week value=2015-W01> This week field has the initial value "2015-W01".</p>
+<p><input type=time value=12:00> This time field has the initial value "12:00".</p>
+<p><input type=datetime-local value=2015-01-01T12:00> This datetime (local) field has the initial value "2015-01-01T12:00".</p>
+<p><input type=number value=1> This number field has the initial value "1".</p>
+<p><input type=range value=1> This range control has the initial value "1".</p>
+<p><input type=color value=#ff0000> This color picker has the initial value "#FF0000".</p>
+<p><input type="button" value="Clone" onclick="clone();"></p>
+</form>
+<script>
+setup(function() {
+ let form = document.getElementsByTagName("form")[0];
+ let inputs = form.getElementsByTagName("input");
+ inputs[0].checked = true;
+ inputs[1].checked = false;
+ inputs[2].checked = true;
+ inputs[4].value = "CHANGED\nCHANGED";
+ inputs[5].value = "CHANGED";
+ inputs[6].value = "CHANGED";
+ inputs[7].value = "CHANGED";
+ inputs[8].value = "https://changed.invalid/";
+ inputs[9].value = "changed@changed.invalid";
+ inputs[10].value = "CHANGED";
+ inputs[11].value = "2016-01-01";
+ inputs[12].value = "2016-01";
+ inputs[13].value = "2016-W01";
+ inputs[14].value = "12:30";
+ inputs[15].value = "2016-01-01T12:30";
+ inputs[16].value = "2";
+ inputs[17].value = "2";
+ inputs[18].value = "#00ff00";
+ let clone = form.cloneNode(true);
+ document.body.appendChild(clone);
+});
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_true(inputs[0].checked, "Should have retained checked state");
+}, "Checkbox must retain checked state.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_false(inputs[1].checked, "Should have retained unchecked state");
+}, "Checkbox must retain unchecked state.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_true(inputs[2].checked, "Should have retained checked state");
+}, "Radiobutton must retain checked state.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_false(inputs[3].checked, "Should have retained unchecked state");
+}, "Radiobutton must retain unchecked state.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[4].value, "CHANGED\nCHANGED", "Should have retained the changed value.");
+}, "Hidden field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[5].value, "CHANGED", "Should have retained the changed value.");
+}, "Text field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[6].value, "CHANGED", "Should have retained the changed value.");
+}, "Search field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[7].value, "CHANGED", "Should have retained the changed value.");
+}, "Phone number field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[8].value, "https://changed.invalid/", "Should have retained the changed value.");
+}, "URL field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[9].value, "changed@changed.invalid", "Should have retained the changed value.");
+}, "Email field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[10].value, "CHANGED", "Should have retained the changed value.");
+}, "Password field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[11].value, "2016-01-01", "Should have retained the changed value.");
+}, "Date field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[12].value, "2016-01", "Should have retained the changed value.");
+}, "Month field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[13].value, "2016-W01", "Should have retained the changed value.");
+}, "Week field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[14].value, "12:30", "Should have retained the changed value.");
+}, "Time field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[15].value, "2016-01-01T12:30", "Should have retained the changed value.");
+}, "Datetime (local) field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[16].value, "2", "Should have retained the changed value.");
+}, "Number field must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[17].value, "2", "Should have retained the changed value.");
+}, "Range control must retain changed value.");
+test(function() {
+ let clone = document.getElementsByTagName("form")[1];
+ let inputs = clone.getElementsByTagName("input");
+ assert_equals(inputs[18].value, "#00ff00", "Should have retained the changed value.");
+}, "Color picker must retain changed value.");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/cloning-steps.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/cloning-steps.html
new file mode 100644
index 000000000..9e6c46fd7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/cloning-steps.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Cloning of input elements</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-node-clonenode">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-node-clone">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-node-clone-ext">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#the-input-element:concept-node-clone-ext">
+<link rel="author" title="Matthew Phillips" href="mailto:matthew@matthewphillips.info">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+"use strict";
+
+test(function() {
+ var input = document.createElement("input");
+ input.value = "foo bar";
+
+ var copy = input.cloneNode();
+ assert_equals(copy.value, "foo bar");
+}, "input element's value should be cloned");
+
+test(function() {
+ var input = document.createElement("input");
+ input.value = "foo bar";
+
+ var copy = input.cloneNode();
+ copy.setAttribute("value", "something else");
+
+ assert_equals(copy.value, "foo bar");
+}, "input element's dirty value flag should be cloned, so setAttribute doesn't affect the cloned input's value");
+
+test(function() {
+ var input = document.createElement("input");
+ input.setAttribute("type", "radio");
+ input.checked = true;
+
+ var copy = input.cloneNode();
+ assert_equals(copy.checked, true);
+}, "input element's checkedness should be cloned");
+
+test(function() {
+ var input = document.createElement("input");
+ input.setAttribute("type", "radio");
+ input.checked = false;
+
+ var copy = input.cloneNode();
+ copy.setAttribute("checked", "checked");
+
+ assert_equals(copy.checked, false);
+}, "input element's dirty checkedness should be cloned, so setAttribute doesn't affect the cloned input's checkedness");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/color.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/color.html
new file mode 100644
index 000000000..6164815f6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/color.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=color</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/common-microsyntaxes.html#colors">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/states-of-the-type-attribute.html#color-state-(type=color)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var colors = [
+ {value: "", expected: "#000000", testname: "Empty value should return #000000"},
+ {expected: "#000000", testname: "Missing value should return #000000"},
+ {value: "#ffffff", expected: "#ffffff", testname: "Valid simple color: should return #ffffff"},
+ {value: "#FFFFFF", expected: "#ffffff", testname: "Valid simple color (containing LATIN CAPITAL LETTERS): should return #ffffff (converted to ASCII lowercase)"},
+ {value: "#0F0F0F", expected: "#0f0f0f", testname: "Zero-padding"},
+ {value: "#fff", expected: "#000000", testname: "Invalid simple color: not 7 characters long"},
+ {value: "fffffff", expected: "#000000", testname: "Invalid simple color: no starting # sign"},
+ {value: "#gggggg", expected: "#000000", testname: "Invalid simple color: non ASCII hex digits"},
+ {value: "foobar", expected: "#000000", testname: "Invalid simple color: foobar"},
+ {value: "#ffffff\u0000", expected: "#000000", testname: "Invalid color: trailing Null (U+0000)"},
+ {value: "#ffffff;", expected: "#000000", testname: "Invalid color: trailing ;"},
+ {value: " #ffffff", expected: "#000000", testname: "Invalid color: leading space"},
+ {value: "#ffffff ", expected: "#000000", testname: "Invalid color: trailing space"},
+ {value: " #ffffff ", expected: "#000000", testname: "Invalid color: leading+trailing spaces"},
+ {value: "crimson", expected: "#000000", testname: "Invalid color: keyword crimson"},
+ {value: "bisque", expected: "#000000", testname: "Invalid color: keyword bisque"},
+ {value: "currentColor", expected: "#000000", testname: "Invalid color: keyword currentColor"},
+ {value: "transparent", expected: "#000000", testname: "Invalid color: keyword transparent"},
+ {value: "ActiveBorder", expected: "#000000", testname: "Invalid color: keyword ActiveBorder"},
+ {value: "inherit", expected: "#000000", testname: "Invalid color: keyword inherit"},
+ {value: "rgb(1,1,1)", expected: "#000000", testname: "Invalid color: rgb(1,1,1)"},
+ {value: "rgb(1,1,1,1)", expected: "#000000", testname: "Invalid color: rgb(1,1,1,1)"},
+ {value: "#FFFFF\u1F4A9", expected: "#000000", testname: "Invalid color: PILE OF POO (U+1F4A9)"}
+ ];
+ for (var i = 0; i < colors.length; i++) {
+ var w = colors[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "color";
+ input.value = w.value;
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/contains.json b/testing/web-platform/tests/html/semantics/forms/the-input-element/contains.json
new file mode 100644
index 000000000..c2b780f0b
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/contains.json
@@ -0,0 +1,154 @@
+[
+ {
+ "id": "states-of-the-type-attribute",
+ "original_id": "states-of-the-type-attribute",
+ "children": [
+ {
+ "id": "hidden-state-type-hidden",
+ "original_id": "hidden-state-(type=hidden)"
+ },
+ {
+ "id": "text-type-text-state-and-search-state-type-search",
+ "original_id": "text-(type=text)-state-and-search-state-(type=search)"
+ },
+ {
+ "id": "telephone-state-type-tel",
+ "original_id": "telephone-state-(type=tel)"
+ },
+ {
+ "id": "url-state-type-url",
+ "original_id": "url-state-(type=url)"
+ },
+ {
+ "id": "e-mail-state-type-email",
+ "original_id": "e-mail-state-(type=email)"
+ },
+ {
+ "id": "password-state-type-password",
+ "original_id": "password-state-(type=password)"
+ },
+ {
+ "id": "date-and-time-state-type-datetime",
+ "original_id": "date-and-time-state-(type=datetime)"
+ },
+ {
+ "id": "date-state-type-date",
+ "original_id": "date-state-(type=date)"
+ },
+ {
+ "id": "month-state-type-month",
+ "original_id": "month-state-(type=month)"
+ },
+ {
+ "id": "week-state-type-week",
+ "original_id": "week-state-(type=week)"
+ },
+ {
+ "id": "time-state-type-time",
+ "original_id": "time-state-(type=time)"
+ },
+ {
+ "id": "local-date-and-time-state-type-datetime-local",
+ "original_id": "local-date-and-time-state-(type=datetime-local)"
+ },
+ {
+ "id": "number-state-type-number",
+ "original_id": "number-state-(type=number)"
+ },
+ {
+ "id": "range-state-type-range",
+ "original_id": "range-state-(type=range)"
+ },
+ {
+ "id": "color-state-type-color",
+ "original_id": "color-state-(type=color)"
+ },
+ {
+ "id": "checkbox-state-type-checkbox",
+ "original_id": "checkbox-state-(type=checkbox)"
+ },
+ {
+ "id": "radio-button-state-type-radio",
+ "original_id": "radio-button-state-(type=radio)"
+ },
+ {
+ "id": "file-upload-state-type-file",
+ "original_id": "file-upload-state-(type=file)"
+ },
+ {
+ "id": "submit-button-state-type-submit",
+ "original_id": "submit-button-state-(type=submit)"
+ },
+ {
+ "id": "image-button-state-type-image",
+ "original_id": "image-button-state-(type=image)"
+ },
+ {
+ "id": "reset-button-state-type-reset",
+ "original_id": "reset-button-state-(type=reset)"
+ },
+ {
+ "id": "button-state-type-button",
+ "original_id": "button-state-(type=button)"
+ }
+ ]
+ },
+ {
+ "id": "input-impl-notes",
+ "original_id": "input-impl-notes"
+ },
+ {
+ "id": "common-input-element-attributes",
+ "original_id": "common-input-element-attributes",
+ "children": [
+ {
+ "id": "the-maxlength-attribute",
+ "original_id": "the-maxlength-attribute"
+ },
+ {
+ "id": "the-size-attribute",
+ "original_id": "the-size-attribute"
+ },
+ {
+ "id": "the-readonly-attribute",
+ "original_id": "the-readonly-attribute"
+ },
+ {
+ "id": "the-required-attribute",
+ "original_id": "the-required-attribute"
+ },
+ {
+ "id": "the-multiple-attribute",
+ "original_id": "the-multiple-attribute"
+ },
+ {
+ "id": "the-pattern-attribute",
+ "original_id": "the-pattern-attribute"
+ },
+ {
+ "id": "the-min-and-max-attributes",
+ "original_id": "the-min-and-max-attributes"
+ },
+ {
+ "id": "the-step-attribute",
+ "original_id": "the-step-attribute"
+ },
+ {
+ "id": "the-list-attribute",
+ "original_id": "the-list-attribute"
+ },
+ {
+ "id": "the-placeholder-attribute",
+ "original_id": "the-placeholder-attribute"
+ }
+ ]
+ },
+ {
+ "id": "common-input-element-apis",
+ "original_id": "common-input-element-apis"
+ },
+ {
+ "id": "common-event-behaviors",
+ "original_id": "common-event-behaviors"
+ }
+] \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/date.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/date.html
new file mode 100644
index 000000000..70885ed05
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/date.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Inputs Date</title>
+ <link rel="author" title="Morishita Hiromitsu" href="mailto:hero@asterisk-works.jp">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#date-state-(type=date)">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dates-and-times">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Inputs Date</h1>
+ <div style="display: none">
+ <input id="valid" type="date" value="2011-11-01" min="2011-01-01" max="2011-12-31" />
+ <input id="too_small_value" type="date" value="1999-01-31" min="2011-01-01" max="2011-12-31"/>
+ <input id="too_large_value" type="date" value="2099-01-31" min="2011-01-01" max="2011-12-31"/>
+ <input id="invalid_min" type="date" value="2011-01-01" min="1999-1" max="2011-12-31"/>
+ <input id="invalid_max" type="date" value="2011-01-01" min="2011-01-01" max="2011-13-162-777"/>
+ <input id="min_larger_than_max" type="date" value="2011-01-01" min="2099-01" max="2011-12-31"/>
+ <input id="invalid_value" type="date" value="invalid-date" min="2011-01-01" max="2011-12-31"/>
+ </div>
+
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(function() {
+ assert_equals(document.getElementById("valid").type, "date")
+ }, "date type support on input element");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").value, "2011-11-01");
+ assert_equals(document.getElementById("too_small_value").value, "2011-01-01");
+ assert_equals(document.getElementById("too_large_value").value, "2011-12-31");
+ }, "The value attribute, if specified and not empty, must have a value that is a valid date string.");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").min, "2011-01-01"),
+ assert_equals(document.getElementById("invalid_min").min, "")
+ }, "The min attribute, if specified, must have a value that is a valid date string.");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").max, "2011-12-31"),
+ assert_equals(document.getElementById("min_larger_than_max").max, "2099-01"),
+ assert_equals(document.getElementById("invalid_max").max, "")
+ },"The max attribute, if specified, must have a value that is a valid date string.");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_value").value, "");
+ }, "User agents must not allow the user to set the value to a non-empty string that is not a valid date string.");
+ test(function() {
+ var numDays = [
+ // the number of days in month month of year year is: 31 if month is 1, 3, 5, 7, 8, 10, or 12;
+ {value: "2014-01-31", expected: "2014-01-31", testname: "January has 31 days"},
+ {value: "2014-01-32", expected: "", testname: "January has 31 days"},
+ {value: "2014-03-31", expected: "2014-03-31", testname: "March has 31 days"},
+ {value: "2014-03-32", expected: "", testname: "March has 31 days"},
+ {value: "2014-05-31", expected: "2014-05-31", testname: "May has 31 days"},
+ {value: "2014-05-32", expected: "", testname: "May has 31 days"},
+ {value: "2014-07-31", expected: "2014-07-31", testname: "July has 31 days"},
+ {value: "2014-07-32", expected: "", testname: "July has 31 days"},
+ {value: "2014-08-31", expected: "2014-08-31", testname: "August has 31 days"},
+ {value: "2014-08-32", expected: "", testname: "August has 31 days"},
+ {value: "2014-10-31", expected: "2014-10-31", testname: "October has 31 days"},
+ {value: "2014-10-32", expected: "", testname: "October has 31 days"},
+ {value: "2014-12-31", expected: "2014-12-31", testname: "December has 31 days"},
+ {value: "2014-12-32", expected: "", testname: "December has 31 days"},
+ // the number of days in month month of year year is: 30 if month is 4, 6, 9, or 11;
+ {value: "2014-04-30", expected: "2014-04-30", testname: "April has 30 days"},
+ {value: "2014-04-31", expected: "", testname: "April has 30 days"},
+ {value: "2014-06-30", expected: "2014-06-30", testname: "June has 30 days"},
+ {value: "2014-06-31", expected: "", testname: "June has 30 days"},
+ {value: "2014-09-30", expected: "2014-09-30", testname: "September has 30 days"},
+ {value: "2014-09-31", expected: "", testname: "September has 30 days"},
+ {value: "2014-11-30", expected: "2014-11-30", testname: "November has 30 days"},
+ {value: "2014-11-31", expected: "", testname: "November has 30 days"},
+ // leap years
+ {value: "2014-02-28", expected: "2014-02-28", testname: "2014 is not a leap year: February has 28 days"},
+ {value: "2014-02-29", expected: "", testname: "2014 is not a leap year: February has 28 days: value should be empty"},
+ {value: "2016-02-29", expected: "2016-02-29", testname: "2016 is a leap year: February has 29 days"}
+ ];
+ for (var i = 0; i < numDays.length; i++) {
+ var input = document.createElement("input");
+ input.type = "date";
+ input.value = numDays[i].value;
+ assert_equals(input.value, numDays[i].expected, numDays[i].testname);
+ }
+ }, "Number of days");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/datetime-local.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/datetime-local.html
new file mode 100644
index 000000000..b4548b77a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/datetime-local.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=datetime-local</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/common-microsyntaxes.html#local-dates-and-times">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/states-of-the-type-attribute.html#local-date-and-time-state-(type=datetime-local)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var datetimeLocal = [
+ {value: "", expected: "", testname: "empty value"},
+ {value: "2014-01-01T11:11:11.111", expected: "2014-01-01T11:11:11.111", testname: "datetime-local input value set to 2014-01-01T11:11:11.111 without min/max"},
+ {value: "2014-01-01 11:11:11.111", expected: "2014-01-01T11:11:11.111", testname: "datetime-local input value set to 2014-01-01 11:11:11.111 without min/max"},
+ {value: "2014-01-01 11:11", expected: "2014-01-01T11:11", testname: "datetime-local input value set to 2014-01-01 11:11 without min/max"},
+ {value: "2014-01-01 00:00:00.000", expected: "2014-01-01T00:00", testname: "datetime-local input value set to 2014-01-01 00:00:00.000 without min/max"},
+ {value: "2014-01-0 11:11", expected: "", testname: "datetime-local input value set to 2014-01-0 11:11 without min/max"},
+ {value: "2014-01-01 11:1", expected: "", testname: "datetime-local input value set to 2014-01-01 11:1 without min/max"},
+ {value: "2014-01-01 11:12", attributes: { min: "2014-01-01 11:11" }, expected: "2014-01-01T11:12", testname: "Value >= min attribute"},
+ {value: "2014-01-01 11:10", attributes: { min: "2014-01-01 11:11" }, expected: "2014-01-01T11:11", testname: "Value < min attribute"},
+ {value: "2014-01-01 11:10", attributes: { max: "2014-01-01 11:11" }, expected: "2014-01-01T11:10", testname: "Value <= max attribute"},
+ {value: "2014-01-01 11:12", attributes: { max: "2014-01-01 11:11" }, expected: "2014-01-01T11:11", testname: "Value > max attribute"}
+ ];
+ for (var i = 0; i < datetimeLocal.length; i++) {
+ var w = datetimeLocal[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "datetime-local";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/datetime.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/datetime.html
new file mode 100644
index 000000000..2e909da2d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/datetime.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Date & Time Inputs</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <h1>Date & Time Inputs</h1>
+ <div style="display: none">
+ <input type="date" value="2011-12-01" min="2011-12-01" max="2011-12-31" step="5" />
+ <input type="time" value= "12:00" min="11:30" max="14:00" step="600" />
+ <input type="datetime" value="2011-12-01T12:00Z" min="2011-12-01T12:00Z" max="2011-12-31T22:00Z" step="7200" />
+ <input type="month" value="2011-01" min="2011-01" max="2011-12" step="2" />
+ <input type="week" value="2011-W40" min="2011-W20" max="2011-W50" step="2" />
+ </div>
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].type, "date")}, "date type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].value, "2011-12-01")}, "[date] The value must be a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].min, "2011-12-01")}, "[date] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].max, "2011-12-31")}, "[date] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].step, "5")}, "[date] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[0].stepUp) == "function")}, "[date] stepUp method support on input 'date' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[0].stepDown) == "function")}, "[date] stepDown method support on input 'date' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].type, "time")}, "[time] time type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].value, "12:00")}, "[time] The value must be a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].min, "11:30")}, "[time] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].max, "14:00")}, "[time] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].step, "600")}, "[time] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[1].stepUp) == "function")}, "[time] stepUp method support on input 'time' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[1].stepDown) == "function")}, "[time] stepDown method support on input 'time' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].type, "datetime")}, "datetime type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].value, "2011-12-01T12:00Z")}, "[datetime] The must be a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].min, "2011-12-01T12:00Z")}, "[datetime] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].max, "2011-12-31T22:00Z")}, "[datetime] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].step, "7200")}, "[datetime] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[2].stepUp) == "function")}, "[datetime] stepUp method support on input 'datetime' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[2].stepDown) == "function")}, "[datetime] stepDown method support on input 'datetime' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].type, "month")}, "month type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].value, "2011-01")}, "[month] The value must be a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].min, "2011-01")}, "[month] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].max, "2011-12")}, "[month] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].step, "2")}, "[month] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[3].stepUp) == "function")}, "[month] stepUp method support on input 'month' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[3].stepDown) == "function")}, "[month] stepDown method support on input 'month' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].type, "week")}, "week type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].value, "2011-W40")}, "[week] The value must be a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].min, "2011-W20")}, "[week] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].max, "2011-W50")}, "[week] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].step, "2")}, "[week] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[4].stepUp) == "function")}, "[week] stepUp method support on input 'week' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[4].stepDown) == "function")}, "[week] stepDown method support on input 'week' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/email.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/email.html
new file mode 100644
index 000000000..fc92529ef
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/email.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>Input Email</title>
+<link rel="author" title="Kazuki Kanamori" href="mailto:yogurito@gmail.com">
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#e-mail-state-(type=email)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<input type="email" id="single_email" value="user@example.com"/>
+<input type="email" id="multiple_email" value="user1@example.com, user2@test.com" multiple/>
+<div id="log"></div>
+
+<script type="text/javascript">
+ var single = document.getElementById('single_email'),
+ mult = document.getElementById('multiple_email');
+
+ test(function(){
+ assert_false(single.multiple);
+ }, "single_email doesn't have the multiple attribute");
+
+ test(function(){
+ single.value = 'user2@example.com\u000A';
+ assert_equals(single.value, 'user2@example.com');
+ single.value = 'user3@example.com\u000D';
+ assert_equals(single.value, 'user3@example.com');
+ }, 'value should be sanitized: strip line breaks');
+
+ test(function(){
+ single.value = 'user4@example.com';
+ assert_true(single.validity.valid);
+ single.value = 'example.com';
+ assert_false(single.validity.valid);
+ }, 'Email address validity');
+
+ test(function(){
+ single.setAttribute('multiple', true);
+ single.value = ' user@example.com , user2@example.com ';
+ assert_equals(single.value, 'user@example.com,user2@example.com');
+ single.removeAttribute('multiple');
+ assert_equals(single.value, 'user@example.com,user2@example.com');
+ }, 'When the multiple attribute is removed, the user agent must run the value sanitization algorithm');
+
+ test(function(){
+ assert_true(mult.multiple);
+ }, "multiple_email has the multiple attribute");
+
+ test(function(){
+ mult.value = ' user1@example.com , user2@test.com, user3@test.com ';
+ assert_equals(mult.value, 'user1@example.com,user2@test.com,user3@test.com');
+ }, "run the value sanitization algorithm after setting a new value");
+
+ test(function(){
+ mult.value = 'user1@example.com,user2@test.com,user3@test.com';
+ assert_true(mult.validity.valid);
+
+ mult.value = 'u,ser1@example.com,user2@test.com,user3@test.com';
+ assert_false(mult.validity.valid);
+ }, "valid value is a set of valid email addresses separated by a single ','");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/file-manual.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/file-manual.html
new file mode 100644
index 000000000..9e2d47c42
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/file-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type file</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#file-upload-state-(type=file)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<p>Manual test: clicking on the input should open a prompt allowing you to select a file.</p>
+<input type=file id=file>
+<script>
+ setup({explicit_timeout:true});
+
+ var input = document.getElementById('file'),
+ t1 = async_test("selecting files should fire the input event at the input element"),
+ t2 = async_test("selecting files should fire the change event at the input element");
+
+ document.getElementById('file').oninput = t1.step_func_done(function(e) {
+ assert_true(e.bubbles, "input event bubbles");
+ assert_true(e.isTrusted, "input event should be trusted");
+ assert_false(e.cancelable, "input event should not be cancelable");
+ })
+ document.getElementById('file').onchange = t2.step_func_done(function(e) {
+ assert_true(e.bubbles, "change event bubbles");
+ assert_true(e.isTrusted, "change event should be trusted");
+ assert_false(e.cancelable, "change event should not be cancelable");
+ assert_true(input.files instanceof FileList);
+ assert_equals(input.value, "C:\\fakepath\\" + input.files[0].name);
+ })
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/files.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/files.html
new file mode 100644
index 000000000..107b86c08
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/files.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLInputElement#files</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var types = [
+ "hidden",
+ "text",
+ "search",
+ "tel",
+ "url",
+ "email",
+ "password",
+ "date",
+ "month",
+ "week",
+ "time",
+ "datetime-local",
+ "number",
+ "range",
+ "color",
+ "checkbox",
+ "radio",
+ "submit",
+ "image",
+ "reset",
+ "button",
+];
+
+types.forEach(function(type) {
+ test(function() {
+ var input = document.createElement("input");
+ input.type = type;
+ assert_equals(input.files, null, "files should be null");
+ }, "files for input type=" + type);
+});
+
+test(function() {
+ var input = document.createElement("input");
+ input.type = "file";
+ assert_not_equals(input.files, null);
+ assert_true(input.files instanceof FileList, "files should be a FileList");
+ var files = input.files;
+ assert_equals(input.files, files, "files should return the same object");
+}, "files for input type=file");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/hidden.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/hidden.html
new file mode 100644
index 000000000..4aca00d8c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/hidden.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Hidden input element</title>
+ <link rel="author" title="Kinuko Yasuda" href="mailto:kinuko@chromium.org">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#hidden-state-(type=hidden)">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <h1>Hidden input element</h1>
+ <div style="display: none">
+
+ <input id="hidden" type="hidden" />
+ <input id="hidden_with_value" type="hidden" value="foo" />
+
+ </div>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").value, "");
+ assert_equals(document.getElementById("hidden_with_value").value, "foo");
+ }, "Value returns the current value for hidden");
+
+ test(
+ function() {
+ document.getElementById("hidden").value = "A";
+ assert_equals(document.getElementById("hidden").value, "A");
+ document.getElementById("hidden").value = "B";
+ assert_equals(document.getElementById("hidden").value, "B");
+ }, "Setting value changes the current value for hidden");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").files, null);
+ }, "files attribute must return null for hidden");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").valueAsDate, null);
+ }, "valueAsDate attribute must return null for hidden");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").valueAsNumber, NaN);
+ }, "valueAsNumber attribute must return NaN for hidden");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").list, null);
+ }, "list attribute must return null for hidden");
+
+ test(
+ function() {
+ var el = document.getElementById("hidden");
+ assert_throws("InvalidStateError", function() { el.stepDown(); }, "");
+ }, "stepDown does not apply for hidden");
+
+ test(
+ function() {
+ var el = document.getElementById("hidden");
+ assert_throws("InvalidStateError", function() { el.stepUp(); }, "");
+ }, "stepUp does not apply for hidden");
+
+ test(function(){
+ var el = document.getElementById("hidden");
+ assert_false(el.willValidate);
+ }, "input type=hidden is barred from constraint validation");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/image01-ref.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/image01-ref.html
new file mode 100644
index 000000000..62c141d96
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/image01-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type image reference file</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<img src="/media/poster.png"/>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/image01.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/image01.html
new file mode 100644
index 000000000..e9028dcee
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/image01.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type image</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#image-button-state-(type=image)">
+<link rel="match" href="image01-ref.html">
+<input type=image id=image src="/media/poster.png">
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/input-type-button.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/input-type-button.html
new file mode 100644
index 000000000..0f269355a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/input-type-button.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<head>
+<title>input type button</title>
+<link rel="author" title="Takeharu.Oshida" href="mailto:georgeosddev@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#button-state-(type=button)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<div id="hide" style="display">
+ <input type="button"/>
+ <input type="button" value="BUTTON"/>
+ <form action="/" method="get" onsubmit="isSubmitted = true;return false;">
+ <input type="button" value="mutable"/>
+ </form>
+ <form action="/" method="get" onsubmit="isSubmitted = true;return false;">
+ <input type="button" value="immutable" disabled/>
+ </form>
+</div>
+<script>
+var isSubmitted = false;
+var buttons = document.getElementsByTagName("input");
+
+test(function() {
+ assert_equals(buttons[0].click(), undefined, "The input element represents a button with no default behavior");
+},"default behavior");
+
+test(function() {
+ assert_equals(buttons[0].value, "", "It must be the empty string");
+},"empty value attribute");
+
+test(function() {
+ document.getElementById("hide").style.display = "block";
+ assert_not_equals(buttons[0].offsetWidth, buttons[1].offsetWidth, "If the element has a value attribute, the button's label must be the value of that attribute");
+ document.getElementById("hide").style.display = "none";
+},"label value");
+
+test(function() {
+ isSubmitted = false;
+ buttons[2].click();
+ assert_equals(isSubmitted, false, "If the element is mutable, the element's activation behavior is to do nothing.");
+},"mutable element's activation behavior is to do nothing.");
+
+test(function() {
+ isSubmitted = false;
+ buttons[3].click()
+ assert_equals(isSubmitted, false, "If the element is immutable, the element has no activation behavior.");
+},"immutable element has no activation behavior.");
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/input-type-checkbox.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/input-type-checkbox.html
new file mode 100644
index 000000000..7dd2f26b1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/input-type-checkbox.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<head>
+<title>input type checkbox</title>
+<link rel="author" title="Gary Gao" href="mailto:angrytoast@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div style="display:none;">
+ <input id="checkbox_default" type="checkbox" width="20" />
+
+ <input id="checkbox_checked" type="checkbox" checked />
+
+ <input id="checkbox_indeterminate" type="checkbox" />
+
+ <input id="checkbox_default_value" type="checkbox" />
+</div>
+
+<div id="log"></div>
+
+<script>
+ var checkbox_default = document.getElementById('checkbox_default'),
+ checkbox_checked = document.getElementById('checkbox_checked'),
+ checkbox_indeterminate = document.getElementById('checkbox_indeterminate'),
+ checkbox_default_value = document.getElementById('checkbox_default_value');
+
+ test(function() {
+ assert_false(checkbox_default.checked);
+ }, "default checkbox has no checkedness state");
+
+ test(function() {
+ assert_true(checkbox_checked.checked);
+ }, "checkbox with initial state set to checked has checkedness state");
+
+ test(function() {
+ checkbox_default.checked = 'chicken'
+ assert_true(checkbox_default.checked);
+ }, "changing the checked attribute to a string sets the checkedness state");
+
+ test(function() {
+ assert_false(checkbox_indeterminate.indeterminate);
+ }, "a checkbox has an indeterminate state set to false onload");
+
+ test(function() {
+ checkbox_indeterminate.indeterminate = true,
+ assert_true(checkbox_indeterminate.indeterminate);
+ }, "on setting, a checkbox's indeterminate state must be set to the new value and returns the last value it was set to");
+
+ test(function() {
+ assert_equals(checkbox_default_value.value, 'on');
+ }, "default/on: on getting, if the element has a value attribute, it must return that attribute's value; otherwise, it must return the string 'on'");
+
+ test(function() {
+ checkbox_default_value.value = 'chicken'
+ assert_equals(checkbox_default_value.value, 'chicken');
+ }, "on getting, if the element has a value attribute, it must return that attribute's value");
+</script>
+
+</body>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/maxlength-manual.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/maxlength-manual.html
new file mode 100644
index 000000000..fdf6c2644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/maxlength-manual.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>input max length</title>
+ <link rel="author" title="Sam Gibson" href="mailto:sam@ifdown.net">
+ <link rel=help href="https://html.spec.whatwg.org/multipage/forms.html#the-maxlength-and-minlength-attributes">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <div id="log"></div>
+ <p>Type a letter anywhere into the input field (do not select any text, or otherwise manipulate the input)</p>
+ <input type=text maxlength=4 id=only-four value="inpu"></input>
+
+ <script>
+ var input;
+ setup(function() {
+ input = document.getElementById('only-four');
+ }, {explicit_done: true, explicit_timeout: true});
+
+
+ on_event(input, 'keyup', function(event) {
+ if ((event.keyCode >= 65 && event.keyCode <= 90) ||
+ (event.keyCode >= 97 && event.keyCode <= 122)) {
+ test(function() {
+ assert_equals(input.value, "inpu");
+ }, 'input content should limit to maxlength')
+
+ done();
+ }
+ });
+ </script>
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/maxlength.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/maxlength.html
new file mode 100644
index 000000000..8f0a2567d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/maxlength.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>input max length</title>
+ <link rel="author" title="Sam Gibson" href="mailto:sam@ifdown.net">
+ <link rel=help href="https://html.spec.whatwg.org/multipage/forms.html#the-maxlength-and-minlength-attributes">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <h1>Text input element</h1>
+
+ <div style="display: none">
+ <input id="none" />
+ <input id="negative" type="-5" />
+ <input id="non-numeric" type="not-a-number" />
+ <input id="assign-negative" />
+ <input id="assign-non-numeric" />
+ </div>
+
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(
+ function() {
+ assert_equals(document.getElementById("none").maxLength, -1);
+ }, "Unset maxlength is -1");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("negative").maxLength, -1);
+ }, "Negative maxlength is always -1");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("non-numeric").maxLength, -1);
+ }, "Non-numeric maxlength is -1");
+
+ test(
+ function() {
+ assert_throws("INDEX_SIZE_ERR", function() {
+ document.getElementById("assign-negative").maxLength = -5;
+ });
+ }, "Assigning negative integer throws IndexSizeError");
+
+ test(
+ function() {
+ document.getElementById("assign-non-numeric").maxLength = "not-a-number";
+ assert_equals(document.getElementById("assign-non-numeric").maxLength, 0);
+ }, "Assigning non-numeric to maxlength sets maxlength to 0");
+ </script>
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/minlength.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/minlength.html
new file mode 100644
index 000000000..7bfdf189a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/minlength.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>input min length</title>
+ <link rel="author" title="Taryn Hill" href="mailto:Phrohdoh@gmail.com">
+ <link rel=help href="https://html.spec.whatwg.org/multipage/forms.html#the-minlength-and-minlength-attributes">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <h1>Text input element</h1>
+
+ <div style="display: none">
+ <input id="none" />
+ <input id="negative" minlength=-5 />
+ <input id="non-numeric" minlength="not-a-number" />
+ <input id="assign-negative" />
+ <input id="assign-non-numeric" />
+ </div>
+
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(
+ function() {
+ assert_equals(document.getElementById("none").minLength, -1);
+ }, "Unset minlength is -1");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("negative").minLength, -1);
+ }, "Negative minlength is always -1");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("non-numeric").minLength, -1);
+ }, "Non-numeric minlength is -1");
+
+ test(
+ function() {
+ assert_throws("INDEX_SIZE_ERR", function() {
+ document.getElementById("assign-negative").minLength = -5;
+ });
+ }, "Assigning negative integer throws IndexSizeError");
+
+ test(
+ function() {
+ document.getElementById("assign-non-numeric").minLength = "not-a-number";
+ assert_equals(document.getElementById("assign-non-numeric").minLength, 0);
+ }, "Assigning non-numeric to minlength sets minlength to 0");
+ </script>
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/month.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/month.html
new file mode 100644
index 000000000..15fa76dd4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/month.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Inputs Month</title>
+ <link rel="author" title="Morishita Hiromitsu" href="mailto:hero@asterisk-works.jp">
+ <link rel="author" title="kaseijin" href="mailto:pcmkas@gmail.com">
+ <link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#months">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#month-state-(type=month)">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Inputs Month</h1>
+ <div style="display: none">
+ <input id="valid" type="month" value="2011-11" min="2011-01" max="2011-12" />
+ <input id="invalid_value" type="month" value="invalid-month" min="2011-01" max="2011-12"/>
+ <input id="value_can_be_empty_string" type="month" value="2013-06" />
+ <input id="invalid_value_with_two_digits_year" type="month" value="13-06" />
+ <input id="invalid_value_is_set" type="month" />
+ <input id="step_attribute_is_invalid_value" type="month" value="2013-06" step="invalid_step_value" />
+ <input id="invalid_month_too_high" type="month" value="2013-13" />
+ <input id="invalid_month_too_low" type="month" value="2013-00" />
+ </div>
+
+ <div id="log"></div>
+
+ <script>
+ test(function() {
+ assert_equals(document.getElementById("valid").type, "month")
+ }, "month type support on input element");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_value").value, "")
+ }, "User agents must not allow the user to set the value to a non-empty string that is not a valid month string.");
+
+ test(function() {
+ document.getElementById("value_can_be_empty_string").value = "";
+ assert_equals(document.getElementById("value_can_be_empty_string").value, "")
+ }, "Month value can be empty string.");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_value_with_two_digits_year").value, "")
+ }, "When value attribute has two digits year value, the value,which is invalid, must return empty string.");
+
+ test(function() {
+ document.getElementById("invalid_value_is_set").value = "invalid value";
+ assert_equals(document.getElementById("invalid_value_is_set").value, "")
+ }, "When value is set with invalid value, the value must return empty string.");
+
+ test(function() {
+ document.getElementById("step_attribute_is_invalid_value").stepUp();
+ assert_equals(document.getElementById("step_attribute_is_invalid_value").value, "2013-07")
+ }, "When step attribute is given invalid value, it must ignore the invalid value and use defaul value instead.");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_month_too_high").value, "");
+ }, "Month should be <= 13: If the value of the element is not a valid month string, then set it to the empty string instead.");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_month_too_low").value, "");
+ }, "Month should be > 0: If the value of the element is not a valid month string, then set it to the empty string instead.>");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/number.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/number.html
new file mode 100644
index 000000000..5067d0e2f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/number.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=number</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#password-state-(type=number)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var numbers = [
+ {value: "", expected: "", testname: "empty value"},
+ {value: "11", expected: "11", testname: "value = 11"},
+ {value: "11.12", expected: "11.12", testname: "value = 11.12"},
+ {value: "-11111", expected: "-11111", testname: "value = -11111"},
+ {value: "-11111.123", expected: "-11111.123", testname: "value = -11111.123"},
+ {value: "1e2", expected: "1e2", testname: "value = 1e2"},
+ {value: "1E2", expected: "1E2", testname: "value = 1E2"},
+ {value: "1e+2", expected: "1e+2", testname: "value = 1e+2"},
+ {value: "1e-2", expected: "1e-2", testname: "value = 1e-2"},
+ {value: "1d+2", expected: "", testname: "value is not a valid floating-point number: 1d+2"},
+ {value: "foobar", expected: "", testname: "value not a valid floating-point number: random string"},
+ {value: "11", attributes: { min: "10" }, expected: "11", testname: "Value >= min attribute"},
+ {value: "9", attributes: { min: "10" }, expected: "9", testname: "Value < min attribute"},
+ {value: "19", attributes: { max: "20" }, expected: "19", testname: "Value <= max attribute"},
+ {value: "21", attributes: { max: "20" }, expected: "21", testname: "Value > max attribute"},
+ {value: ".1", expected: ".1", testname: "value with a leading '.'"},
+ {value: "1.", expected: "", testname: "value ending with '.'"},
+ {value: "-0", expected: "-0", testname: "value = -0"},
+ {value: "Infinity", expected: "", testname: " value = Infinity"},
+ {value: "-Infinity", expected: "", testname: "value = -Infinity"},
+ {value: "NaN", expected: "", testname: "value = NaN"},
+ {value: "9007199254740993", expected: "9007199254740992", testname: "value = 2^53+1"},
+ {value: "2e308", expected: "", testname: "value >= Number.MAX_VALUE"},
+ {value: "1e", expected: "", testname: "value = 1e"},
+ {value: "+1", expected: "1", testname: "value = +1"},
+ {value: "+", expected: "", testname: "value = '+'"},
+ {value: "-", expected: "", testname: "value = '-'"},
+ {value: " 1", expected: "1", testname: "value with a leading whitespace"},
+ {value: "1trailing junk", expected: "1", testname: "value = 1trailing junk"}
+ ];
+ for (var i = 0; i < numbers.length; i++) {
+ var w = numbers[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "number";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/password.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/password.html
new file mode 100644
index 000000000..aac54aa1c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/password.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Password input element</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#password-state-%28type=password%29">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div style="display: none">
+<input id="password" type="password" />
+<input id=password2 type=password value="password">
+<input id="password_with_value" type="password" value="foobar" />
+</div>
+<script type="text/javascript">
+ setup(function() {
+ window.password = document.getElementById("password");
+ });
+
+ test(function() {
+ assert_equals(password.value, "");
+ assert_equals(document.getElementById("password_with_value").value, "foobar");
+ }, "Value returns the current value for password");
+
+ test(function() {
+ password.value = "A";
+ assert_equals(password.value, "A");
+ assert_equals(password.getAttribute("value"), null);
+ password.value = "B";
+ assert_equals(password.value, "B");
+ assert_equals(password.getAttribute("value"), null);
+ }, "Setting value changes the current value for password, but not the value content attribute");
+
+ test(function() {
+ // Any LF (\n) must be stripped.
+ password.value = "\nAB";
+ assert_equals(password.value, "AB");
+ password.value = "A\nB";
+ assert_equals(password.value, "AB");
+ password.value = "AB\n";
+ assert_equals(password.value, "AB");
+
+ // Any CR (\r) must be stripped.
+ password.value = "\rAB";
+ assert_equals(password.value, "AB");
+ password.value = "A\rB";
+ assert_equals(password.value, "AB");
+ password.value = "AB\r";
+ assert_equals(password.value, "AB");
+
+ // Any combinations of LF CR must be stripped.
+ password.value = "\r\nAB";
+ assert_equals(password.value, "AB");
+ password.value = "A\r\nB";
+ assert_equals(password.value, "AB");
+ password.value = "AB\r\n";
+ assert_equals(password.value, "AB");
+ password.value = "\r\nA\n\rB\r\n";
+ assert_equals(password.value, "AB");
+ }, "Value sanitization algorithm should strip line breaks for password");
+
+ var pass = document.getElementById('password2');
+
+ test(function(){
+ assert_equals(pass.value, "password");
+ pass.value = " pass word ";
+ assert_equals(pass.value, " pass word ");
+ }, "sanitization algorithm doesn't strip leading and trailing whitespaces");
+
+ test(function(){
+ pass.value = "pass\u000Aword";
+ assert_equals(pass.value, "password");
+ pass.value = "\u000Apassword\u000A";
+ assert_equals(pass.value, "password");
+ pass.value = "pass\u000Dword";
+ assert_equals(pass.value, "password");
+ pass.value = "\u000Dpassword\u000D";
+ assert_equals(pass.value, "password");
+ }, "sanitization algorithm strips line breaks");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/pattern_attribute.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/pattern_attribute.html
new file mode 100644
index 000000000..ef01c2972
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/pattern_attribute.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Pattern Attribute</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-input-pattern">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+
+
+ <h1>Pattern Attribute</h1>
+ <div style="display: none">
+ <input pattern="[a-z]{3}" value="abcd" title="three letters max"/>
+ </div>
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].getAttribute("pattern"), "[a-z]{3}")}, "pattern attribute support on input element");
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/radio-groupname-case.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/radio-groupname-case.html
new file mode 100644
index 000000000..05192fc7d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/radio-groupname-case.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>radio group name compatibility caseless</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="http://people.mozilla.org/~jdaggett/tests/radiobuttonnamecase.html">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input id=r1 type="radio" name="sImPlE">
+<input id=r2 type="radio" name="simple">
+<input id=r3 type="radio" name="SIMPLE">
+
+<input id=r4 type="radio" name="paSSfield-killroyß">
+<input id=r5 type="radio" name="passfield-killroyß">
+<input id=r6 type="radio" name="PASSFIELD-KILLROYß">
+<input id=r7 type="radio" name="paſſfield-killroyß">
+<input id=r8 type="radio" name="passfield-&#x212a;illroyß">
+<input id=r9 type="radio" name="paßfield-killroyß">
+<input id=r10 type="radio" name="paẞfield-killroyß">
+<input id=r11 type="radio" name="passfield-killroyẞ">
+<input id=r12 type="radio" name="passfield-killroyß">
+<input id=r13 type="radio" name="passfıeld-killroyß">
+<input id=r14 type="radio" name="passfİeld-killroyß">
+
+<input id=r15 type="radio" name="глупый">
+<input id=r16 type="radio" name="глупы&#x438;&#x306;">
+<input id=r17 type="radio" name="ГЛУПЫЙ">
+<input id=r18 type="radio" name="ГЛУПЫ&#x418;&#x306;">
+
+<input id=r19 type="radio" name="åωk">
+<input id=r20 type="radio" name="ÅΩK">
+<input id=r21 type="radio" name="&#x212b;ωk">
+<input id=r22 type="radio" name="å&#x2126;k">
+<input id=r23 type="radio" name="åω&#x212a;">
+
+<input id=r24 type="radio" name="blah1">
+<input id=r25 type="radio" name="blah&#x2460;">
+<input id=r26 type="radio" name="bl&#x24b6;h1">
+<input id=r27 type="radio" name="bl&#x24d0;h1">
+
+<input id=r28 type="radio" name="t&Eacute;dz5アパートFi">
+<input id=r29 type="radio" name="T&Eacute;DZ5アパートFi">
+<input id=r30 type="radio" name="T&eacute;&#x01F1;&#x2075;アパートFi">
+<input id=r31 type="radio" name="t&Eacute;dz5&#x3300;Fi">
+<input id=r32 type="radio" name="t&Eacute;dz5&#x30A2;&#x30CF;&#x309A;&#x30FC;&#x30C8;Fi">
+<input id=r33 type="radio" name="t&Eacute;dz5&#x30A2;&#x30D1;&#x30FC;&#x30C8;Fi">
+<input id=r34 type="radio" name="T&Eacute;DZ⁵アパートFi">
+<input id=r35 type="radio" name="T&Eacute;DZ5アパートfi">
+
+<input id=r36 type="radio" name="ΣΣ">
+<input id=r37 type="radio" name="σς">
+<script>
+ var groups = [["r1" ,"r2", "r3"],
+ ["r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14"],
+ ["r15", "r16", "r17", "r18"],
+ ["r19", "r20", "r21", "r22", "r23"],
+ ["r24", "r25", "r26", "r27"],
+ ["r28", "r29", "r30", "r31", "r32", "r33", "r34", "r35"],
+ ["r36", "r37"]],
+ groupName = ["sImPlE", "paSSfield-killroyß", "глупый", "åωk", "blah1", "tÉdz5アパートFi", "ΣΣ"];
+ groups.forEach(function(group, index) {
+ test(function(){
+ group.forEach(function(radioId) {
+ assert_false(document.getElementById(radioId).checked);
+ });
+ for (var i = 0; i < group.length; i++) {
+ document.getElementById(group[i]).checked = true;
+ assert_true(document.getElementById(group[i]).checked);
+ for (var j = 0; j < group.length; j++) {
+ if (j != i) assert_false(document.getElementById(group[j]).checked);
+ }
+ }
+ }, "radio button group name = " + groupName[index]);
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/radio.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/radio.html
new file mode 100644
index 000000000..6681b3506
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/radio.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type radio</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input type=radio name=group1 id=radio1>
+<input type=radio name=group1 id=radio2>
+
+<input type=radio name=groüp2 id=radio3>
+<input type=radio name=groÜp2 id=radio4>
+
+<input type=radio id=radio5>
+<input type=radio id=radio6 disabled>
+
+<input type=radio name="group5" id=radio71 checked>
+<input type=radio name="group5" id=radio72>
+
+<input type=radio name=group3 id=radio8 checked>
+<input type=radio name=group3 id=radio9>
+<input type=radio name=group4 id=radio10>
+<input type=radio name=group4 id=radio11 checked>
+
+
+<script>
+ var radio1 = document.getElementById('radio1'),
+ radio2 = document.getElementById('radio2'),
+ radio3 = document.getElementById('radio3'),
+ radio4 = document.getElementById('radio4'),
+ radio5 = document.getElementById('radio5'),
+ radio6 = document.getElementById('radio6'),
+ radio71 = document.getElementById('radio71'),
+ radio72 = document.getElementById('radio72'),
+ radio8 = document.getElementById('radio8'),
+ radio9 = document.getElementById('radio9'),
+ radio10 = document.getElementById('radio10'),
+ radio11 = document.getElementById('radio11'),
+ t1 = async_test("click on mutable radio fires click event, then input event, then change event"),
+ t3 = async_test("click on non-mutable radio doesn't fire the input event"),
+ t4 = async_test("click on non-mutable radio doesn't fire the change event"),
+ t5 = async_test("canceled activation steps on unchecked radio"),
+ input_fired = false,
+ change_fired = false;
+
+ test(function(){
+ assert_false(radio1.checked);
+ assert_false(radio2.checked);
+ radio1.checked = true;
+ assert_true(radio1.checked);
+ assert_false(radio2.checked);
+ radio2.checked = true;
+ assert_false(radio1.checked);
+ assert_true(radio2.checked);
+ }, "only one control of a radio button group can have its checkedness set to true");
+
+ test(function(){
+ assert_false(radio3.checked);
+ assert_false(radio4.checked);
+ radio3.checked = true;
+ assert_true(radio3.checked);
+ assert_false(radio4.checked);
+ radio4.checked = true;
+ assert_false(radio3.checked);
+ assert_true(radio4.checked);
+ }, "radio inputs with name attributes groüp2 and groÜp2 belong to the same radio button group");
+
+ test(function(){
+ assert_true(radio8.checked);
+ assert_false(radio9.checked);
+ assert_false(radio10.checked);
+ assert_true(radio11.checked);
+ radio9.name="group4";
+ radio9.checked = true;
+ assert_true(radio8.checked);
+ assert_true(radio9.checked);
+ assert_false(radio10.checked);
+ assert_false(radio11.checked);
+ }, "changing the name of a radio input element and setting its checkedness to true makes all the other elements' checkedness in the same radio button group be set to false");
+
+ radio5.onclick = t1.step_func(function(e) {
+ click_fired = true;
+ assert_false(input_fired, "click event should fire before input event");
+ assert_false(change_fired, "click event should fire before change event");
+ assert_false(e.isTrusted, "click()-initiated click event shouldn't be trusted");
+ });
+
+ radio5.oninput = t1.step_func(function(e) {
+ input_fired = true;
+ assert_true(click_fired, "input event should fire after click event");
+ assert_false(change_fired, "input event should fire before change event");
+ assert_true(e.bubbles, "input event should bubble")
+ assert_true(e.isTrusted, "input event should be trusted");
+ assert_false(e.cancelable, "input event should not be cancelable");
+ });
+
+ radio5.onchange = t1.step_func(function(e) {
+ change_fired = true;
+ assert_true(click_fired, "change event should fire after click event");
+ assert_true(input_fired, "change event should fire after input event");
+ assert_true(e.bubbles, "change event should bubble")
+ assert_true(e.isTrusted, "change event should be trusted");
+ assert_false(e.cancelable, "change event should not be cancelable");
+ });
+
+ radio6.oninput= t3.step_func_done(function(e) {
+ assert_unreached("event input fired");
+ });
+
+ radio6.onchange = t4.step_func_done(function(e) {
+ assert_unreached("event change fired");
+ });
+
+ t1.step(function() {
+ radio5.click();
+ assert_true(input_fired);
+ t1.done();
+ });
+
+ t3.step(function(){
+ radio6.click();
+ t3.done();
+ t4.done();
+ });
+
+ radio72.onclick = t5.step_func_done(function(e){
+ assert_false(radio71.checked, "click on radio should uncheck other radio in same group");
+ assert_true(radio72.checked, "click on radio should check that radio");
+ e.preventDefault();
+ // The cancelation of the click doesn't have an effect until after all the click event handlers have been run.
+ assert_false(radio71.checked, "radio remains unchecked immediately after click event on other radio in same group is canceled");
+ assert_true(radio72.checked, "clicked radio remains checked immediately after click event is canceled");
+ });
+
+ t5.step(function(){
+ assert_true(radio71.checked, "initially checked radio should be checked");
+ assert_false(radio72.checked, "other radios in same group as initially-checked radio should be unchecked");
+ radio72.click();
+ // Now that the click event has been fully dispatched, its cancelation has taken effect.
+ assert_true(radio71.checked, "canceled click event on radio should leave the previously-checked radio checked");
+ assert_false(radio72.checked, "canceled click event on previously-unchecked radio should leave that radio unchecked");
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/range-2.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/range-2.html
new file mode 100644
index 000000000..3277dfc07
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/range-2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>range input Tests</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input type="range" id="r00" min="0" max="100" step="20" value="40" style="display:none">
+<input type="range" id="r01" min="0" max="1" step=".1" value=".2" style="display:none">
+<input type="range" id="r02" style="display:none">
+<input type="range" id="r03" style="display:none">
+<input type="range" id="r04" style="display:none">
+
+<script>
+test(function rangeElementTest0() {
+ document.getElementById('r00').value = "";
+ assert_equals(document.getElementById('r00').type, "range");
+ assert_equals(document.getElementById('r00').value, "60");
+}, "range input value set to ''");
+
+test(function rangeElementTest1() {
+ document.getElementById('r01').value = .6;
+ assert_equals(document.getElementById('r01').type, "range");
+ assert_equals(document.getElementById('r01').value, "0.6");
+}, "range input value set to an integer");
+
+test(function rangeElementTest2() {
+ assert_equals(document.getElementById('r02').type, "range");
+ assert_equals(document.getElementById('r02').value, "50");
+}, "range input value equals 50");
+
+test(function rangeElementTest3() {
+ document.getElementById('r03').value = 200;
+ assert_equals(document.getElementById('r03').type, "range");
+ assert_equals(document.getElementById('r03').value, "100");
+}, "range input value equals 100");
+
+test(function rangeElementTest4() {
+ document.getElementById('r04').value = 2.1;
+ assert_equals(document.getElementById('r04').type, "range");
+ assert_equals(document.getElementById('r04').value, "2");
+}, "range input value equals 2");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/range.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/range.html
new file mode 100644
index 000000000..2e7a85ea9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/range.html
@@ -0,0 +1,276 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Input Range</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="author" title="Tomoyuki SHIMIZU" href="mailto:tomoyuki.labs@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+
+
+ <h1>Input Range</h1>
+ <div style="display:none">
+ <input type="range" id="range_basic" min=0 max=5 />
+ <input type="range" id="value_smaller_than_min" min=0 max=5 value=-10 />
+ <input type="range" id="value_larger_than_max" min=0 max=5 value=7 />
+ <input type="range" id="empty_attributes" />
+ <input type="range" id="value_not_specified" min=2 max=6 />
+ <input type="range" id="control_step_mismatch" min=0 max=7 step=2 />
+ <input type="range" id="max_smaller_than_min" min=2 max=-3 />
+ <input type="range" id="default_step_scale_factor_1" min=5 max=12.6 value=6.7 />
+ <input type="range" id="default_step_scale_factor_2" min=5.3 max=12 value=6.7 />
+ <input type="range" id="default_step_scale_factor_3"min=5 max=12.6 step=0.5 value=6.7 />
+ <input type="range" id="float_step_scale_factor" min=5.3 max=12 step=0.5 value=6.7 />
+ <input type="range" id="stepup" min=3 max=14 value=6 step=3 />
+ <input type="range" id="stepdown" min=3 max=11 value=9 step=3 />
+ <input type="range" id="stepup_beyond_max" min=3 max=14 value=9 step=3 />
+ <input type="range" id="stepdown_beyond_min" min=3 max=11 value=6 step=3 />
+ <input type="range" id="illegal_min_and_max" min="ab" max="f" />
+ <input type="range" id="illegal_value_and_step" min=0 max=5 value="ppp" step="xyz" />
+ </div>
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+ test(
+ function() {
+ assert_equals(document.getElementById('range_basic').type, "range");
+ },
+ "range type support on input element",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('range_basic').min, "0")
+ },
+ "min attribute support on input element",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('range_basic').max, "5")
+ },
+ "max attribute support on input element",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max"
+ }
+ );
+
+ // HTML5 spec says the default vaules of min and max attributes are 0 and 100 respectively,
+ // however, Chrome, Opera and Firefox would not give any default value at all...
+ test(
+ function() {
+ assert_equals(document.getElementById('illegal_min_and_max').min, "0")
+ },
+ "Illegal value of min attribute",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('illegal_min_and_max').max, "100")
+ },
+ "Illegal value of max attribute",
+ { "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('illegal_value_and_step').value, "3")
+ },
+ "Converting an illegal string to the default value",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('illegal_value_and_step').step, "1")
+ },
+ "Converting an illegal string to the default step",
+ { "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('value_smaller_than_min').value, "0")
+ },
+ "the value is set to min when a smaller value than min attribute is given",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('value_larger_than_max').value, "5")
+ },
+ "the value is set to max when a larger value than max attribute is given",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('empty_attributes').min, "0")
+ },
+ "default value of min attribute in input type=range",
+ { "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('empty_attributes').max, "100")
+ },
+ "default value of max attribute in input type=range",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('value_not_specified').value, "4")
+ },
+ "default value when min and max attributes are given (= min plus half the difference between min and max)",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('control_step_mismatch').value, "4")
+ },
+ "default value with step control when both min and max attributes are given",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ // Chrome would result in different value out of the range between min and max. Why?
+ test(
+ function() {
+ assert_equals(document.getElementById('max_smaller_than_min').value, "2")
+ },
+ "default value when both min and max attributes are given, while min > max",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('default_step_scale_factor_1').value, "7")
+ },
+ "The default step scale factor is 1, unless min attribute has non-integer value",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('default_step_scale_factor_2').value, "6.3")
+ },
+ "Step scale factor behavior when min attribute has integer value but max attribute is non-integer ",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('default_step_scale_factor_3').step, "1")
+ },
+ "The default scale factor is 1 even if step attribute is explicitly set to non-integer value, unless min attribute has non-integer value",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('float_step_scale_factor').value, "6.8")
+ },
+ "Solving the step mismatch",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ // Firefox Nightly (24.0a1) would result in the possible maximum value in this range... (i.e. 12)
+ test(
+ function() {
+ var e = document.getElementById('stepup');
+ e.stepUp();
+ assert_equals(e.value, "9")
+ },
+ "Performing stepUp()",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup"
+ }
+ );
+
+ // Firefox Nightly (24.0a1) would result in the possible minimum value in this range... (i.e. 3)
+ test(
+ function() {
+ var e = document.getElementById('stepdown');
+ e.stepDown();
+ assert_equals(e.value, "6")
+ },
+ "Performing stepDown()",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown"
+ }
+ );
+
+ // Chrome and Opera would throw DOM Exception 11 (InvalidStateError)
+ // Firefox Nightly gives the correct result
+ test(
+ function() {
+ var e = document.getElementById('stepup_beyond_max');
+ e.stepUp(2);
+ assert_equals(e.value, "12")
+ },
+ "Performing stepUp() beyond the value of the max attribute",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup"
+ }
+ );
+
+ // Chrome and Opera would throw DOM Exception 11 (InvalidStateError)
+ // Firefox Nightly gives the correct result
+ test(
+ function() {
+ var e = document.getElementById('stepdown_beyond_min');
+ e.stepDown(2);
+ assert_equals(e.value, "3")
+ }, "Performing stepDown() beyond the value of the min attribute", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown"
+ }
+ );
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/required_attribute.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/required_attribute.html
new file mode 100644
index 000000000..63488e9f4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/required_attribute.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Required Attribute</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-input-required">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+
+
+ <h1>Required Attribute</h1>
+ <div style="display: none">
+ <input type="text" required="required" />
+ </div>
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].getAttribute("required"), "required")}, "required attribute support on input element");
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/reset.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/reset.html
new file mode 100644
index 000000000..9a9799542
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/reset.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type reset</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#reset-button-state-(type=reset)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form>
+ <input type=text id=input1 value="foobar">
+ <input type=text id=input2>
+ <input type=reset id=r1>
+</form>
+
+<input type=text id=input3 value="barfoo">
+
+<table>
+ <form>
+ <tr>
+ <td>
+ <input type=text id=input4 value="foobar">
+ <input type=reset id=r2>
+ </td>
+ </tr>
+ </form>
+</table>
+
+<div>
+ <form>
+ <input type=text id=input5 value="foobar">
+ </div>
+ <input type=reset id=r3>
+</form>
+
+<div>
+ <form>
+ <input type=reset id=r4>
+ </div>
+ <input type=text id=input6 value="foobar">
+</form>
+
+<form id=form5>
+ <input type=reset id=r5>
+</form>
+<input form=form5 type=text id=input7 value="foobar">
+
+<form id=form6>
+ <input type=text id=input8 value="foobar">
+</form>
+<input type=reset form=form6 id=r6>
+
+<script>
+ var input1 = document.getElementById('input1'),
+ input2 = document.getElementById('input2'),
+ input3 = document.getElementById('input3'),
+ input7 = document.getElementById('input7'),
+ input8 = document.getElementById('input8'),
+ r1 = document.getElementById('r1');
+
+ test(function(){
+ assert_equals(input1.value, "foobar");
+ assert_equals(input2.value, "");
+ assert_equals(input3.value, "barfoo");
+ input1.value = "foobar1";
+ input2.value = "notempty";
+ input3.value = "barfoo1";
+ assert_equals(input1.value, "foobar1");
+ assert_equals(input2.value, "notempty");
+ assert_equals(input3.value, "barfoo1");
+ r1.click();
+ assert_equals(input1.value, "foobar");
+ assert_equals(input2.value, "");
+ assert_equals(input3.value, "barfoo1");
+ }, "reset button only resets the form owner");
+
+ test(function(){
+ assert_false(r1.willValidate);
+ }, "the element is barred from constraint validation");
+
+ test(function(){
+ assert_equals(input1.value, "foobar");
+ assert_equals(input2.value, "");
+ assert_equals(input3.value, "barfoo1");
+ r1.disabled = true;
+ r1.click();
+ assert_equals(input1.value, "foobar");
+ assert_equals(input2.value, "");
+ assert_equals(input3.value, "barfoo1");
+ }, "clicking on a disabled reset does nothing");
+
+ function testReset(inputId, buttonId) {
+ var inp = document.getElementById(inputId);
+ assert_equals(inp.value, "foobar");
+ inp.value = "barfoo";
+ assert_equals(inp.value, "barfoo");
+ document.getElementById(buttonId).click();
+ assert_equals(inp.value, "foobar");
+ }
+
+ test(function(){
+ testReset("input4", "r2");
+ testReset("input5", "r3");
+ testReset("input6", "r4");
+ }, "reset button resets controls associated with their form using the form element pointer");
+
+ test(function(){
+ testReset("input7", "r5");
+ }, "reset button resets controls associated with a form using the form attribute");
+
+ test(function(){
+ testReset("input8", "r6");
+ }, "reset button associated with a form using the form attribute resets all the form's controls");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/search_input.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/search_input.html
new file mode 100644
index 000000000..175cdde99
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/search_input.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Search Input</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+
+
+ <h1>Search Input</h1>
+ <input type="search" style="display:none" placeholder="Search..." />
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].type, "search")}, "search type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].placeholder, "Search...")}, "placeholder attribute support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-placeholder" });
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/selection.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/selection.html
new file mode 100644
index 000000000..4ed4bc914
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/selection.html
@@ -0,0 +1,135 @@
+<!DOCTYPE HTML>
+<title>Input element programmatic selection support</title>
+<link rel="author" title="yaycmyk" href="mailto:evan@yaycmyk.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-select">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+/* all textual, non-hidden inputs support .select() */
+test(function() {
+ var valid = [
+ "text",
+ "search",
+ "url",
+ "tel",
+ "email",
+ "password",
+ "date",
+ "month",
+ "week",
+ "time",
+ "datetime-local",
+ "number",
+ "color",
+ "file",
+ ];
+
+ var invalid = [
+ "hidden",
+ "range",
+ "checkbox",
+ "radio",
+ "submit",
+ "image",
+ "reset",
+ "button"
+ ];
+
+ valid.forEach(function(type) {
+ test(function() {
+ var input = document.createElement("input");
+ var a;
+
+ input.type = type;
+ assert_equals(input.type, type, "the given input type is not supported");
+
+ input.select();
+
+ }, "input type " + type + " should support the select() method");
+ });
+
+ invalid.forEach(function(type) {
+ test(function() {
+ var input = document.createElement("input");
+
+ input.type = type;
+ assert_equals(input.type, type, "the given input type is not supported");
+
+ assert_throws("INVALID_STATE_ERR", function() { input.select(); });
+
+ }, "input type " + type + " should not support the select() method");
+ });
+});
+
+/* only certain input types are allowed to have a variable-length selection */
+test(function() {
+ var valid = [
+ "text",
+ "search",
+ "url",
+ "tel",
+ "password"
+ ];
+
+ var invalid = [
+ "hidden",
+ "email",
+ "date",
+ "month",
+ "week",
+ "time",
+ "datetime-local",
+ "number",
+ "range",
+ "color",
+ "checkbox",
+ "radio",
+ "file",
+ "submit",
+ "image",
+ "reset",
+ "button"
+ ];
+
+ valid.forEach(function(type) {
+ test(function() {
+ var input = document.createElement("input");
+ var a;
+
+ input.type = type;
+ assert_equals(input.type, type, "the given input type is not supported");
+
+ a = input.selectionStart;
+ input.selectionStart = 0;
+ a = input.selectionEnd;
+ input.selectionEnd = 0;
+ a = input.selectionDirection;
+ input.selectionDirection = "none";
+ input.setSelectionRange(0, 0);
+ input.setRangeText('', 0, 0);
+
+ }, "input type " + type + " should support all selection attributes and methods");
+ });
+
+ invalid.forEach(function(type) {
+ test(function() {
+ var input = document.createElement("input");
+
+ input.type = type;
+ assert_equals(input.type, type, "the given input type is not supported");
+
+ assert_equals(input.selectionStart, null, 'getting input.selectionStart');
+ assert_throws("INVALID_STATE_ERR", function() { input.selectionStart = 0; });
+ assert_equals(input.selectionEnd, null, 'getting input.selectionEnd');
+ assert_throws("INVALID_STATE_ERR", function() { input.selectionEnd = 0; });
+ assert_equals(input.selectionDirection, null, 'getting input.selectionDirection');
+ assert_throws("INVALID_STATE_ERR", function() { input.selectionDirection = "none"; });
+ assert_throws("INVALID_STATE_ERR", function() { input.setSelectionRange(0, 0); });
+ assert_throws("INVALID_STATE_ERR", function() { input.setRangeText('', 0, 0); });
+
+ }, "input type " + type + " should not support variable-length selections");
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/telephone.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/telephone.html
new file mode 100644
index 000000000..974cbaf88
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/telephone.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Input tel</title>
+ <link rel="author" title="Kazuki Kanamori" href="mailto:yogurito@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#telephone-state-(type=tel)">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Input tel</h1>
+ <input type="tel" id="novalue" />
+ <input type="tel" id="value_with_LF" value="0&#x000A;1" />
+ <input type="tel" id="value_with_CR" value="0&#x000D;1" />
+ <input type="tel" id="value_with_CRLF" value="0&#x000A;&#x000D;1" />
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+ var element = document.getElementById('novalue');
+ test(function(){
+ assert_equals(element.type, 'tel');
+ }, 'tel type supported on input element');
+ test(function(){
+ element.value = '0\u000A1';
+ assert_equals(element.value, '01');
+ }, 'User agents must not allow users to insert "LF" (U+000A)');
+ test(function(){
+ element.value = '0\u000D1';
+ assert_equals(element.value, '01');
+ }, 'User agents must not allow users to insert "CR" (U+000D)');
+
+ element = document.getElementById('value_with_LF');
+ test(function(){
+ assert_equals(element.value, '01');
+ }, 'The value attribute, if specified, must have a value that contains no "LF" (U+000A)');
+
+ element = document.getElementById('value_with_CR');
+ test(function(){
+ assert_equals(element.value, '01');
+ }, 'The value attribute, if specified, must have a value that contains no "CR" (U+000D)');
+
+ test(function(){
+ element = document.getElementById('novalue');
+ element.value = '0\u000D\u000A1';
+ assert_equals(element.value, '01');
+
+ element = document.getElementById('value_with_CRLF');
+ assert_equals(element.value, '01');
+ }, 'The value sanitization algorithm is as follows: Strip line breaks from the value');
+
+ element = document.getElementById('novalue');
+ test(function(){
+ element.value = '+811234';
+ assert_equals(element.value, '+811234');
+ }, 'Element can accept the phone number with plus sign(country code)');
+ test(function(){
+ element.value = '1234#5678';
+ assert_equals(element.value, '1234#5678');
+ }, 'Element can accept the phone number with hash mark(extension number)');
+ test(function(){
+ element.value = '123-456-789';
+ assert_equals(element.value, '123-456-789');
+ }, 'Element can accept the phone number with hyphen');
+ test(function(){
+ element.value = '123.456.789';
+ assert_equals(element.value, '123.456.789');
+ }, 'Element can accept the phone number with dots');
+ test(function(){
+ element.value = '1 23 4';
+ assert_equals(element.value, '1 23 4');
+ }, 'Element can accept the phone number with whitespace');
+ test(function(){
+ element.value = ' 1234 ';
+ assert_equals(element.value, ' 1234 ');
+ }, 'Element can accept the phone number with leading & following whitespaces');
+ test(function(){
+ element.value = '(03)12345678';
+ assert_equals(element.value, '(03)12345678');
+ }, 'Element can accept the phone number with parentheses(area code)');
+ </script>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/text.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/text.html
new file mode 100644
index 000000000..b6d4ceabf
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/text.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Text input element</title>
+ <link rel="author" title="Kinuko Yasuda" href="mailto:kinuko@chromium.org">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#text-(type=text)-state-and-search-state-(type=search)">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <h1>Text input element</h1>
+ <div style="display: none">
+
+ <input id="text" type="text" />
+ <input id="text_with_value" type="text" value="foo" />
+
+ <input id="search" type="search" />
+ <input id="search_with_value" type="search" value="foo" />
+
+ </div>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var types = [ 'text', 'search' ];
+
+ for (var i = 0; i < types.length; ++i) {
+ test(
+ function() {
+ assert_equals(document.getElementById(types[i]).value, "");
+ assert_equals(document.getElementById(types[i] + "_with_value").value, "foo");
+ }, "Value returns the current value for " + types[i]);
+
+ test(
+ function() {
+ document.getElementById(types[i]).value = "A";
+ assert_equals(document.getElementById(types[i]).value, "A");
+ document.getElementById(types[i]).value = "B";
+ }, "Setting value changes the current value for " + types[i]);
+
+ test(
+ function() {
+ // Any LF (\n) must be stripped.
+ document.getElementById(types[i]).value = "\nAB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "A\nB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "AB\n";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+
+ // Any CR (\r) must be stripped.
+ document.getElementById(types[i]).value = "\rAB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "A\rB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "AB\r";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+
+ // Any combinations of LF CR must be stripped.
+ document.getElementById(types[i]).value = "\r\nAB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "A\r\nB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "AB\r\n";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "\r\nA\n\rB\r\n";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ }, "Value sanitization algorithm should strip line breaks for " + types[i]);
+
+ test(
+ function() {
+ assert_equals(document.getElementById(types[i]).files, null);
+ }, "files attribute must return null for " + types[i]);
+
+ test(
+ function() {
+ assert_equals(document.getElementById(types[i]).valueAsDate, null);
+ }, "valueAsDate attribute must return null for " + types[i]);
+
+ test(
+ function() {
+ assert_equals(document.getElementById(types[i]).valueAsNumber, NaN);
+ }, "valueAsNumber attribute must return NaN for " + types[i]);
+
+ test(
+ function() {
+ assert_equals(document.getElementById("text").list, null);
+ }, "list attribute must return null for " + types[i]);
+
+ test(
+ function() {
+ var el = document.getElementById(types[i]);
+ assert_throws("InvalidStateError", function() { el.stepDown(); }, "");
+ }, "stepDown does not apply for " + types[i]);
+
+ test(
+ function() {
+ var el = document.getElementById(types[i]);
+ assert_throws("InvalidStateError", function() { el.stepUp(); }, "");
+ }, "stepUp does not apply for " + types[i]);
+ }
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/time-2.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/time-2.html
new file mode 100644
index 000000000..cf0d4cbbe
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/time-2.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=time</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/common-microsyntaxes.html#times">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/states-of-the-type-attribute.html#time-state-(type=time)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var times = [
+ {value: "", expected: "", testname: "empty value"},
+ {value: "00:00", expected: "00:00", testname: "Valid value: value should be 00:00"},
+ {value: "00:00:00", expected: "00:00:00", testname: "Valid value: value should be 00:00:00"},
+ {value: "00:00:00.0", expected: "00:00:00.0", testname: "Valid value: value should be 00:00:00.0"},
+ {value: "00:00:00.00", expected: "00:00:00.00", testname: "Valid value: value should be 00:00:00.00"},
+ {value: "00:00:00.000", expected: "00:00:00.000", testname: "Valid value: value should be 00:00:00.000"},
+ {value: "00:00:00.0000", expected: "", testname: "Invalid value: fraction should have one, two or three ASCII digits. Value should be empty"},
+ {value: "0:00:00.000", expected: "", testname: "Invalid value: hour should have two ASCII digits. Value should be empty"},
+ {value: "00:0:00.000", expected: "", testname: "Invalid value: minutes should have two ASCII digits. Value should be empty"},
+ {value: "00:00:0.000", expected: "", testname: "Invalid value: seconds should have two ASCII digits. Value should be empty"},
+ {value: "24:00:00.000", expected: "", testname: "Invalid value: hour > 23. Value should be empty"},
+ {value: "00:60:00.000", expected: "", testname: "Invalid value: minute > 59. Value should be empty"},
+ {value: "00:00:60.000", expected: "", testname: "Invalid value: second > 59. Value should be empty"},
+ {value: "12:00:00.001", attributes: { min: "12:00:00.000" }, expected: "12:00:00.001", testname: "Value >= min attribute"},
+ {value: "12:00:00.000", attributes: { min: "12:00:00.001" }, expected: "12:00:00.001", testname: "Value < min attribute"},
+ {value: "12:00:00.000", attributes: { max: "12:00:00.001" }, expected: "12:00:00.000", testname: "Value <= max attribute"},
+ {value: "12:00:00.001", attributes: { max: "12:00:00.000" }, expected: "12:00:00.000", testname: "Value > max attribute"}
+ ];
+ for (var i = 0; i < times.length; i++) {
+ var w = times[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "time";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/time.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/time.html
new file mode 100644
index 000000000..5178d91de
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/time.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Input Time</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <h1>Input Time</h1>
+ <div style="display:none;">
+ <input type="time "id="chkDefaultValue" />
+ <input type="time" id="chkStep" />
+ <input type="time" id="chkSetValueTest" />
+ <input type="time" id="chkSupportAttribute" min="01:01:01.001" max="12:12:12.012" step="600" />
+ </div>
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+/* check default value */
+test(function(){ assert_equals(document.getElementById("chkDefaultValue").value, "");
+}, "time element of default time value");
+test(function(){assert_equals(document.getElementById('chkStep').step, "");
+}, "step attribute on default value check");
+test(function(){assert_equals(document.getElementById('chkDefaultValue').max, "");
+}, "max attribute on default value check")
+test(function(){assert_equals(document.getElementById('chkDefaultValue').max, "");
+}, "min attribute on default value check")
+
+/* simple attribute test*/
+test(function(){assert_equals(document.getElementById("chkSupportAttribute").type,"time");}
+ , "type attribute support on input element");
+test(function(){assert_equals(document.getElementById('chkSupportAttribute').min, "01:01:01.001")}
+ , "max attribute support on input element");
+test(function(){assert_equals(document.getElementById('chkSupportAttribute').max, "12:12:12.012")}
+ , "min attribute support on input element");
+test(function(){assert_equals(document.getElementById("chkSupportAttribute").step, "600")}
+ , "step attribute support on input element");
+
+/* check step up and down */
+var _StepTest = document.getElementById("chkStep");
+test(function(){ assert_true(typeof(_StepTest.stepUp) ==="function" ) } , "stepUp function support on input Element");
+test(function(){ assert_true(typeof(_StepTest.stepDown) ==="function" ) } , "stepDown function support on input Element");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value,"12:01");
+} , "stepUp step value empty on default step value ");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value,"11:59");
+}, "stepDown step value empty default step value");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "-600";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "12:01");
+},"stepUp on step value minus");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "-600";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:59");
+},"stepDown on step value minus");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "0";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "12:01");
+} , "stepUp on step value zero ");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "0";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:59");
+} , "stepDown on step value zero ");
+
+test(function(){
+ _StepTest.value = "00:00";
+ _StepTest.step = "86399";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "23:59:59");
+} , "stepUp on step value 24 hour");
+test(function(){
+ _StepTest.value = "23:59:59";
+ _StepTest.step = "86399";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "00:00:00");
+} , "stepDown on step value 24 hour ");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "3600";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "13:00");
+} , "stepUp on step value hour ");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "3600";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:00");
+} , "stepDown on step value hour ");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "1";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "12:00:01");
+} , "stepUp on step value second ");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "1";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:59:59");
+} , "stepDown on step value second ");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "0.001";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "12:00:00.001");
+} , "stepUp on step value miri second ");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "0.001";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:59:59.999");
+} , "stepDown on step value miri second ");
+
+test(function(){
+ _StepTest.value = "13:00:00";
+ _StepTest.step = "1";
+ _StepTest.stepUp(2);
+ assert_equals(_StepTest.value, "13:00:02");
+}, "stepUp argment 2 times");
+test(function(){
+ _StepTest.value = "13:00:00";
+ _StepTest.step = "1";
+ _StepTest.stepDown(2);
+ assert_equals(_StepTest.value, "12:59:58");
+}, "stepDown argment 2 times");
+
+test(function(){
+ _StepTest.max = "15:00";
+ _StepTest.value = "15:00";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "15:00");
+ _StepTest.max = "";
+} , "stepUp stop because it exceeds the maximum value");
+test(function(){
+ _StepTest.min = "13:00";
+ _StepTest.value = "13:00";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "13:00");
+ _StepTest.min="";
+} , "stepDown Stop so lower than the minimum value");
+
+test(function(){
+ _StepTest.max = "15:01";
+ _StepTest.value = "15:00";
+ _StepTest.step = "120";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "15:01");
+ _StepTest.max = "";
+} , "stop at border on stepUp");
+test(function(){
+ _StepTest.min = "12:59";
+ _StepTest.value = "13:00";
+ _StepTest.step = "120";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "12:59");
+ _StepTest.min="";
+} , "stop at border on stepDown");
+
+test(function(){
+ _StepTest.value = "";
+ _StepTest.step = "60";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "00:01");
+} , " empty value of stepUp");
+
+
+/* set value test */
+test(function(){
+ var _time = document.getElementById("chkSetValueTest");
+ _time.value = "12:00:00.000";
+ assert_equals(_time.value, "12:00:00.000");
+ _time.value = "hh:mi:ss.sss";
+ assert_equals(_time.value, "");
+}, "set value on not time format value");
+
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/type-change-state.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/type-change-state.html
new file mode 100644
index 000000000..def11da84
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/type-change-state.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Input element's type attribute changes state</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-input-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var types = [
+ { type: "hidden" },
+ { type: "text", sanitizedValue: " foobar " },
+ { type: "search", sanitizedValue: " foobar " },
+ { type: "tel", sanitizedValue: " foobar " },
+ { type: "url", sanitizedValue: "foobar" },
+ { type: "email", sanitizedValue: "foobar" },
+ { type: "password", sanitizedValue: " foobar " },
+ { type: "datetime-local", sanitizedValue: "" },
+ { type: "date", sanitizedValue: "" },
+ { type: "month", sanitizedValue: "" },
+ { type: "week", sanitizedValue: "" },
+ { type: "time", sanitizedValue: "" },
+ { type: "number", sanitizedValue: "" },
+ { type: "range", sanitizedValue: "50" },
+ { type: "color", sanitizedValue: "#000000" },
+ { type: "checkbox" },
+ { type: "radio" },
+ { type: "file" },
+ { type: "submit" },
+ { type: "image" },
+ { type: "reset" },
+ { type: "button" }
+ ];
+ for (var i = 0; i < types.length; i++) {
+ for (var j = 0; j < types.length; j++) {
+ if (types[i] != types[j]) {
+ test(function() {
+ var input = document.createElement("input");
+ input.type = types[i].type;
+ if (types[i].type === "file") {
+ assert_throws("INVALID_STATE_ERR", function() {
+ input.value = " foo\rbar ";
+ });
+ assert_equals(input.value, "");
+ } else if (types[j].type === "file") {
+ input.value = " foo\rbar ";
+ input.type = types[j].type; // change state
+ assert_equals(input.value, "");
+ } else {
+ input.value = " foo\rbar ";
+ input.type = types[j].type; // change state
+ if (types[j].sanitizedValue || types[j].sanitizedValue === "") {
+ assert_equals(input.value, types[j].sanitizedValue, "input.value should be " + types[j].sanitizedValue + " after change of state");
+ } else {
+ assert_equals(input.value, " foo\rbar ", "input.value should be ' foo\\rbar ' after change of state");
+ }
+ }
+ }, "change state from " + types[i].type + " to " + types[j].type);
+ }
+ }
+ }
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/url.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/url.html
new file mode 100644
index 000000000..aafa0ced9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/url.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Input url</title>
+ <link rel="author" title="Hyeonseok Shin" href="mailto:hyeonseok@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#url-state-%28type=url%29">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Input url</h1>
+ <div style="display: none">
+ <input type="url" id="type_support" />
+ <input type="url" id="set_value_LF" />
+ <input type="url" id="set_value_CR" />
+ <input type="url" id="set_value_CRLF" />
+ <input type="url" id="value_with_CRLF" value="a&#x000D;&#x000A;a" />
+ <input type="url" id="value_with_leading_trailing_white_space" value=" aa " />
+ <input type="url" id="value_with_leading_trailing_inner_white_space" value=" a a " />
+ </div>
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+ test(function(){
+ var element = document.getElementById('type_support');
+ assert_equals(element.type, 'url');
+ }, 'url type supported on input element');
+
+ test(function(){
+ var element = document.getElementById('set_value_LF');
+ element.value = 'a\u000Aa';
+ assert_equals(element.value, 'aa');
+
+ element = document.getElementById('set_value_CR');
+ element.value = 'a\u000Da';
+ assert_equals(element.value, 'aa');
+
+ element = document.getElementById('set_value_CRLF');
+ element.value = 'a\u000D\u000Aa';
+ assert_equals(element.value, 'aa');
+ }, 'The value must not be set with "LF" (U+000A) or "CR" (U+000D)');
+
+ test(function(){
+ var element = document.getElementById('value_with_CRLF');
+ assert_equals(element.value, 'aa');
+ }, 'The value sanitization algorithm is as follows: Strip line breaks from the value');
+
+ test(function(){
+ var element = document.getElementById('value_with_leading_trailing_white_space');
+ assert_equals(element.value, 'aa');
+
+ element = document.getElementById('value_with_leading_trailing_inner_white_space');
+ assert_equals(element.value, 'a a');
+ }, 'The value sanitization algorithm is as follows: Strip leading and trailing whitespace from the value.');
+ </script>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/valueMode.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/valueMode.html
new file mode 100644
index 000000000..709c176dd
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/valueMode.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Input element value mode</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var types = [
+ { type: "hidden", mode: "default" },
+ { type: "text", mode: "value", sanitizedValue: "foo" },
+ { type: "search", mode: "value", sanitizedValue: "foo" },
+ { type: "tel", mode: "value", sanitizedValue: "foo" },
+ { type: "url", mode: "value", sanitizedValue: "foo" },
+ { type: "email", mode: "value", sanitizedValue: "foo" },
+ { type: "password", mode: "value", sanitizedValue: "foo" },
+ { type: "datetime-local", mode: "value", sanitizedValue: "" },
+ { type: "date", mode: "value", sanitizedValue: "" },
+ { type: "month", mode: "value", sanitizedValue: "" },
+ { type: "week", mode: "value", sanitizedValue: "" },
+ { type: "time", mode: "value", sanitizedValue: "" },
+ { type: "number", mode: "value", sanitizedValue: "" },
+ { type: "range", mode: "value", sanitizedValue: "50" },
+ { type: "color", mode: "value", sanitizedValue: "#000000" },
+ { type: "checkbox", mode: "default/on" },
+ { type: "radio", mode: "default/on" },
+ { type: "submit", mode: "default" },
+ { type: "image", mode: "default" },
+ { type: "reset", mode: "default" },
+ { type: "button", mode: "default" }
+ ];
+ for (var i = 0; i < types.length; i++) {
+ test(function() {
+ var input = document.createElement("input"),
+ expected;
+ input.type = types[i].type;
+ input.value = "foo";
+ switch(types[i].mode) {
+ case "default":
+ expected = "";
+ break;
+ case "default/on":
+ expected = "on";
+ break;
+ case "value":
+ expected = types[i].sanitizedValue;
+ break;
+ }
+ assert_equals(input.value, expected);
+ }, "value IDL attribute of input type " + types[i].type + " without value attribute");
+
+ test(function() {
+ var input = document.createElement("input"),
+ expected;
+ input.type = types[i].type;
+ input.setAttribute("value", "bar");
+ input.value = "foo";
+ switch(types[i].mode) {
+ case "default":
+ expected = "bar";
+ break;
+ case "default/on":
+ expected = "bar";
+ break;
+ case "value":
+ expected = types[i].sanitizedValue;
+ break;
+ }
+ assert_equals(input.value, expected);
+ }, "value IDL attribute of input type " + types[i].type + " with value attribute");
+ }
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/week.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/week.html
new file mode 100644
index 000000000..e06b67889
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/week.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=week</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#weeks">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#week-state-(type=week)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var weeks = [
+ {value: "", expected: "", testname: "empty value"},
+ {value: "2014-W52", expected: "2014-W52", testname: "Valid value: Value should be 2014-W52"},
+ {value: "2014-W53", expected: "", testname: "2014 has 52 weeks: Value should be empty"},
+ {value: "2015-W53", expected: "2015-W53", testname: "2015 has 53 weeks: Value should be 2015-W53"},
+ {value: "2014", expected: "", testname: "Invalid value: year only"},
+ {value: "2014W", expected: "", testname: "Invalid value: no week number"},
+ {value: "2014W52", expected: "", testname: "Invalid value: no '-' (U+002D)"},
+ {value: "-W52", expected: "", testname: "Invalid value: yearless week"},
+ {value: "W52", expected: "", testname: "Invalid value: yearless week and no '-' (U+002D)"},
+ {value: "2014-W03", attributes: { min: "2014-W02" }, expected: "2014-W03", testname: "Value >= min attribute"},
+ {value: "2014-W01", attributes: { min: "2014-W02" }, expected: "2014-W02", testname: "Value < min attribute"},
+ {value: "2014-W10", attributes: { max: "2014-W11" }, expected: "2014-W10", testname: "Value <= max attribute"},
+ {value: "2014-W12", attributes: { max: "2014-W11" }, expected: "2014-W11", testname: "Value > max attribute"}
+ ];
+ for (var i = 0; i < weeks.length; i++) {
+ var w = weeks[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "week";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-keygen-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-keygen-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-keygen-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-label-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-label-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-label-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-label-element/label-attributes.html b/testing/web-platform/tests/html/semantics/forms/the-label-element/label-attributes.html
new file mode 100644
index 000000000..826533e0c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-label-element/label-attributes.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: The label element</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id="fm" style="display:none">
+ <label id="lbl0" for="test0"></label>
+ <b id="test0"></b>
+
+ <input id="test1"></input>
+
+ <label id="lbl1">
+ <a id="test2"></a>
+ <div><input id="test3"></div>
+ <input id="test4">
+ </label>
+
+ <label id="lbl2" for="testx">
+ <input id="test5">
+ </label>
+
+ <label id="lbl3" for="test6">
+ <b id="test6"></b>
+ <input id="test6" class="class1">
+ </label>
+
+ <label id="lbl4" for="">
+ <input id="" class="class2">
+ </label>
+
+ <label id="lbl5" for="test7"></label>
+ <input id="test7">
+</form>
+
+<label id="lbl6" for="test7"></label>
+
+<script>
+
+ //control attribute
+ test(function () {
+ assert_not_equals(document.getElementById("lbl0").control, document.getElementById("test0"),
+ "An element that's not a labelable element can't be a label element's labeled control.");
+ assert_equals(document.getElementById("lbl0").control, null,
+ "A label element whose 'for' attribute doesn't reference any labelable element shouldn't have any labeled control.");
+ }, "A label element with a 'for' attribute should only be associated with a labelable element.");
+
+ test(function () {
+ var label = document.createElement("label");
+ label.htmlFor = "test1";
+ assert_not_equals(label.control, document.getElementById("test1"),
+ "A label element not in a document should not label an element in a document.");
+ document.body.appendChild(label);
+ assert_equals(label.control, document.getElementById("test1"));
+ label.remove();
+ }, "A label element not in a document can not label any element in the document.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl1").control, document.getElementById("test3"),
+ "The first labelable descendant of a label element should be its labeled control.");
+
+ var input = document.createElement("input");
+ document.getElementById("lbl1").insertBefore(input, document.getElementById("test2"));
+ assert_equals(document.getElementById("lbl1").control, input,
+ "The first labelable descendant of a label element in tree order should be its labeled control.");
+ input.remove();
+ }, "The labeled control for a label element that has no 'for' attribute is the first labelable element which is a descendant of that label element.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl2").control, null,
+ "The label's 'control' property should return null if its 'for' attribute points to an inexistent element.");
+ }, "The 'for' attribute points to an inexistent id.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl3").control, null, "The label should have no control associated.");
+ assert_equals(document.querySelector(".class1").labels.length, 0);
+ }, "A non-control follows by a control with same ID.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl4").control, null,
+ "A label element with an empty 'for' attribute should not associate with anything.");
+ }, "The 'for' attribute is an empty string.");
+
+ //labels attribute
+ test(function () {
+ var labels = document.getElementById("test7").labels;
+ assert_true(labels instanceof NodeList,
+ "A form control's 'labels' property should be an instance of a NodeList.");
+ assert_equals(labels.length, 2,
+ "The number of labels associated with a form control should be the number of label elements for which it is a labeled control.");
+ assert_array_equals(labels, [document.getElementById("lbl5"), document.getElementById("lbl6")],
+ "The labels for a form control should be returned in tree order.");
+
+ var newLabel = document.createElement("label");
+ newLabel.htmlFor = "test7";
+ document.getElementById("fm").insertBefore(newLabel, document.getElementById("lbl0"));
+ assert_array_equals(document.getElementById("test7").labels, [newLabel, document.getElementById("lbl5"), document.getElementById("lbl6")],
+ "The labels for a form control should be returned in tree order.");
+ newLabel.remove();
+ }, "A form control has multiple labels.");
+
+ test(function () {
+ var labels = document.getElementById("test3").labels;
+ assert_true(labels instanceof NodeList, "A form control's 'labels' property should be an instance of a NodeList.");
+ assert_equals(labels.length, 1, "The form control has an ancestor with no explicit associated label, and is the first labelable descendant.");
+ }, "A form control has an implicit label.");
+
+ test(function () {
+ var labels = document.getElementById("test4").labels;
+ assert_true(labels instanceof NodeList, "A form control's 'labels' property should be an instance of a NodeList.");
+ assert_equals(labels.length, 0, "The form control has an ancestor with no explicit associated label, but is *not* the first labelable descendant");
+ }, "A form control has no label 1.");
+
+ test(function () {
+ assert_equals(document.getElementById("test5").labels.length, 0,
+ "The number of labels should be 0 if the form control has an ancestor label element that the for attribute points to another control.");
+ assert_equals(document.getElementById("lbl2").control, null,
+ "The labeled cotrol should be associated with the control whose ID is equal to the value of the 'for' attribute.");
+ }, "A form control has no label 2.");
+
+ // form attribute
+ test(function () {
+ assert_equals(document.getElementById("lbl0").form, null,
+ "The 'form' property for a label should return null if label.control is null.");
+ }, "A label in a form without a control");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl6").form, document.getElementById("fm"),
+ "The 'form' property for a label should return label.control.form.");
+ }, "A label outside a form with a control inside the form");
+
+ // htmlFor attribute
+ test(function () {
+ assert_equals(document.getElementById("lbl2").htmlFor, "testx");
+ }, "A label's htmlFor attribute must reflect the for content attribute");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-label-element/labelable-elements.html b/testing/web-platform/tests/html/semantics/forms/the-label-element/labelable-elements.html
new file mode 100644
index 000000000..7bbb0b395
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-label-element/labelable-elements.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: labelable elements</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form style="display:none">
+ <output id="testoutput"></output>
+ <label id="lbl0" for="testoutput"></label>
+ <progress id="testprogress"></progress>
+ <label id="lbl1" for="testprogress"></label>
+ <select id="testselect"></select>
+ <label id="lbl2" for="testselect"></label>
+ <textarea id="testarea"></textarea>
+ <label id="lbl3" for="testarea"></label>
+ <button id="testButton"></button>
+ <label id="lbl4" for="testButton"></label>
+ <input type="hidden" id="testHidden">
+ <label id="lbl5" for="testHidden"></label>
+ <input type="radio" id="testRadio">
+ <label id="lbl6" for="testRadio"></label>
+ <keygen id="testkeygen">
+ <label id="lbl7" for="testkeygen"></label>
+ <meter id="testmeter"></meter>
+ <label id="lbl8" for="testmeter"></label>
+
+ <fieldset id="testfieldset"></fieldset>
+ <label id="lbl9" for="testfieldset"></label>
+ <label id="testlabel"></label>
+ <label id="lbl10" for="testlabel"></label>
+ <object id="testobject"></object>
+ <label id="lbl11" for="testobject"></label>
+ <img id="testimg">
+ <label id="lbl12" for="testimg"></label>
+</form>
+
+<script>
+function testLabelsAttr(formElementId, labelElementId, hasLabels) {
+ var elem = document.getElementById(formElementId);
+ if (labelElementId) {
+ assert_equals(elem.labels.length, 1);
+ assert_equals(elem.labels[0].id, labelElementId);
+ } else {
+ assert_equals(elem.labels.length, 0);
+ }
+}
+
+test(function() {
+ assert_equals(document.getElementById("lbl0").control.id, "testoutput", "An output element should be labelable.");
+}, "Check if the output element is a labelable element");
+
+test(function() {
+ testLabelsAttr("testoutput", "lbl0");
+}, "Check if the output element can access 'labels'");
+
+test(function() {
+ assert_equals(document.getElementById("lbl1").control.id, "testprogress", "A progress element should be labelable.");
+}, "Check if the progress element is a labelable element");
+
+test(function() {
+ testLabelsAttr("testprogress", "lbl1");
+}, "Check if the progress element can access 'labels'");
+
+test(function() {
+ assert_equals(document.getElementById("lbl2").control.id, "testselect", "A select element should be labelable.");
+}, "Check if the select element is a labelable element");
+
+test(function() {
+ testLabelsAttr("testselect", "lbl2");
+}, "Check if the select element can access 'labels'");
+
+test(function() {
+ assert_equals(document.getElementById("lbl3").control.id, "testarea", "A textarea element should be labelable.");
+}, "Check if the textarea element is a labelable form-element");
+
+test(function() {
+ testLabelsAttr("testarea", "lbl3");
+}, "Check if the textarea element can access 'labels'");
+
+test(function() {
+ assert_equals(document.getElementById("lbl4").control.id, "testButton", "A button element should be labelable.");
+}, "Check if the button element is a labelable element");
+
+test(function() {
+ testLabelsAttr("testButton", "lbl4");
+}, "Check if the button element can access 'labels'");
+
+test(function() {
+ assert_equals(document.getElementById("lbl5").control, null, "An input element in hidden state should not be labelable.");
+}, "Check if the hidden input element is not a labelable element.");
+
+test(function() {
+ testLabelsAttr("testHidden", null);
+}, "Check if the hidden input element can access 'labels'");
+
+test(function() {
+ assert_equals(document.getElementById("lbl6").control.id, "testRadio", "An input element in radio state should be labelable.");
+}, "Check if the input element in radio state is a labelable element");
+
+test(function() {
+ testLabelsAttr("testRadio", "lbl6");
+}, "Check if the input element in radio state can access 'labels'");
+
+test(function() {
+ assert_equals(document.getElementById("lbl7").control.id, "testkeygen", "A keygen element should be labelable.");
+}, "Check if the keygen element is a labelable element");
+
+test(function() {
+ testLabelsAttr("testkeygen", "lbl7");
+}, "Check if the keygen element can access 'labels'");
+
+test(function() {
+ assert_equals(document.getElementById("lbl8").control.id, "testmeter", "A meter element should be labelable.");
+}, "Check if the meter element is a labelable element");
+
+test(function() {
+ testLabelsAttr("testmeter", "lbl8");
+}, "Check if the meter element can access 'labels'");
+
+test(function() {
+ assert_not_equals(document.getElementById("lbl9").control, document.getElementById("testfieldset"));
+ assert_equals(document.getElementById("lbl9").control, null, "A fieldset element should not be labelable.");
+}, "Check if the fieldset element is not a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("testfieldset").labels, undefined);
+}, "Check if the fieldset element can access 'labels'");
+
+test(function() {
+ assert_not_equals(document.getElementById("lbl9").control, document.getElementById("testlabel"));
+ assert_equals(document.getElementById("lbl10").control, null, "A label element should not be labelable.");
+}, "Check if the label element is not a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("testlabel").labels, undefined);
+}, "Check if the label element can access 'labels'");
+
+test(function() {
+ assert_not_equals(document.getElementById("lbl9").control, document.getElementById("testobject"));
+ assert_equals(document.getElementById("lbl11").control, null, "An object element should not be labelable.");
+}, "Check if the object element is not a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("testobject").labels, undefined);
+}, "Check if the object element can access 'labels'");
+
+test(function() {
+ assert_not_equals(document.getElementById("lbl9").control, document.getElementById("testimg"));
+ assert_equals(document.getElementById("lbl12").control, null, "An img element should not be labelable.");
+}, "Check if the img element is not a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("lbl9").labels, undefined);
+}, "Check if the img element can access 'labels'");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-legend-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-legend-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-legend-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-legend-element/legend-form.html b/testing/web-platform/tests/html/semantics/forms/the-legend-element/legend-form.html
new file mode 100644
index 000000000..b127164ae
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-legend-element/legend-form.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLLegendElement Test: form</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<div style="display:none">
+ <form id="testform">
+ <legend id="testlegend">radio</legend>
+ </form>
+</div>
+
+<div style="display:none">
+ <form id="testformWithFieldSet">
+ <fieldset>
+ <legend id="legendWithFieldSet">radio</legend>
+ </fieldset>
+ </form>
+</div>
+<script>
+test(function () {
+ var legendEle = document.getElementById("legendWithFieldSet");
+ assert_not_equals(legendEle.form, null);
+ assert_equals(legendEle.form, document.getElementById("testformWithFieldSet"));
+}, "Check if legend.form returns its parent when it's inside a fieldset");
+test(function () {
+ var legendEle = document.getElementById("testlegend");
+ assert_equals(legendEle.form, null);
+}, "Check if legend.form return null when legend has no fieldset element as its parent");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-meter-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-meter-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-meter-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-meter-element/meter.html b/testing/web-platform/tests/html/semantics/forms/the-meter-element/meter.html
new file mode 100644
index 000000000..1c1ce4f18
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-meter-element/meter.html
@@ -0,0 +1,250 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>The meter element</title>
+ <link rel="author" title="Tomoyuki SHIMIZU" href="mailto:tomoyuki.labs@gmail.com">
+ <link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-meter-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Meter Element</h1>
+ <div id="log"></div>
+ <div style="display: none;">
+ <meter id="meter_illegal_value" value="abc"></meter>
+ <meter id="meter_without_min" value="-10"></meter>
+ <meter id="meter_without_max" value="10"></meter>
+ <meter id="meter_min_without_max_1" value="10" min="-3.1"></meter>
+ <meter id="meter_min_without_max_2" value="210" min="12.1"></meter>
+ <meter id="meter_max_without_min_1" value="-10" max="-5342.55"></meter>
+ <meter id="meter_max_without_min_2" value="210" max="-9.9"></meter>
+ <meter id="meter_illegal_min" value="-2" min="hugfe"></meter>
+ <meter id="meter_illegal_max" value="2.4" max="min"></meter>
+ <meter id="meter_illegal_low_with_min" value="-20" min="-10.3" low="ahuge"></meter>
+ <meter id="meter_illegal_high_with_max" value="2.4" high="old" max="1.5"></meter>
+ <meter id="meter_smaller_than_min" value="-10" min="4.5"></meter>
+ <meter id="meter_larger_than_max" value="2345.53" max="52.02"></meter>
+ <meter id="meter_default_low_and_high_1" value="40" min="-12.3" max="3.4"></meter>
+ <meter id="meter_default_low_and_high_2" value="23"></meter>
+ <meter id="meter_low_smaller_than_min" value="-4" min="12.3" low="34"></meter>
+ <meter id="meter_low_larger_than_max" value="-1" min="-50" low="-5" max="-34.5"></meter>
+ <meter id="meter_high_smaller_than_min" value="-4" min="12.3" high="34"></meter>
+ <meter id="meter_high_larger_than_max" value="-1" min="-50" high="-5" max="-34.5"></meter>
+ <meter id="meter_high_smaller_than_low" value="-9" min="-20" low="-10.3" high="-15.2" max="-2"></meter>
+ <meter id="meter_low_without_min" value="-1" low="-5"></meter>
+ <meter id="meter_high_without_max" value="50000" high="4"></meter>
+ <meter id="meter_optimum_smaller_than_min" value="-8" optimum="-4"></meter>
+ <meter id="meter_optimum_larger_than_max" value="324" optimum="4.6"></meter>
+ <meter id="meter_default_optimum" value="10" min="-132.35" max="33.423"></meter>
+ </div>
+ <script>
+ var meters = [
+ {value: 0, expectedValue: 0, expectedMin: 0, expectedMax: 1.0, expectedLow: 0, expectedHigh: 1.0, expectedOptimum: 0.5, testname: "Default values"},
+ {value: 3, expectedValue: 3, min: -10.1, expectedMin: -10.1, max: 10.1, expectedMax: 10.1, low: -9.1, expectedLow: -9.1, high: 9.1, expectedHigh: 9.1, optimum: 3, expectedOptimum: 3, testname: "Setting values to min, max, low, high and optimum"},
+ {value: 0, expectedValue: 0, min: 0, expectedMin: 0, max: -1.0, expectedMax: 0, expectedLow: 0, expectedHigh: 0, expectedOptimum: 0, testname: "max < min"},
+ {value: 0, expectedValue: 10, min: 10, expectedMin: 10, max: 20, expectedMax: 20, expectedLow: 10, expectedHigh: 20, expectedOptimum: 15, testname: "value < min"},
+ {value: 30, expectedValue: 20, min: 10, expectedMin: 10, max: 20, expectedMax: 20, expectedLow: 10, expectedHigh: 20, expectedOptimum: 15, testname: "value > max"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, low: 5, expectedLow: 10, expectedHigh: 20, expectedOptimum: 15, testname: "low < min"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, low: 25, expectedLow: 20, expectedHigh: 20, expectedOptimum: 15, testname: "low > max"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, low: 12, expectedLow: 12, high: 10, expectedHigh: 12, expectedOptimum: 15, testname: "high < low"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, low: 10, expectedLow: 10, high: 22, expectedHigh: 20, expectedOptimum: 15, testname: "high > max"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, expectedLow: 10, expectedHigh: 20, optimum: 9, expectedOptimum: 10, testname: "optimum < min"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, expectedLow: 10, expectedHigh: 20, optimum: 21, expectedOptimum: 20, testname: "optimum > max"}
+ ];
+ for (var i = 0; i < meters.length; i++) {
+ var m = meters[i];
+ test(function() {
+ var meter = document.createElement("meter");
+ meter.value = m.value;
+ if (m.min) meter.min= m.min;
+ if (m.max) meter.max = m.max;
+ if (m.low) meter.low = m.low;
+ if (m.high) meter.high = m.high;
+ if (m.optimum) meter.optimum = m.optimum;
+ assert_equals(meter.value, m.expectedValue, "meter value");
+ assert_equals(meter.min, m.expectedMin, "min value");
+ assert_equals(meter.max, m.expectedMax, "max value");
+ assert_equals(meter.low, m.expectedLow, "low value");
+ assert_equals(meter.high, m.expectedHigh, "high value");
+ assert_equals(meter.optimum, m.expectedOptimum, "optimum value");
+ }, m.testname);
+ }
+ test(function() {
+ var meter = document.createElement("meter");
+ assert_throws(new TypeError(), function() { meter.value = "foobar"; }, "value attribute");
+ assert_throws(new TypeError(), function() { meter.min = "foobar"; }, "min attribute");
+ assert_throws(new TypeError(), function() { meter.max = "foobar"; }, "max attribute");
+ assert_throws(new TypeError(), function() { meter.low = "foobar"; }, "low attribute");
+ assert_throws(new TypeError(), function() { meter.high = "foobar"; }, "high attribute");
+ assert_throws(new TypeError(), function() { meter.optimum = "foobar"; }, "optimum attribute");
+ }, "Invalid floating-point number values");
+
+ </script>
+ <script type="text/javascript">
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_value').value, 0);
+ }, "value must be 0 when a string is given");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_without_min').min, 0);
+ }, "default value of min is 0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_without_min').value, 0);
+ }, "If min is not specified and value is smaller than the default value of min (i.e. 0), the actual value must be 0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_without_max').max, 1.0);
+ }, "default value of max is 1.0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_without_max').value, 1.0);
+ }, "If max is not specified and value is larger than the default value of max (i.e. 1.0), the actual value must be 1.0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_min_without_max_1').max, 1.0);
+ }, "If a value smaller than 1.0 is given to min and max is not specified, max must be the same value as its default value (i.e. 1.0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_min_without_max_1').value, 1.0);
+ }, "If a value smaller than 1.0 is given to min, max is not specified, and value is larger than the default value of max (i.e. 1.0), the actual value must be 1.0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_min_without_max_2').max, 12.1);
+ }, "If a value larger than or equal to 1.0 is given to min and max is not specified, max must be the same value as min");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_min_without_max_2').value, 12.1);
+ }, "If a value larger than or equal to 1.0 is given to min and max is not specified, the actual value must be the same value as min");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_1').min, 0);
+ }, "If a value smaller than 0 is given to max and min is not specified, min must be be the same value as its default value (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_1').max, 0);
+ }, "If a value smaller than 0 is given to max and min is not specified, max must be be the same value as the default value of min (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_1').value, 0);
+ }, "If a value smaller than 0 is given to max and min is not specified, the actual value must be be the same value as the default value of min (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_2').max, 0);
+ }, "If a value larger than or equal to 0 is given to max and min is not specified, max must be the same value as the default value of min (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_2').min, 0);
+ }, "If a value larger than or equal to 0 is given to max and min is not specified, min must be the same value as its default value (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_2').value, 0);
+ }, "If a value larger than or equal to 0 is given to max and min is not specified, the actual value must be the same value as the default value of min (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_min').min, 0);
+ }, "min must be 0 when a string is given");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_min').value, 0);
+ }, "If a string is given to min and value is smaller than the default value of min (i.e. 0), the actual value must be 0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_max').max, 1.0);
+ }, "max must be 1.0 when a string is given");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_max').value, 1.0);
+ }, "If a string is given to max and value is larger than the default value of min (i.e. 1.0), the actual value must be 1.0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_low_with_min').low, -10.3);
+ }, "giving a string to low must not affect the actual value");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_high_with_max').high, 1.5);
+ }, "high must equal max when a string is given to high");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_high_with_max').value, 1.5);
+ }, "giving a string to high must not affect the actual value");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_smaller_than_min').value, 4.5);
+ }, "value must not be smaller than min");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_larger_than_max').value, 52.02);
+ }, "value must not be larger than max");
+
+ test(function() {
+ var e = document.getElementById('meter_default_low_and_high_1');
+ assert_array_equals([e.low,e.high], [-12.3,3.4]);
+ }, "default low and high values equal min and max, respectively");
+
+ test(function() {
+ var e = document.getElementById('meter_default_low_and_high_2');
+ assert_array_equals([e.low,e.high], [0,1.0]);
+ }, "default low and high values equal 0 and 1.0 respectively, if both low and high are not specified");
+
+ test(function() {
+ var e = document.getElementById('meter_low_smaller_than_min');
+ assert_array_equals([e.low,e.min,e.value], [12.3,12.3,12.3]);
+ }, "low must not be smaller than min");
+
+ test(function() {
+ var e = document.getElementById('meter_low_larger_than_max');
+ assert_array_equals([e.low,e.max,e.value], [-34.5,-34.5,-34.5]);
+ }, "low must not be larger than max");
+
+ test(function() {
+ var e = document.getElementById('meter_high_smaller_than_min');
+ assert_array_equals([e.high,e.min,e.value], [12.3,12.3,12.3]);
+ }, "high must not be smaller than min");
+
+ test(function() {
+ var e = document.getElementById('meter_high_larger_than_max');
+ assert_array_equals([e.high,e.max,e.value], [-34.5,-34.5,-34.5]);
+ }, "high must not be larger than max");
+
+ test(function() {
+ var e = document.getElementById('meter_low_without_min');
+ assert_array_equals([e.low,e.min,e.value], [0,0,0]);
+ }, "If min is not specified, low must not be smaller than default value of min (i.e. 0)");
+
+ test(function() {
+ var e = document.getElementById('meter_high_smaller_than_low');
+ assert_array_equals([e.low,e.high,e.value], [-10.3,-10.3,-9]);
+ }, "If a value smaller than low is given to high, it must be set to the same value as low");
+
+ test(function() {
+ var e = document.getElementById('meter_high_without_max');
+ assert_array_equals([e.high,e.value], [1.0,1.0]);
+ }, "If max is not specified, high must not be larger than default value of max (i.e. 1.0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_optimum_smaller_than_min').optimum, 0);
+ }, "optimum smaller than min");
+
+ test(function() {
+ var e = document.getElementById('meter_optimum_smaller_than_min');
+ assert_array_equals([e.min,e.value], [0,0]);
+ }, "optimum (smaller than min) must not affect min and the actual value");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_optimum_larger_than_max').optimum, 1.0);
+ }, "optimum smaller than max");
+
+ test(function() {
+ var e = document.getElementById('meter_optimum_larger_than_max');
+ assert_array_equals([e.max,e.value], [1.0,1.0]);
+ }, "optimum (larger than max) must not affect max and the actual value");
+
+ test(function() {
+ var e = document.getElementById('meter_default_optimum');
+ assert_equals(e.optimum, (e.max + e.min) / 2);
+ }, "default optimum value is the midpoint between min and max");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-optgroup-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-optgroup-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-optgroup-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-optgroup-element/optgroup-disabled-manual.html b/testing/web-platform/tests/html/semantics/forms/the-optgroup-element/optgroup-disabled-manual.html
new file mode 100644
index 000000000..ca8c6cda8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-optgroup-element/optgroup-disabled-manual.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLOptGroupElement Test: disabled</title>
+<meta name="flags" content="interact">
+<link rel="author" title="Intel" href="http://www.intel.com/">
+
+<form>
+ <select>
+ <optgroup label="8.01" disabled>
+ <option value="8.01.1">Lecture 01: Powers of Ten</option>
+ <option value="8.01.2">Lecture 02: 1D Kinematics</option>
+ <option value="8.01.3">Lecture 03: Vectors</option>
+ </optgroup>
+ <optgroup label="8.02">
+ <option value="8.02.1">Lecture 01: What holds our world together?</option>
+ <option value="8.02.2">Lecture 02: Electric Field</option>
+ <option value="8.02.3">Lecture 03: Electric Flux</option>
+ </optgroup>
+ </select>
+</form>
+
+<h2>Description</h2>
+<p>
+ This test validates that an optgroup element is disabled if its disabled attribute is present.
+</p>
+
+<h2>Test steps:</h2>
+<ol>
+ <li>
+ Click the select flag to select section '8.01'
+ </li>
+</ol>
+
+<h2>Result:</h2>
+<p>Click the select flag and try to select section 8.01, test passes if the section 8.01 is disable to be selected</p>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-option-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-disabled-manual.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-disabled-manual.html
new file mode 100644
index 000000000..25dfcc87a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-disabled-manual.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLOptionElement Test: disabled</title>
+<meta name="flags" content="interact">
+<link rel="author" title="Intel" href="http://www.intel.com/">
+
+<div>
+ <select>
+ <option id="testOption1" text="Option1" >Option1</option>
+ <option id="testOption2" disabled >Option2</option>
+ <option id="testOption3" >Option3</option>
+ </select>
+</div>
+
+<h2>Description</h2>
+<p>
+ This test validates that an option element is disabled if its disabled attribute is present.
+</p>
+
+<h2>Test steps:</h2>
+<ol>
+ <li>
+ Click the select flag to select 'Option2'
+ </li>
+</ol>
+
+<h2>Result:</h2>
+<p>Test passes if not able to select 'Option2'</p>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-form.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-form.html
new file mode 100644
index 000000000..1a68b5c1c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-form.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.form</title>
+<link rel=author title="Sergey Alexandrov" href="mailto:splavgm@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-form">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<form id="form">
+ <select id="select">
+ <optgroup id="optgroup"></optgroup>
+ </select>
+</form>
+<div id=log></div>
+
+<script>
+test(function () {
+ var form = document.getElementById("form");
+ var select = document.getElementById("select");
+ var optgroup = document.getElementById("optgroup");
+
+ var o1 = document.createElement("option");
+ assert_equals(o1.form, null);
+
+ select.appendChild(o1);
+ assert_equals(o1.form, select.form);
+
+ var o2 = document.createElement("option");
+ select.appendChild(o2);
+ assert_equals(o2.form, select.form);
+
+}, "form");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-label-value.js b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-label-value.js
new file mode 100644
index 000000000..5c453f173
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-label-value.js
@@ -0,0 +1,82 @@
+function test_option(member) {
+ test(function() {
+ var option = document.createElement("option");
+ assert_equals(option[member], "");
+ }, "No children, no " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.setAttribute(member, "")
+ assert_equals(option[member], "");
+ }, "No children, empty " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.setAttribute(member, member)
+ assert_equals(option[member], member);
+ }, "No children, " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.setAttributeNS("http://www.example.com/", member, member)
+ assert_equals(option[member], "");
+ }, "No children, namespaced " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ assert_equals(option[member], "child");
+ }, "Single child, no " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.setAttribute(member, "")
+ assert_equals(option[member], "");
+ }, "Single child, empty " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.setAttribute(member, member)
+ assert_equals(option[member], member);
+ }, "Single child, " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.setAttributeNS("http://www.example.com/", member, member)
+ assert_equals(option[member], "child");
+ }, "Single child, namespaced " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.appendChild(document.createTextNode(" node "));
+ assert_equals(option[member], "child node");
+ }, "Two children, no " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.appendChild(document.createTextNode(" node "));
+ option.setAttribute(member, "")
+ assert_equals(option[member], "");
+ }, "Two children, empty " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.appendChild(document.createTextNode(" node "));
+ option.setAttribute(member, member)
+ assert_equals(option[member], member);
+ }, "Two children, " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.appendChild(document.createTextNode(" node "));
+ option.setAttributeNS("http://www.example.com/", member, member)
+ assert_equals(option[member], "child node");
+ }, "Two children, namespaced " + member);
+}
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-label.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-label.html
new file mode 100644
index 000000000..f931b9622
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-label.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.label</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-label">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=option-label-value.js></script>
+<div id=log></div>
+<script>
+test_option("label")
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-selected.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-selected.html
new file mode 100644
index 000000000..e18e90b85
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-selected.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.selected</title>
+<link rel=author title="Corey Farwell" href="mailto:coreyf@rwell.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-selected">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<script>
+test(function () {
+ var elem = document.createElement("option");
+ assert_equals(elem.selected, false);
+
+ elem.setAttribute("selected", "");
+ assert_equals(elem.selected, true);
+
+ elem.removeAttribute("selected");
+ assert_equals(elem.selected, false);
+
+ elem.defaultSelected = true
+ assert_equals(elem.selected, true);
+
+ elem.defaultSelected = false;
+ assert_equals(elem.selected, false);
+}, "not dirty");
+
+test(function () {
+ testDirty(true);
+}, "dirty, selected");
+
+test(function () {
+ testDirty(false);
+}, "dirty, not selected");
+
+function testDirty(isSelected) {
+ var elem = document.createElement("option");
+
+ elem.selected = isSelected; // After this assignment, dirtiness=true
+ assertDirty(elem, isSelected);
+
+ elem.selected = !isSelected; // Change the value, still dirty
+ assertDirty(elem, !isSelected);
+};
+
+function assertDirty(elem, expect) {
+ assert_equals(elem.selected, expect);
+
+ elem.setAttribute("selected", "");
+ assert_equals(elem.selected, expect);
+
+ elem.removeAttribute("selected");
+ assert_equals(elem.selected, expect);
+
+ elem.defaultSelected = true;
+ assert_equals(elem.selected, expect);
+
+ elem.defaultSelected = false;
+ assert_equals(elem.selected, expect);
+}
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-backslash.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-backslash.html
new file mode 100644
index 000000000..34bd0d368
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-backslash.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<meta charset=EUC-JP>
+<title>Test for the backslash sign in option.text</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<select id=test><option>\</option></select>
+<script>
+test(function() {
+ var select = document.getElementById("test");
+ var option = select.firstChild;
+ assert_equals(option.text, "\\");
+ assert_equals(option.textContent, "\\");
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-label.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-label.html
new file mode 100644
index 000000000..9259aecf3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-label.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.text</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var option = document.createElement("option");
+ option.setAttribute("label", "label");
+ option.textContent = "text";
+ assert_equals(option.text, "text");
+}, "Option with non-empty label.");
+
+test(function() {
+ var option = document.createElement("option");
+ option.setAttribute("label", "");
+ option.textContent = "text";
+ assert_equals(option.text, "text");
+}, "Option with empty label.");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-recurse.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-recurse.html
new file mode 100644
index 000000000..cf854f526
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-recurse.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.text</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createElement("font"))
+ .appendChild(document.createTextNode(" font "));
+ assert_equals(option.text, "font");
+}, "option.text should recurse");
+
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElement("script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before after");
+}, "option.text should not recurse into HTML script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before after");
+}, "option.text should not recurse into SVG script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before script after");
+}, "option.text should recurse into MathML script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS(null, "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before script after");
+}, "option.text should recurse into null script elements");
+test(function() {
+ var option = document.createElement("option");
+ var span = option.appendChild(document.createElement("span"));
+ span.appendChild(document.createTextNode(" Some "));
+ span.appendChild(document.createElement("script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" Text "));
+ assert_equals(option.text, "Some Text");
+}, "option.text should work if a child of the option ends with a script");
+
+test(function() {
+ var script = document.createElement("script");
+ var option = script.appendChild(document.createElement("option"));
+ option.appendChild(document.createTextNode("text"));
+ assert_equals(option.text, "text");
+}, "option.text should work if the option is in an HTML script element");
+test(function() {
+ var script = document.createElementNS("http://www.w3.org/2000/svg", "script");
+ var option = script.appendChild(document.createElement("option"));
+ option.appendChild(document.createTextNode("text"));
+ assert_equals(option.text, "text");
+}, "option.text should work if the option is in an SVG script element");
+test(function() {
+ var script = document.createElementNS("http://www.w3.org/1998/Math/MathML", "script");
+ var option = script.appendChild(document.createElement("option"));
+ option.appendChild(document.createTextNode("text"));
+ assert_equals(option.text, "text");
+}, "option.text should work if the option is in a MathML script element");
+
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode("te"));
+ option.appendChild(document.createComment("comment"));
+ option.appendChild(document.createTextNode("xt"));
+ assert_equals(option.text, "text");
+}, "option.text should ignore comment children");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode("te"));
+ option.appendChild(document.createProcessingInstruction("target", "data"));
+ option.appendChild(document.createTextNode("xt"));
+ assert_equals(option.text, "text");
+}, "option.text should ignore PI children");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-spaces.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-spaces.html
new file mode 100644
index 000000000..2c712655a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-text-spaces.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.text</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var spaces = ["\u0020", "\u0009", "\u000A", "\u000C", "\u000D"];
+ spaces.forEach(function(space) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = space + "text";
+ assert_equals(option.text, "text");
+ }, "option.text should strip leading space characters (" +
+ format_value(space) + ")");
+ });
+ spaces.forEach(function(space) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "text" + space;
+ assert_equals(option.text, "text");
+ }, "option.text should strip trailing space characters (" +
+ format_value(space) + ")");
+ });
+ spaces.forEach(function(space) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = space + "text" + space;
+ assert_equals(option.text, "text");
+ }, "option.text should strip leading and trailing space characters (" +
+ format_value(space) + ")");
+ });
+ spaces.forEach(function(space) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "before" + space + "after";
+ assert_equals(option.text, "before after");
+ }, "option.text should replace single internal space characters (" +
+ format_value(space) + ")");
+ });
+ spaces.forEach(function(space1) {
+ spaces.forEach(function(space2) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "before" + space1 + space2 + "after";
+ assert_equals(option.text, "before after");
+ }, "option.text should replace multiple internal space characters (" +
+ format_value(space1) + ", " + format_value(space2) + ")");
+ });
+ });
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "\u00a0text";
+ assert_equals(option.text, "\u00a0text");
+ }, "option.text should leave leading NBSP alone.");
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "text\u00a0";
+ assert_equals(option.text, "text\u00a0");
+ }, "option.text should leave trailing NBSP alone.");
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "before\u00a0after";
+ assert_equals(option.text, "before\u00a0after");
+ }, "option.text should leave a single internal NBSP alone.");
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "before\u00a0\u00a0after";
+ assert_equals(option.text, "before\u00a0\u00a0after");
+ }, "option.text should leave two internal NBSPs alone.");
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-option-element/option-value.html b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-value.html
new file mode 100644
index 000000000..cccdc3748
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-option-element/option-value.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.value</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-label">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=option-label-value.js></script>
+<div id=log></div>
+<script>
+test_option("value")
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-output-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-output-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-output-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-output-element/output.html b/testing/web-platform/tests/html/semantics/forms/the-output-element/output.html
new file mode 100644
index 000000000..7682703fa
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-output-element/output.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>The output element</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-output-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<output id=output></output>
+<script>
+ var output = document.getElementById("output");
+
+ test(function(){
+ assert_equals(output.type, "output", "type must return the string 'output'");
+ assert_equals(output.textContent, "", "textContent is empty");
+ assert_equals(output.value, "", "value should be empty");
+ assert_equals(output.defaultValue, "", "defaultValue should be empty");
+
+ output.textContent="5";
+ assert_equals(output.value, "5", "textContent is set to 5: value is updated");
+ assert_equals(output.textContent, "5", "textContent is set to 5");
+ assert_equals(output.defaultValue, "5", "textContent is set to 5: defaultValue is updated");
+
+ output.defaultValue="10"; // value mode flag is in "default" mode. Setting defaultValue should set textContent as well
+ assert_equals(output.value, "10", "defaultValue is set to 10: value is updated");
+ assert_equals(output.textContent, "10", "defaultValue is set to 10: textContent is updated");
+ assert_equals(output.defaultValue, "10", "defaultValue is set to 10");
+
+ output.value="20"; // set the value mode flag to "value": default value remains unchanged
+ assert_equals(output.value, "20", "value is set to 20");
+ assert_equals(output.textContent, "20", "value is set to 20: textContent is updated");
+ assert_equals(output.defaultValue, "10", "value is set to 20: defaultValue remains unchanged");
+
+ output.defaultValue="15"; // value mode flag is in "value" mode. textContent remains unchanged when setting defaultValue
+ assert_equals(output.value, "20", "defaultValue is set to 15: value remains unchanged");
+ assert_equals(output.textContent, "20", "defaultValue is set to 15: textContent remains unchanged");
+ assert_equals(output.defaultValue, "15", "defaultValue is set to 15");
+ }, "output value and defaultValue");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-progress-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-progress-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-progress-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-progress-element/progress-2.html b/testing/web-platform/tests/html/semantics/forms/the-progress-element/progress-2.html
new file mode 100644
index 000000000..ebc475062
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-progress-element/progress-2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Progress Element Tests</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-progress-element" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <progress id="p00" style="display: none"></progress>
+ <progress id="p01" max="5.5" value=".5" style="display: none"></progress>
+ <script>
+ test(function () {
+ assert_equals(document.getElementById('p00').position, -1);
+ }, "progress position equals -1");
+
+ test(function () {
+ assert_equals(document.getElementById('p00').value, 0);
+ }, "progress value equals 0");
+
+ test(function () {
+ assert_equals(document.getElementById('p01').value, .5);
+ }, "progress value equals .5");
+
+ test(function () {
+ document.getElementById('p00').value = document.getElementById('p00').value;
+ assert_equals(document.getElementById('p00').position, 0);
+ }, "progress position equals 0");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-progress-element/progress.html b/testing/web-platform/tests/html/semantics/forms/the-progress-element/progress.html
new file mode 100644
index 000000000..0c176d8ea
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-progress-element/progress.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>The progress element</title>
+
+ <link rel="author" title="dan smith" href="mailto:XX1011@gmail.com">
+ <link rel="author" title="Tomoyuki SHIMIZU" href="mailto:tomoyuki.labs@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-progress-element">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <progress id="indeterminate"></progress>
+ <progress id="removevalue" value="0.5"></progress>
+ <progress id="quarter" value="1" max="4"></progress>
+ <progress id="largerthanmax" value="2"></progress>
+ <progress id="invalidmax" value="1" max="a"></progress>
+ <progress id="negativemax" value="1" max="-1"></progress>
+ <progress id="invalidvalue" value="a"></progress>
+ <progress id="negativevalue" value="-1"></progress>
+
+ <script>
+
+ test(function() {
+ assert_equals(indeterminate.position, -1);
+ }, "Indeterminate progress bar should have position -1");
+
+ test(function() {
+ removevalue.removeAttribute('value');
+ assert_equals(removevalue.position, -1);
+ }, "Revoming the value attribute makes an intermediate progress bar, which should have position -1");
+
+ test(function() {
+ assert_equals(quarter.position, quarter.value / quarter.max);
+ }, "Determinate progress bar should have fractional position");
+
+ test(function() {
+ assert_equals(indeterminate.value, 0);
+ }, "Indeterminate progress bar should have value 0");
+
+ test(function() {
+ assert_array_equals(largerthanmax.value, 1);
+ }, "Value must equal max if the parsed value is larger than max");
+
+ test(function() {
+ assert_equals(indeterminate.max, 1);
+ }, "Max must be 1 by default");
+
+ test(function() {
+ assert_array_equals(largerthanmax.max, 1);
+ }, "Max must be 1 by default, even if value is specified");
+
+ test(function() {
+ assert_equals(invalidmax.max, 1);
+ }, "Max must be 1 if max value is invalid");
+
+ test(function() {
+ assert_equals(negativemax.max, 1);
+ }, "Max must be 1 if the parsed max value is less than or equal to zero");
+
+ test(function() {
+ assert_equals(invalidvalue.value, 0);
+ }, "Value must be 0 if value is invalid");
+
+ test(function() {
+ assert_equals(negativevalue.value, 0);
+ }, "Value must be 0 if the parsed value is less than or equal to zero");
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-select-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection-namedItem.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection-namedItem.html
new file mode 100644
index 000000000..c5c8510a4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection-namedItem.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title id='title'>HTMLOptionsCollection</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<select id="selly">
+ <option id="id1" name="name1">1</option>
+ <option id="id2" name="name2">2</option>
+ <option id="id3" name="name3">3</option>
+ <option id="id4" name="name4">4</option>
+ <option name="nameonly">nameonly</option>
+ <option id="id3">duplicate ID</option>
+ <option name="name4">duplicate name</option>
+ <option id="mixed1">mixed ID</option>
+ <option name="mixed1">mixed name</option>
+</select>
+
+<script>
+var selly;
+setup(function() {
+ selly = document.getElementById('selly');
+});
+
+test(function () {
+ assert_equals(selly.namedItem('nameonly')["value"], "nameonly");
+}, "if only one item has a *name* or id value matching the parameter, return that object and stop");
+
+test(function () {
+ assert_equals(selly.namedItem('id2')["value"], "2");
+}, "if only one item has a name or *id* value matching the parameter, return that object and stop");
+
+test(function () {
+ assert_equals(selly.namedItem('thisdoesnotexist'), null);
+}, "if no item has a name or id value matching the parameter, return null and stop");
+
+test(function () {
+ assert_equals(selly.namedItem('id3')["value"], "3");
+}, "if multiple items have a name or *id* value matching the parameter, return the first object and stop");
+
+test(function () {
+ assert_equals(selly.namedItem('name4')["value"], "4");
+}, "if multiple items have a *name* or id value matching the parameter, return the first object and stop");
+
+test(function () {
+ assert_equals(selly.namedItem('mixed1')["value"], "mixed ID");
+}, "if multiple items have a *name* or *id* value matching the parameter, return the first object and stop");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html
new file mode 100644
index 000000000..6bae66ccf
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title id='title'>HTMLOptionsCollection</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<select id="selly">
+ <option>1</option>
+ <option>2</option>
+ <option>3</option>
+ <option>4</option>
+</select>
+
+<script>
+var selly;
+setup(function() {
+ selly = document.getElementById('selly');
+});
+
+test(function () {
+ assert_equals(selly.length, 4);
+}, "On getting, the length attribute must return the number of nodes represented by the collection.");
+
+test(function () {
+ selly.length = 7;
+ assert_equals(selly.length, 7,
+ "Number of nodes in collection should have changed");
+ assert_equals(selly.children.length, 7,
+ "Number of children should have changed");
+ for (var i = 4; i < 7; ++i) {
+ var child = selly.children[i];
+ assert_equals(child.localName, "option",
+ "new child should be an option");
+ assert_equals(child.namespaceURI, "http://www.w3.org/1999/xhtml",
+ "new child should be an HTML element");
+ assert_equals(child.attributes.length, 0,
+ "new child should not have attributes");
+ assert_equals(child.childNodes.length, 0,
+ "new child should not have child nodes");
+ }
+}, "Changing the length adds new nodes; The number of new nodes = new length minus old length");
+
+test(function () {
+ var elarray = [];
+ for (var i = 0; i < selly.length; i++) {
+ elarray.push(selly[i].value);
+ }
+ assert_array_equals(elarray, ["1", "2", "3", "4", "", "", ""]);
+}, "New nodes have no value");
+
+test(function () {
+ selly.length = 7;
+ assert_equals(selly.length, 7,
+ "Number of nodes in collection should not have changed");
+ assert_equals(selly.children.length, 7,
+ "Number of children should not have changed");
+}, "Setting a length equal to existing length changes nothing");
+
+test(function () {
+ selly.length = 4;
+ assert_equals(selly[6], undefined,
+ "previously set node is now undefined");
+ assert_equals(selly.length, 4,
+ "Number of nodes in collection is correctly changed");
+ assert_equals(selly.children.length, 4,
+ "Number of children should have changed");
+}, "Setting a length lower than the old length trims nodes from the end");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-ask-for-reset.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-ask-for-reset.html
new file mode 100644
index 000000000..822114fb2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-ask-for-reset.html
@@ -0,0 +1,97 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLSelectElement ask for reset</title>
+<link rel="author" title="Dongie Agnir" href="dongie.agnir@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var select = makeSelect(5);
+
+ select.children[4].selected = true;
+ unselectedExcept(select, 4);
+
+ select.children[4].remove();
+ unselectedExcept(select, 0); // remove selected node, should default to first
+
+ select.children[3].selected = true;
+
+ select.children[0].remove();
+ unselectedExcept(select, 2); // last node still selected
+
+ select.size = 2;
+ select.children[2].remove();
+
+ unselectedExcept(select, null);
+}, "ask for reset on node remove, non multiple.");
+
+test(function() {
+ var select = makeSelect(3);
+ select.children[1].selected = true;
+
+ // insert selected option, should remain selected
+ var opt4 = document.createElement("option");
+ opt4.selected = true;
+ select.appendChild(opt4);
+ unselectedExcept(select, 3);
+
+ // insert unselected, 3 should remain selected
+ var opt5 = document.createElement("option");
+ select.appendChild(opt5);
+ unselectedExcept(select, 3);
+}, "ask for reset on node insert, non multiple.");
+
+test(function() {
+ var select = makeSelect(3);
+
+ var options = select.children;
+
+ // select options from first to last
+ for (var i = 0; i < options.length; ++i) {
+ options[i].selected = true;
+ unselectedExcept(select, i);
+ }
+
+ // select options from last to first
+ for (var i = options.length - 1; i >= 0; --i) {
+ options[i].selected = true;
+ unselectedExcept(select, i);
+ }
+
+ options[2].selected = true;
+ options[2].selected = false; // none selected
+ unselectedExcept(select, 0);
+
+ // disable first so option at index 1 is first eligible
+ options[0].disabled = true;
+ options[2].selected = true;
+ options[2].selected = false; // none selected
+ unselectedExcept(select, 1);
+
+ select.size = 2;
+ options[1].selected = false;
+ unselectedExcept(select, null); // size > 1 so should not default to any
+}, "change selectedness of option, non multiple.");
+
+
+function unselectedExcept(sel, opt) {
+ for (var i = 0; i < sel.children.length; ++i) {
+ if (i != opt) {
+ assert_false(sel.children[i].selected, "option should not be selected.");
+ }
+ if (opt != null) {
+ assert_true(sel.children[opt].selected, "option should be selected.");
+ }
+ }
+}
+
+function makeSelect(n) {
+ var sel = document.createElement("select");
+ for (var i = 0; i < n; ++i) {
+ opt = document.createElement("option");
+ sel.appendChild(opt);
+ }
+ return sel;
+}
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-named-getter.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-named-getter.html
new file mode 100644
index 000000000..da43da9d9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-named-getter.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Absence of a named getter on HTMLSelectElement</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<select id=select>
+ <option id=op1>A</option>
+ <option name=op2>B</option>
+ <option id=op3 name=op4>C</option>
+ <option id=>D</option>
+ <option name=>D</option>
+</select>
+<script>
+test(function() {
+ var select = document.getElementById("select");
+ assert_equals(select.op1, undefined);
+ assert_false("op1" in select);
+ assert_equals(select.namedItem("op1"), select.children[0]);
+}, "Option with id")
+
+test(function() {
+ var select = document.getElementById("select");
+ assert_equals(select.op2, undefined);
+ assert_false("op2" in select);
+ assert_equals(select.namedItem("op2"), select.children[1]);
+}, "Option with name")
+
+test(function() {
+ var select = document.getElementById("select");
+ assert_equals(select.op3, undefined);
+ assert_false("op3" in select);
+ assert_equals(select.namedItem("op3"), select.children[2]);
+
+ assert_equals(select.op4, undefined);
+ assert_false("op4" in select);
+ assert_equals(select.namedItem("op4"), select.children[2]);
+}, "Option with name and id")
+
+test(function() {
+ var select = document.getElementById("select");
+ assert_equals(select[""], undefined);
+ assert_false("" in select);
+ assert_equals(select.namedItem(""), null);
+}, "Empty string name");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-remove.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-remove.html
new file mode 100644
index 000000000..cf2128bd1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-remove.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLSelectElement.remove</title>
+<link rel="author" title="Ms2ger" href="Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-childnode-remove">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-select-remove">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-htmloptionscollection-remove">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function testRemove(getter, desc) {
+ test(function() {
+ var div = document.createElement("div");
+ var select = document.createElement("select");
+ div.appendChild(select);
+ assert_equals(select.parentNode, div);
+
+ var options = [];
+ for (var i = 0; i < 3; ++i) {
+ var option = document.createElement("option");
+ option.textContent = String(i);
+ select.appendChild(option);
+ options.push(option);
+ }
+
+ getter(select).remove(-1);
+ assert_array_equals(select.options, options, "After remove(-1)");
+ assert_equals(select.parentNode, div);
+
+ getter(select).remove(3);
+ assert_array_equals(select.options, options, "After remove(3)");
+ assert_equals(select.parentNode, div);
+
+ getter(select).remove(0);
+ assert_array_equals(select.options, [options[1], options[2]], "After remove(0)");
+ assert_equals(select.parentNode, div);
+ }, desc)
+}
+testRemove(function(select) { return select; }, "select.remove(n) should work");
+testRemove(function(select) { return select.options; }, "select.options.remove(n) should work");
+test(function() {
+ var div = document.createElement("div");
+ var select = document.createElement("select");
+ div.appendChild(select);
+ assert_equals(select.parentNode, div);
+ assert_equals(div.firstChild, select);
+
+ select.remove();
+ assert_equals(select.parentNode, null);
+ assert_equals(div.firstChild, null);
+}, "remove() should work on select elements.")
+test(function() {
+ var div = document.createElement("div");
+ var select = document.createElement("select");
+ div.appendChild(select);
+ assert_equals(select.parentNode, div);
+ assert_equals(div.firstChild, select);
+
+ Element.prototype.remove.call(select);
+ assert_equals(select.parentNode, null);
+ assert_equals(div.firstChild, null);
+}, "Element#remove() should work on select elements.")
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/.gitkeep b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/.gitkeep
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/cloning-steps.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/cloning-steps.html
new file mode 100644
index 000000000..7a85bd26a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/cloning-steps.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Cloning of textarea elements</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-node-clonenode">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-node-clone">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-node-clone-ext">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#the-textarea-element:concept-node-clone-ext">
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+"use strict";
+
+test(function() {
+ var textarea = document.createElement("textarea");
+ textarea.value = "foo bar";
+
+ var copy = textarea.cloneNode();
+ assert_equals(copy.value, "foo bar");
+}, "textarea element's value should be cloned");
+
+test(function() {
+ var textarea = document.createElement("textarea");
+ textarea.value = "foo bar";
+
+ var copy = textarea.cloneNode();
+ copy.setAttribute("value", "something else");
+
+ assert_equals(copy.value, "foo bar");
+}, "textarea element's dirty value flag should be cloned, so setAttribute doesn't affect the cloned textarea's value");
+
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html
new file mode 100644
index 000000000..d69195b4f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML Test reference: newline in &lt;textarea&gt; separates bidi paragraphs</title>
+ <link rel="author" title="Amir E. Aharoni" href="mailto:amir.aharoni@mail.huji.ac.il"/>
+ <link rel="author" title="Eyal Sela" href="mailto:eyal@post.isoc.org.il"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-textarea-element"/>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the rightmost character in the first line below is a full stop and to the left of it is a Hebrew letter.</p></div>
+ <div class="test">
+ <textarea cols="70" rows="3">
+A Hebrew letter and a full stop: &#x05d0;.&lrm;
+&#x05d0; this line begins with a Hebrew letter.
+ </textarea>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html
new file mode 100644
index 000000000..ce1ff944c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: newline in &lt;textarea&gt; separates bidi paragraphs</title>
+ <link rel="match" href="textarea-newline-bidi-ref.html" />
+ <link rel="author" title="Amir E. Aharoni" href="mailto:amir.aharoni@mail.huji.ac.il"/>
+ <link rel="author" title="Eyal Sela" href="mailto:eyal@post.isoc.org.il"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-textarea-element"/>
+ <meta name="assert"
+ content="A newline in a textarea element, and in its raw value, should separate paragraphs for the purposes of the Unicode bidirectional algorithm."/>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the rightmost character in the first line below is a full stop and to the left of it is a Hebrew letter.</p></div>
+ <div class="test">
+ <textarea cols="70" rows="3">
+A Hebrew letter and a full stop: &#x05d0;.
+&#x05d0; this line begins with a Hebrew letter.
+ </textarea>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-placeholder-manual.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-placeholder-manual.html
new file mode 100644
index 000000000..d59a25941
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-placeholder-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: textarea - placeholder attribute</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-textarea-placeholder">
+<meta name="flags" content="interact">
+<body>
+ <p>
+ Test passes if there is a "Placeholder Text" in the text area,
+ and if the "Placeholder Text" disappears after type in any character.
+ </p>
+ <textarea placeholder="Placeholder Text"></textarea>
+</body>
+
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-select-event-manual.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-select-event-manual.html
new file mode 100644
index 000000000..f1679e280
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-select-event-manual.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLTextAreaElement Test: select event</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<p>Select any numberic characters in the text area below</p>
+
+<form id="testForm" name="testForm">
+ <textarea id="testtextarea">0123456789</textarea>
+</form>
+
+<script>
+
+var textarea = document.getElementById("testtextarea");
+
+setup({explicit_done : true});
+setup({explicit_timeout : true});
+
+on_event(textarea, "select", function(evt) {
+ test(function() {
+ assert_greater_than(textarea.value.substring(textarea.selectionStart, textarea.selectionEnd).length, 0, "Check if select event captured when text selected");
+ });
+ done();
+});
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-select-manual.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-select-manual.html
new file mode 100644
index 000000000..4e98ba509
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-select-manual.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLTextAreaElement Test: select()</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<meta name="flags" content="interact">
+
+<p>Test passes if content of the input area is selected</p>
+
+<textarea id="test_obj">1234567</textarea>
+<script>
+var textarea = document.querySelector("#test_obj");
+textarea.select();
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-type.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-type.html
new file mode 100644
index 000000000..ac80f9365
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/textarea-type.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<title>The type IDL attribute</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-textarea-type">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="test">
+<textarea></textarea>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementById("test")
+ .getElementsByTagName("textarea")[0].type,
+ "textarea");
+}, "Textarea's type attribute should return 'textarea'");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1-ref.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1-ref.html
new file mode 100644
index 000000000..98a7f8a3a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<title>Dynamic manipulation of textarea.wrap</title>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#dom-textarea-wrap>
+<link rel=author title=Ms2ger href=mailto:ms2ger@gmail.com>
+<textarea wrap=soft cols=20>01234567890 01234567890 01234567890</textarea>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1a.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1a.html
new file mode 100644
index 000000000..b3baa79d7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1a.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Dynamic manipulation of textarea.wrap</title>
+<link rel=match href=wrap-reflect-1-ref.html>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#dom-textarea-wrap>
+<link rel=author title=Ms2ger href=mailto:ms2ger@gmail.com>
+<textarea wrap=off cols=20>01234567890 01234567890 01234567890</textarea>
+<script>
+document.getElementsByTagName("textarea")[0].wrap = "soft";
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1b.html b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1b.html
new file mode 100644
index 000000000..b0a9b460f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-textarea-element/wrap-reflect-1b.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Dynamic manipulation of textarea.wrap</title>
+<link rel=match href=wrap-reflect-1-ref.html>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#dom-textarea-wrap>
+<link rel=author title=Ms2ger href=mailto:ms2ger@gmail.com>
+<textarea wrap=off cols=20>01234567890 01234567890 01234567890</textarea>
+<script>
+document.getElementsByTagName("textarea")[0].setAttribute("wrap", "soft");
+</script>