mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 17:25:36 +00:00
Backed out changeset 97fa9c6849ff (bug 1504418) for ES Lint failure CLOSED TREE
This commit is contained in:
parent
0526004d2d
commit
3e61f0ac55
@ -11,14 +11,12 @@ DIRS += ['input']
|
||||
|
||||
MOCHITEST_MANIFESTS += [
|
||||
'test/forms/mochitest.ini',
|
||||
'test/forms/xbl/mochitest.ini',
|
||||
'test/mochitest.ini',
|
||||
]
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += [
|
||||
'test/chrome.ini',
|
||||
'test/forms/chrome.ini',
|
||||
'test/forms/xbl/chrome.ini',
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
@ -1,4 +0,0 @@
|
||||
[DEFAULT]
|
||||
prefs = dom.ua_widget.enabled=false
|
||||
|
||||
[test_autocompleteinfo.html]
|
@ -1,40 +0,0 @@
|
||||
[DEFAULT]
|
||||
prefs =
|
||||
dom.ua_widget.enabled=false
|
||||
support-files =
|
||||
!/dom/html/test/reflect.js
|
||||
../FAIL.html
|
||||
../PASS.html
|
||||
|
||||
[test_input_attributes_reflection.html]
|
||||
[test_input_date_bad_input.html]
|
||||
[test_input_date_key_events.html]
|
||||
[test_input_datetime_input_change_events.html]
|
||||
[test_input_datetime_focus_blur.html]
|
||||
[test_input_datetime_focus_blur_events.html]
|
||||
[test_input_datetime_focus_state.html]
|
||||
[test_input_datetime_tabindex.html]
|
||||
[test_input_defaultValue.html]
|
||||
[test_input_sanitization.html]
|
||||
skip-if = os == 'android' && debug # Extremely slow on debug android
|
||||
[test_input_textarea_set_value_no_scroll.html]
|
||||
[test_input_time_key_events.html]
|
||||
[test_input_time_sec_millisec_field.html]
|
||||
[test_input_types_pref.html]
|
||||
[test_input_typing_sanitization.html]
|
||||
skip-if = os == "android" && debug # bug 1397615
|
||||
[test_label_input_controls.html]
|
||||
[test_max_attribute.html]
|
||||
[test_min_attribute.html]
|
||||
[test_mozistextfield.html]
|
||||
[test_novalidate_attribute.html]
|
||||
[test_pattern_attribute.html]
|
||||
[test_required_attribute.html]
|
||||
[test_step_attribute.html]
|
||||
[test_stepup_stepdown.html]
|
||||
[test_textarea_attributes_reflection.html]
|
||||
[test_validation.html]
|
||||
[test_valueAsDate_pref.html]
|
||||
[test_valueasdate_attribute.html]
|
||||
[test_valueasnumber_attribute.html]
|
||||
[test_validation_not_in_doc.html]
|
@ -1,171 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Test getAutocompleteInfo() on <input> and <select>
|
||||
-->
|
||||
<head>
|
||||
<title>Test for getAutocompleteInfo()</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/AddTask.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<form>
|
||||
<input id="input"/>
|
||||
<select id="select" />
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
var values = [
|
||||
// Missing or empty attribute
|
||||
[undefined, {}, ""],
|
||||
["", {}, ""],
|
||||
|
||||
// One token
|
||||
["on", {fieldName: "on" }, "on"],
|
||||
["On", {fieldName: "on" }, "on"],
|
||||
["off", {fieldName: "off" }, "off" ],
|
||||
["name", {fieldName: "name" }, "name"],
|
||||
[" name ", {fieldName: "name" }, "name"],
|
||||
["username", {fieldName: "username"}, ""],
|
||||
[" username ", {fieldName: "username"}, ""],
|
||||
["cc-csc", {fieldName: "cc-csc"}, ""],
|
||||
["language", {fieldName: "language"}, ""],
|
||||
["tel-extension", {fieldName: "tel-extension"}, ""],
|
||||
["foobar", {}, ""],
|
||||
["section-blue", {}, ""],
|
||||
|
||||
// Two tokens
|
||||
["on off", {}, ""],
|
||||
["off on", {}, ""],
|
||||
["username tel", {}, ""],
|
||||
["tel username ", {}, ""],
|
||||
[" username tel ", {}, ""],
|
||||
["tel mobile", {}, ""],
|
||||
["tel shipping", {}, ""],
|
||||
["shipping tel", {addressType: "shipping", fieldName: "tel"}, "shipping tel"],
|
||||
["shipPING tel", {addressType: "shipping", fieldName: "tel"}, "shipping tel"],
|
||||
["mobile tel", {contactType: "mobile", fieldName: "tel"}, "mobile tel"],
|
||||
[" MoBiLe TeL ", {contactType: "mobile", fieldName: "tel"}, "mobile tel"],
|
||||
["pager impp", {contactType: "pager", fieldName: "impp"}, ""],
|
||||
["fax tel-extension", {contactType: "fax", fieldName: "tel-extension"}, ""],
|
||||
["XXX tel", {}, ""],
|
||||
["XXX username", {}, ""],
|
||||
["name section-blue", {}, ""],
|
||||
["scetion-blue cc-name", {}, ""],
|
||||
["pager language", {}, ""],
|
||||
["fax url", {}, ""],
|
||||
["section-blue name", {section: "section-blue", fieldName: "name"}, "section-blue name"],
|
||||
["section-blue tel", {section: "section-blue", fieldName: "tel"}, "section-blue tel"],
|
||||
|
||||
// Three tokens
|
||||
["billing invalid tel", {}, ""],
|
||||
["___ mobile tel", {}, ""],
|
||||
["mobile foo tel", {}, ""],
|
||||
["mobile tel foo", {}, ""],
|
||||
["tel mobile billing", {}, ""],
|
||||
["billing mobile tel", {addressType: "billing", contactType: "mobile", fieldName: "tel"}, "billing mobile tel"],
|
||||
[" BILLing MoBiLE tEl ", {addressType: "billing", contactType: "mobile", fieldName: "tel"}, "billing mobile tel"],
|
||||
["billing home tel", {addressType: "billing", contactType: "home", fieldName: "tel"}, "billing home tel"],
|
||||
["home section-blue tel", {}, ""],
|
||||
["setion-blue work email", {}, ""],
|
||||
["section-blue home address-level2", {}, ""],
|
||||
["section-blue shipping name", {section: "section-blue", addressType: "shipping", fieldName: "name"}, "section-blue shipping name"],
|
||||
["section-blue mobile tel", {section: "section-blue", contactType: "mobile", fieldName: "tel"}, "section-blue mobile tel"],
|
||||
|
||||
// Four tokens
|
||||
["billing billing mobile tel", {}, ""],
|
||||
["name section-blue shipping home", {}, ""],
|
||||
["secti shipping work address-line1", {}, ""],
|
||||
["section-blue shipping home name", {}, ""],
|
||||
["section-blue shipping mobile tel", {section: "section-blue", addressType: "shipping", contactType: "mobile", fieldName: "tel"}, "section-blue shipping mobile tel"],
|
||||
|
||||
// Five tokens (invalid)
|
||||
["billing billing billing mobile tel", {}, ""],
|
||||
["section-blue section-blue billing mobile tel", {}, ""],
|
||||
];
|
||||
|
||||
var autocompleteInfoFieldIds = ["input", "select"];
|
||||
var autocompleteEnabledTypes = ["hidden", "text", "search", "url", "tel",
|
||||
"email", "password", "date", "time", "number",
|
||||
"range", "color"];
|
||||
var autocompleteDisabledTypes = ["reset", "submit", "image", "button", "radio",
|
||||
"checkbox", "file"];
|
||||
|
||||
function testInputTypes() {
|
||||
let field = document.getElementById("input");
|
||||
|
||||
for (var type of autocompleteEnabledTypes) {
|
||||
testAutocomplete(field, type, true);
|
||||
}
|
||||
|
||||
for (var type of autocompleteDisabledTypes) {
|
||||
testAutocomplete(field, type, false);
|
||||
}
|
||||
|
||||
// Clear input type attribute.
|
||||
field.removeAttribute("type");
|
||||
}
|
||||
|
||||
function testAutocompleteInfoValue(aEnabled) {
|
||||
for (var fieldId of autocompleteInfoFieldIds) {
|
||||
let field = document.getElementById(fieldId);
|
||||
|
||||
for (var test of values) {
|
||||
if (typeof(test[0]) === "undefined")
|
||||
field.removeAttribute("autocomplete");
|
||||
else
|
||||
field.setAttribute("autocomplete", test[0]);
|
||||
|
||||
var info = field.getAutocompleteInfo();
|
||||
if (aEnabled) {
|
||||
// We need to consider if getAutocompleteInfo() is valid,
|
||||
// but @autocomplete is invalid case, because @autocomplete
|
||||
// has smaller set of values.
|
||||
is(field.autocomplete, test[2], "Checking @autocomplete of: " + test[0]);
|
||||
}
|
||||
|
||||
is(info.section, "section" in test[1] ? test[1].section : "",
|
||||
"Checking autocompleteInfo.section for " + field + ": " + test[0]);
|
||||
is(info.addressType, "addressType" in test[1] ? test[1].addressType : "",
|
||||
"Checking autocompleteInfo.addressType for " + field + ": " + test[0]);
|
||||
is(info.contactType, "contactType" in test[1] ? test[1].contactType : "",
|
||||
"Checking autocompleteInfo.contactType for " + field + ": " + test[0]);
|
||||
is(info.fieldName, "fieldName" in test[1] ? test[1].fieldName : "",
|
||||
"Checking autocompleteInfo.fieldName for " + field + ": " + test[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testAutocomplete(aField, aType, aEnabled) {
|
||||
aField.type = aType;
|
||||
if (aEnabled) {
|
||||
ok(aField.getAutocompleteInfo() !== null, "getAutocompleteInfo shouldn't return null");
|
||||
} else {
|
||||
is(aField.getAutocompleteInfo(), null, "getAutocompleteInfo should return null");
|
||||
}
|
||||
}
|
||||
|
||||
// getAutocompleteInfo() should be able to parse all tokens as defined
|
||||
// in the spec regardless of whether dom.forms.autocomplete.formautofill pref
|
||||
// is on or off.
|
||||
add_task(async function testAutocompletePreferenceEnabled() {
|
||||
await SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.formautofill", true]]}, testInputTypes);
|
||||
testAutocompleteInfoValue(true);
|
||||
});
|
||||
|
||||
add_task(async function testAutocompletePreferenceDisabled() {
|
||||
await SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.formautofill", false]]}, testInputTypes);
|
||||
testAutocompleteInfoValue(false);
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,279 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for HTMLInputElement attributes reflection</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="../../reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for HTMLInputElement attributes reflection **/
|
||||
|
||||
// TODO: maybe make those reflections be tested against all input types.
|
||||
|
||||
function testWidthHeight(attr) {
|
||||
var element = document.createElement('input');
|
||||
is(element[attr], 0, attr + ' always returns 0 if not type=image');
|
||||
element.setAttribute(attr, '42');
|
||||
is(element[attr], 0, attr + ' always returns 0 if not type=image');
|
||||
is(element.getAttribute(attr), '42');
|
||||
element[attr] = 0;
|
||||
is(element.getAttribute(attr), '0', 'setting ' + attr + ' changes the content attribute');
|
||||
element[attr] = 12;
|
||||
is(element.getAttribute(attr), '12', 'setting ' + attr + ' changes the content attribute');
|
||||
|
||||
element.removeAttribute(attr);
|
||||
is(element.getAttribute(attr), null);
|
||||
|
||||
element = document.createElement('input');
|
||||
element.type = 'image';
|
||||
document.getElementById('content').appendChild(element);
|
||||
isnot(element[attr], 0, attr + ' represents the dimension of the element if type=image');
|
||||
|
||||
element.setAttribute(attr, '42');
|
||||
isnot(element[attr], 0, attr + ' represents the dimension of the element if type=image');
|
||||
isnot(element[attr], 42, attr + ' represents the dimension of the element if type=image');
|
||||
is(element.getAttribute(attr), '42');
|
||||
element[attr] = 0;
|
||||
is(element.getAttribute(attr), '0', 'setting ' + attr + ' changes the content attribute');
|
||||
element[attr] = 12;
|
||||
is(element.getAttribute(attr), '12', 'setting ' + attr + ' changes the content attribute');
|
||||
|
||||
element.removeAttribute(attr);
|
||||
is(element.getAttribute(attr), null);
|
||||
}
|
||||
|
||||
// .accept
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "accept",
|
||||
otherValues: [ "audio/*", "video/*", "image/*", "image/png",
|
||||
"application/msword", "appplication/pdf" ],
|
||||
});
|
||||
|
||||
// .alt
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "alt",
|
||||
});
|
||||
|
||||
// .autocomplete
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "autocomplete",
|
||||
validValues: [ "on", "off" ],
|
||||
invalidValues: [ "", "default", "foo", "tulip" ],
|
||||
});
|
||||
|
||||
// .autofocus
|
||||
reflectBoolean({
|
||||
element: document.createElement("input"),
|
||||
attribute: "autofocus",
|
||||
});
|
||||
|
||||
// .defaultChecked
|
||||
reflectBoolean({
|
||||
element: document.createElement("input"),
|
||||
attribute: { idl: "defaultChecked", content: "checked" },
|
||||
});
|
||||
|
||||
// .checked doesn't reflect a content attribute.
|
||||
|
||||
// .dirName
|
||||
todo("dirName" in document.createElement("input"),
|
||||
"dirName isn't implemented yet");
|
||||
|
||||
// .disabled
|
||||
reflectBoolean({
|
||||
element: document.createElement("input"),
|
||||
attribute: "disabled",
|
||||
});
|
||||
|
||||
// TODO: form (HTMLFormElement)
|
||||
// TODO: files (FileList)
|
||||
|
||||
// .formAction
|
||||
reflectURL({
|
||||
element: document.createElement("button"),
|
||||
attribute: "formAction",
|
||||
});
|
||||
|
||||
// .formEnctype
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "formEnctype",
|
||||
validValues: [ "application/x-www-form-urlencoded", "multipart/form-data",
|
||||
"text/plain" ],
|
||||
invalidValues: [ "", "foo", "tulip", "multipart/foo" ],
|
||||
defaultValue: { invalid: "application/x-www-form-urlencoded", missing: "" }
|
||||
});
|
||||
|
||||
// .formMethod
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "formMethod",
|
||||
validValues: [ "get", "post" ],
|
||||
invalidValues: [ "", "foo", "tulip" ],
|
||||
defaultValue: { invalid: "get", missing: "" }
|
||||
});
|
||||
|
||||
// .formNoValidate
|
||||
reflectBoolean({
|
||||
element: document.createElement("input"),
|
||||
attribute: "formNoValidate",
|
||||
});
|
||||
|
||||
// .formTarget
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "formTarget",
|
||||
otherValues: [ "_blank", "_self", "_parent", "_top" ],
|
||||
});
|
||||
|
||||
// .height
|
||||
testWidthHeight('height');
|
||||
|
||||
// .indeterminate doesn't reflect a content attribute.
|
||||
|
||||
// .inputmode
|
||||
if (SpecialPowers.getBoolPref("dom.forms.inputmode")) {
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "inputMode",
|
||||
validValues: [ "numeric", "digit", "uppercase", "lowercase", "titlecase", "autocapitalized", "auto" ],
|
||||
invalidValues: [ "", "foo", "tulip" ],
|
||||
defaultValue: "auto"
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: list (HTMLElement)
|
||||
|
||||
// .max
|
||||
reflectString({
|
||||
element: document.createElement('input'),
|
||||
attribute: 'max',
|
||||
});
|
||||
|
||||
// .maxLength
|
||||
reflectInt({
|
||||
element: document.createElement("input"),
|
||||
attribute: "maxLength",
|
||||
nonNegative: true,
|
||||
});
|
||||
|
||||
// .min
|
||||
reflectString({
|
||||
element: document.createElement('input'),
|
||||
attribute: 'min',
|
||||
});
|
||||
|
||||
// .multiple
|
||||
reflectBoolean({
|
||||
element: document.createElement("input"),
|
||||
attribute: "multiple",
|
||||
});
|
||||
|
||||
// .name
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "name",
|
||||
otherValues: [ "isindex", "_charset_" ],
|
||||
});
|
||||
|
||||
// .pattern
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "pattern",
|
||||
otherValues: [ "[0-9][A-Z]{3}" ],
|
||||
});
|
||||
|
||||
// .placeholder
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "placeholder",
|
||||
otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
|
||||
});
|
||||
|
||||
// .readOnly
|
||||
reflectBoolean({
|
||||
element: document.createElement("input"),
|
||||
attribute: "readOnly",
|
||||
});
|
||||
|
||||
// .required
|
||||
reflectBoolean({
|
||||
element: document.createElement("input"),
|
||||
attribute: "required",
|
||||
});
|
||||
|
||||
// .size
|
||||
reflectUnsignedInt({
|
||||
element: document.createElement("input"),
|
||||
attribute: "size",
|
||||
nonZero: true,
|
||||
defaultValue: 20,
|
||||
});
|
||||
|
||||
// .src (URL)
|
||||
reflectURL({
|
||||
element: document.createElement('input'),
|
||||
attribute: 'src',
|
||||
});
|
||||
|
||||
// .step
|
||||
reflectString({
|
||||
element: document.createElement('input'),
|
||||
attribute: 'step',
|
||||
});
|
||||
|
||||
// .type
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "type",
|
||||
validValues: [ "hidden", "text", "search", "tel", "url", "email", "password",
|
||||
"checkbox", "radio", "file", "submit", "image", "reset",
|
||||
"button", "date", "time", "number", "range", "color", "month",
|
||||
"week", "datetime-local" ],
|
||||
invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
|
||||
defaultValue: "text"
|
||||
});
|
||||
|
||||
// .defaultValue
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: { idl: "defaultValue", content: "value" },
|
||||
otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
|
||||
});
|
||||
|
||||
// .value doesn't reflect a content attribute.
|
||||
|
||||
// .valueAsDate
|
||||
is("valueAsDate" in document.createElement("input"), true,
|
||||
"valueAsDate should be available");
|
||||
|
||||
// Deeper check will be done with bug 763305.
|
||||
is('valueAsNumber' in document.createElement("input"), true,
|
||||
"valueAsNumber should be available");
|
||||
|
||||
// .selectedOption
|
||||
todo("selectedOption" in document.createElement("input"),
|
||||
"selectedOption isn't implemented yet");
|
||||
|
||||
// .width
|
||||
testWidthHeight('width');
|
||||
|
||||
// .willValidate doesn't reflect a content attribute.
|
||||
// .validity doesn't reflect a content attribute.
|
||||
// .validationMessage doesn't reflect a content attribute.
|
||||
// .labels doesn't reflect a content attribute.
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,108 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1372369
|
||||
-->
|
||||
<head>
|
||||
<title>Test for <input type='date'> bad input validity state</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
input { background-color: rgb(0,0,0) !important; }
|
||||
:valid { background-color: rgb(0,255,0) !important; }
|
||||
:invalid { background-color: rgb(255,0,0) !important; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1372369">Mozilla Bug 1372369</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<form>
|
||||
<input type="date" id="input">
|
||||
<form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for <input type='date'> bad input validity state **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Turn off Spatial Navigation because it hijacks arrow keydown events:
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
const DATE_BAD_INPUT_MSG = "Please enter a valid date.";
|
||||
const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
|
||||
|
||||
function checkValidity(aElement, aIsBadInput) {
|
||||
is(aElement.validity.valid, aIsBadInput ? false : true,
|
||||
"validity.valid should be " + (aIsBadInput ? "false" : "true"));
|
||||
is(aElement.validity.badInput, aIsBadInput ? true : false,
|
||||
"validity.badInput should be " + (aIsBadInput ? "true" : "false"));
|
||||
is(aElement.validationMessage, aIsBadInput ? DATE_BAD_INPUT_MSG : "",
|
||||
"validationMessage should be: " + (aIsBadInput ? DATE_BAD_INPUT_MSG : ""));
|
||||
|
||||
is(window.getComputedStyle(aElement).getPropertyValue('background-color'),
|
||||
aIsBadInput ? "rgb(255, 0, 0)" : "rgb(0, 255, 0)",
|
||||
(aIsBadInput ? ":invalid" : "valid") + " pseudo-classs should apply");
|
||||
}
|
||||
|
||||
function sendKeys(aKey) {
|
||||
if (aKey.startsWith("KEY_")) {
|
||||
synthesizeKey(aKey);
|
||||
} else {
|
||||
sendString(aKey);
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
var elem = document.getElementById("input");
|
||||
var inputRect = input.getBoundingClientRect();
|
||||
|
||||
// Points over the input's reset button
|
||||
var resetButton_X = inputRect.width - 15;
|
||||
var resetButton_Y = inputRect.height / 2;
|
||||
|
||||
elem.focus();
|
||||
sendKeys("02312017");
|
||||
elem.blur();
|
||||
checkValidity(elem, true);
|
||||
|
||||
elem.focus();
|
||||
sendKeys("02292016");
|
||||
elem.blur();
|
||||
checkValidity(elem, false);
|
||||
|
||||
elem.focus();
|
||||
sendKeys("06312000");
|
||||
elem.blur();
|
||||
checkValidity(elem, true);
|
||||
|
||||
// Removing any of the fields makes the input valid again.
|
||||
elem.focus();
|
||||
sendKeys("KEY_Backspace");
|
||||
elem.blur();
|
||||
checkValidity(elem, false);
|
||||
|
||||
elem.focus();
|
||||
sendKeys("02292017");
|
||||
elem.blur();
|
||||
checkValidity(elem, true);
|
||||
|
||||
// Reset button is desktop only.
|
||||
if (isDesktop) {
|
||||
// Clearing all fields should clear bad input validity state as well.
|
||||
synthesizeMouse(input, resetButton_X, resetButton_Y, {});
|
||||
checkValidity(elem, false);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,243 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1286182
|
||||
-->
|
||||
<head>
|
||||
<title>Test key events for time control</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1286182">Mozilla Bug 1286182</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input id="input" type="date">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Turn off Spatial Navigation because it hijacks arrow keydown events:
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
var testData = [
|
||||
/**
|
||||
* keys: keys to send to the input element.
|
||||
* initialVal: initial value set to the input element.
|
||||
* expectedVal: expected value of the input element after sending the keys.
|
||||
*/
|
||||
{
|
||||
// Type 11222016, default order is month, day, year.
|
||||
keys: ["11222016"],
|
||||
initialVal: "",
|
||||
expectedVal: "2016-11-22"
|
||||
},
|
||||
{
|
||||
// Type 3 in the month field will automatically advance to the day field,
|
||||
// then type 5 in the day field will automatically advance to the year
|
||||
// field.
|
||||
keys: ["352016"],
|
||||
initialVal: "",
|
||||
expectedVal: "2016-03-05"
|
||||
},
|
||||
{
|
||||
// Type 13 in the month field will set it to the maximum month, which is
|
||||
// 12.
|
||||
keys: ["13012016"],
|
||||
initialVal: "",
|
||||
expectedVal: "2016-12-01"
|
||||
},
|
||||
{
|
||||
// Type 00 in the month field will set it to the minimum month, which is 1.
|
||||
keys: ["00012016"],
|
||||
initialVal: "",
|
||||
expectedVal: "2016-01-01"
|
||||
},
|
||||
{
|
||||
// Type 33 in the day field will set it to the maximum day, which is 31.
|
||||
keys: ["12332016"],
|
||||
initialVal: "",
|
||||
expectedVal: "2016-12-31"
|
||||
},
|
||||
{
|
||||
// Type 00 in the day field will set it to the minimum day, which is 1.
|
||||
keys: ["12002016"],
|
||||
initialVal: "",
|
||||
expectedVal: "2016-12-01"
|
||||
},
|
||||
{
|
||||
// Type 275769 in the year field will set it to the maximum year, which is
|
||||
// 275760.
|
||||
keys: ["0101275769"],
|
||||
initialVal: "",
|
||||
expectedVal: "275760-01-01"
|
||||
},
|
||||
{
|
||||
// Type 000000 in the year field will set it to the minimum year, which is
|
||||
// 0001.
|
||||
keys: ["0101000000"],
|
||||
initialVal: "",
|
||||
expectedVal: "0001-01-01"
|
||||
},
|
||||
{
|
||||
// Advance to year field and decrement.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_ArrowDown"],
|
||||
initialVal: "2016-11-25",
|
||||
expectedVal: "2015-11-25"
|
||||
},
|
||||
{
|
||||
// Right key should do the same thing as TAB key.
|
||||
keys: ["KEY_ArrowRight", "KEY_ArrowRight", "KEY_ArrowDown"],
|
||||
initialVal: "2016-11-25",
|
||||
expectedVal: "2015-11-25"
|
||||
},
|
||||
{
|
||||
// Advance to day field then back to month field and decrement.
|
||||
keys: ["KEY_ArrowRight", "KEY_ArrowLeft", "KEY_ArrowDown"],
|
||||
initialVal: "2000-05-01",
|
||||
expectedVal: "2000-04-01"
|
||||
},
|
||||
{
|
||||
// Focus starts on the first field, month in this case, and increment.
|
||||
keys: ["KEY_ArrowUp"],
|
||||
initialVal: "2000-03-01",
|
||||
expectedVal: "2000-04-01"
|
||||
},
|
||||
{
|
||||
// Advance to day field and decrement.
|
||||
keys: ["KEY_Tab", "KEY_ArrowDown"],
|
||||
initialVal: "1234-01-01",
|
||||
expectedVal: "1234-01-31"
|
||||
},
|
||||
{
|
||||
// Advance to day field and increment.
|
||||
keys: ["KEY_Tab", "KEY_ArrowUp"],
|
||||
initialVal: "1234-01-01",
|
||||
expectedVal: "1234-01-02"
|
||||
},
|
||||
{
|
||||
// PageUp on month field increments month by 3.
|
||||
keys: ["KEY_PageUp"],
|
||||
initialVal: "1999-01-01",
|
||||
expectedVal: "1999-04-01"
|
||||
},
|
||||
{
|
||||
// PageDown on month field decrements month by 3.
|
||||
keys: ["KEY_PageDown"],
|
||||
initialVal: "1999-01-01",
|
||||
expectedVal: "1999-10-01"
|
||||
},
|
||||
{
|
||||
// PageUp on day field increments day by 7.
|
||||
keys: ["KEY_Tab", "KEY_PageUp"],
|
||||
initialVal: "1999-01-01",
|
||||
expectedVal: "1999-01-08"
|
||||
},
|
||||
{
|
||||
// PageDown on day field decrements day by 7.
|
||||
keys: ["KEY_Tab", "KEY_PageDown"],
|
||||
initialVal: "1999-01-01",
|
||||
expectedVal: "1999-01-25"
|
||||
},
|
||||
{
|
||||
// PageUp on year field increments year by 10.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_PageUp"],
|
||||
initialVal: "1999-01-01",
|
||||
expectedVal: "2009-01-01"
|
||||
},
|
||||
{
|
||||
// PageDown on year field decrements year by 10.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_PageDown"],
|
||||
initialVal: "1999-01-01",
|
||||
expectedVal: "1989-01-01"
|
||||
},
|
||||
{
|
||||
// Home key on month field sets it to the minimum month, which is 01.
|
||||
keys: ["KEY_Home"],
|
||||
initialVal: "2016-06-01",
|
||||
expectedVal: "2016-01-01"
|
||||
},
|
||||
{
|
||||
// End key on month field sets it to the maximum month, which is 12.
|
||||
keys: ["KEY_End"],
|
||||
initialVal: "2016-06-01",
|
||||
expectedVal: "2016-12-01"
|
||||
},
|
||||
{
|
||||
// Home key on day field sets it to the minimum day, which is 01.
|
||||
keys: ["KEY_Tab", "KEY_Home"],
|
||||
initialVal: "2016-01-10",
|
||||
expectedVal: "2016-01-01"
|
||||
},
|
||||
{
|
||||
// End key on day field sets it to the maximum day, which is 31.
|
||||
keys: ["KEY_Tab", "KEY_End"],
|
||||
initialVal: "2016-01-10",
|
||||
expectedVal: "2016-01-31"
|
||||
},
|
||||
{
|
||||
// Home key should have no effect on year field.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_Home"],
|
||||
initialVal: "2016-01-01",
|
||||
expectedVal: "2016-01-01"
|
||||
},
|
||||
{
|
||||
// End key should have no effect on year field.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_End"],
|
||||
initialVal: "2016-01-01",
|
||||
expectedVal: "2016-01-01"
|
||||
},
|
||||
{
|
||||
// Incomplete value maps to empty .value.
|
||||
keys: ["1111"],
|
||||
initialVal: "",
|
||||
expectedVal: ""
|
||||
},
|
||||
];
|
||||
|
||||
function sendKeys(aKeys) {
|
||||
for (let i = 0; i < aKeys.length; i++) {
|
||||
let key = aKeys[i];
|
||||
if (key.startsWith("KEY_")) {
|
||||
synthesizeKey(key);
|
||||
} else {
|
||||
sendString(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
var elem = document.getElementById("input");
|
||||
|
||||
for (let { keys, initialVal, expectedVal } of testData) {
|
||||
elem.focus();
|
||||
elem.value = initialVal;
|
||||
sendKeys(keys);
|
||||
is(elem.value, expectedVal,
|
||||
"Test with " + keys + ", result should be " + expectedVal);
|
||||
elem.value = "";
|
||||
elem.blur();
|
||||
}
|
||||
|
||||
function chromeListener(e) {
|
||||
ok(false, "Picker should not be opened when dispatching untrusted click.");
|
||||
}
|
||||
SpecialPowers.addChromeEventListener("MozOpenDateTimePicker",
|
||||
chromeListener);
|
||||
input.click();
|
||||
SpecialPowers.removeChromeEventListener("MozOpenDateTimePicker",
|
||||
chromeListener);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,65 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
|
||||
-->
|
||||
<head>
|
||||
<title>Test focus/blur behaviour for date/time input types</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input id="input_time" type="time">
|
||||
<input id="input_date" type="date">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/**
|
||||
* Test for Bug 1288591.
|
||||
* This test checks whether date/time input types' .focus()/.blur() works
|
||||
* correctly. This test also checks when focusing on an date/time input element,
|
||||
* the focus is redirected to the anonymous text control, but the
|
||||
* document.activeElement still returns date/time input element.
|
||||
**/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function testFocusBlur(type) {
|
||||
let input = document.getElementById("input_" + type);
|
||||
input.focus();
|
||||
|
||||
// The active element returns the date/time input element.
|
||||
let activeElement = document.activeElement;
|
||||
is(activeElement, input, "activeElement should be the date/time input element");
|
||||
is(activeElement.localName, "input", "activeElement should be an input element");
|
||||
is(activeElement.type, type, "activeElement should be of type " + type);
|
||||
|
||||
// Use FocusManager to check that the actual focus is on the anonymous
|
||||
// text control.
|
||||
let fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"]
|
||||
.getService(SpecialPowers.Ci.nsIFocusManager);
|
||||
let focusedElement = fm.focusedElement;
|
||||
is(focusedElement.localName, "span", "focusedElement should be an span element");
|
||||
|
||||
input.blur();
|
||||
isnot(document.activeElement, input, "activeElement should no longer be the datetime input element");
|
||||
}
|
||||
|
||||
function test() {
|
||||
let inputTypes = ["time", "date"];
|
||||
|
||||
for (let i = 0; i < inputTypes.length; i++) {
|
||||
testFocusBlur(inputTypes[i]);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,90 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1301306
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1301306</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301306">Mozilla Bug 722599</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input type="time" id="input_time" onfocus="++focusEvents[0]"
|
||||
onblur="++blurEvents[0]" onfocusin="++focusInEvents[0]"
|
||||
onfocusout="++focusOutEvents[0]">
|
||||
<input type="date" id="input_date" onfocus="++focusEvents[1]"
|
||||
onblur="++blurEvents[1]" onfocusin="++focusInEvents[1]"
|
||||
onfocusout="++focusOutEvents[1]">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/**
|
||||
* Test for Bug 1301306.
|
||||
* This test checks that when moving inside the time input element, e.g. jumping
|
||||
* through the inner text boxes, does not fire extra focus/blur events.
|
||||
**/
|
||||
|
||||
var inputTypes = ["time", "date"];
|
||||
var focusEvents = [0, 0];
|
||||
var focusInEvents = [0, 0];
|
||||
var focusOutEvents = [0, 0];
|
||||
var blurEvents = [0, 0];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function test() {
|
||||
for (var i = 0; i < inputTypes.length; i++) {
|
||||
var input = document.getElementById("input_" + inputTypes[i]);
|
||||
|
||||
input.focus();
|
||||
is(focusEvents[i], 1, inputTypes[i] + " input element should have dispatched focus event.");
|
||||
is(focusInEvents[i], 1, inputTypes[i] + " input element should have dispatched focusin event.");
|
||||
is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
|
||||
is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
|
||||
|
||||
// Move around inside the input element's input box.
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
|
||||
is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
|
||||
is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
|
||||
is(blurEvents[i], 0, inputTypes[i] + " time input element should not have dispatched blur event.");
|
||||
|
||||
synthesizeKey("KEY_ArrowRight");
|
||||
is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
|
||||
is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
|
||||
is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
|
||||
is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
|
||||
|
||||
synthesizeKey("KEY_ArrowLeft");
|
||||
is(focusEvents[i], 1,inputTypes[i] + " input element should not have dispatched focus event.");
|
||||
is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
|
||||
is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
|
||||
is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
|
||||
|
||||
synthesizeKey("KEY_ArrowRight");
|
||||
is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
|
||||
is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
|
||||
is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
|
||||
is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
|
||||
|
||||
input.blur();
|
||||
is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
|
||||
is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
|
||||
is(focusOutEvents[i], 1, inputTypes[i] + " input element should have dispatched focusout event.");
|
||||
is(blurEvents[i], 1, inputTypes[i] + " input element should have dispatched blur event.");
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,79 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1346085
|
||||
-->
|
||||
<head>
|
||||
<title>Test moving focus in onfocus/onblur handler</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1346085">Mozilla Bug 1346085</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input id="input_time" type="time">
|
||||
<input id="input_date" type="date">
|
||||
<input id="input_dummy" type="text">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/**
|
||||
* Test for Bug 1346085.
|
||||
* This test checks whether date/time input types' focus state are set
|
||||
* correctly, event when moving focus in onfocus/onblur handler.
|
||||
**/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function testFocusState(type) {
|
||||
let input = document.getElementById("input_" + type);
|
||||
|
||||
input.focus();
|
||||
let focus = document.querySelector(":focus");
|
||||
let focusRing = document.querySelector(":-moz-focusring");
|
||||
is(focus, input, "input should have :focus state after focus");
|
||||
is(focusRing, input, "input should have :-moz-focusring state after focus");
|
||||
|
||||
input.blur();
|
||||
focus = document.querySelector(":focus");
|
||||
focusRing = document.querySelector(":-moz-focusring");
|
||||
isnot(focus, input, "input should not have :focus state after blur");
|
||||
isnot(focusRing, input, "input should not have :-moz-focusring state after blur");
|
||||
|
||||
input.addEventListener("focus", function() {
|
||||
document.getElementById("input_dummy").focus();
|
||||
}, { once: true });
|
||||
|
||||
input.focus();
|
||||
focus = document.querySelector(":focus");
|
||||
focusRing = document.querySelector(":-moz-focusring");
|
||||
isnot(focus, input, "input should not have :focus state when moving focus in onfocus handler");
|
||||
isnot(focusRing, input, "input should not have :-moz-focusring state when moving focus in onfocus handler");
|
||||
|
||||
input.addEventListener("blur", function() {
|
||||
document.getElementById("input_dummy").focus();
|
||||
}, { once: true });
|
||||
|
||||
input.blur();
|
||||
focus = document.querySelector(":focus");
|
||||
focusRing = document.querySelector(":-moz-focusring");
|
||||
isnot(focus, input, "input should not have :focus state when moving focus in onblur handler");
|
||||
isnot(focusRing, input, "input should not have :-moz-focusring state when moving focus in onblur handler");
|
||||
}
|
||||
|
||||
function test() {
|
||||
let inputTypes = ["time", "date"];
|
||||
|
||||
for (let i = 0; i < inputTypes.length; i++) {
|
||||
testFocusState(inputTypes[i]);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,93 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1370858
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1370858</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1370858">Mozilla Bug 722599</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input type="time" id="input_time" onchange="++changeEvents[0]"
|
||||
oninput="++inputEvents[0]">
|
||||
<input type="date" id="input_date" onchange="++changeEvents[1]"
|
||||
oninput="++inputEvents[1]">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/**
|
||||
* Test for Bug 1370858.
|
||||
* Test that change and input events are (not) fired for date/time inputs.
|
||||
**/
|
||||
|
||||
const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
|
||||
|
||||
var inputTypes = ["time", "date"];
|
||||
var changeEvents = [0, 0];
|
||||
var inputEvents = [0, 0];
|
||||
var values = ["10:30", "2017-06-08"];
|
||||
var expectedValues = [["09:30", "01:30"], ["2017-05-08", "2017-01-08"]];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function test() {
|
||||
for (var i = 0; i < inputTypes.length; i++) {
|
||||
var input = document.getElementById("input_" + inputTypes[i]);
|
||||
var inputRect = input.getBoundingClientRect();
|
||||
|
||||
// Points over the input's reset button
|
||||
var resetButton_X = inputRect.width - 15;
|
||||
var resetButton_Y = inputRect.height / 2;
|
||||
|
||||
is(changeEvents[i], 0, "Number of change events should be 0 at start.");
|
||||
is(inputEvents[i], 0, "Number of input events should be 0 at start.");
|
||||
|
||||
// Test that change and input events are not dispatched setting .value by
|
||||
// script.
|
||||
input.value = values[i];
|
||||
is(input.value, values[i], "Check that value was set correctly (0).");
|
||||
is(changeEvents[i], 0, "Change event should not have dispatched (0).");
|
||||
is(inputEvents[i], 0, "Input event should not have dispatched (0).");
|
||||
|
||||
// Test that change and input events are fired when changing the value using
|
||||
// up/down keys.
|
||||
input.focus();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
is(input.value, expectedValues[i][0], "Check that value was set correctly (1).");
|
||||
is(changeEvents[i], 1, "Change event should be dispatched (1).");
|
||||
is(inputEvents[i], 1, "Input event should ne dispatched (1).");
|
||||
|
||||
// Test that change and input events are fired when changing the value with
|
||||
// the keyboard.
|
||||
sendString("01");
|
||||
// We get event per character.
|
||||
is(input.value, expectedValues[i][1], "Check that value was set correctly (2).");
|
||||
is(changeEvents[i], 3, "Change event should be dispatched (2).");
|
||||
is(inputEvents[i], 3, "Input event should be dispatched (2).");
|
||||
|
||||
// Reset button is desktop only.
|
||||
if (isDesktop) {
|
||||
// Test that change and input events are fired when clearing the value using
|
||||
// the reset button.
|
||||
synthesizeMouse(input, resetButton_X, resetButton_Y, {});
|
||||
is(input.value, "", "Check that value was set correctly (3).");
|
||||
is(changeEvents[i], 4, "Change event should be dispatched (3).");
|
||||
is(inputEvents[i], 4, "Input event should be dispatched (3).");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,83 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
|
||||
-->
|
||||
<head>
|
||||
<title>Test tabindex attribute for date/time input types</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input id="time1" type="time" tabindex="0">
|
||||
<input id="time2" type="time" tabindex="-1">
|
||||
<input id="time3" type="time" tabindex="0">
|
||||
<input id="date1" type="date" tabindex="0">
|
||||
<input id="date2" type="date" tabindex="-1">
|
||||
<input id="date3" type="date" tabindex="0">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/**
|
||||
* Test for Bug 1288591.
|
||||
* This test checks whether date/time input types tabindex attribute works
|
||||
* correctly.
|
||||
**/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function testTabindex(type) {
|
||||
let input1 = document.getElementById(type + "1");
|
||||
let input2 = document.getElementById(type + "2");
|
||||
let input3 = document.getElementById(type + "3");
|
||||
|
||||
input1.focus();
|
||||
is(document.activeElement, input1,
|
||||
"input element with tabindex=0 is focusable");
|
||||
|
||||
// Advance to next inner field
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(document.activeElement, input1,
|
||||
"input element with tabindex=0 is tabbable");
|
||||
|
||||
// Advance to next inner field
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(document.activeElement, input1,
|
||||
"input element with tabindex=0 is tabbable");
|
||||
|
||||
// Advance to next element
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(document.activeElement, input3,
|
||||
"input element with tabindex=-1 is not tabbable");
|
||||
|
||||
input2.focus();
|
||||
is(document.activeElement, input2,
|
||||
"input element with tabindex=-1 is still focusable");
|
||||
|
||||
// Changing the tabindex attribute dynamically.
|
||||
input3.setAttribute("tabindex", "-1");
|
||||
synthesizeKey("KEY_Tab"); // need only one TAB since input2 is not tabbable
|
||||
isnot(document.activeElement, input3,
|
||||
"element with tabindex changed to -1 should not be tabbable");
|
||||
}
|
||||
|
||||
function test() {
|
||||
let inputTypes = ["time", "date"];
|
||||
|
||||
for (let i = 0; i < inputTypes.length; i++) {
|
||||
testTabindex(inputTypes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,81 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=977029
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 977029</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=977029">Bug 977029</a>
|
||||
<p>
|
||||
Goal of this test is to check that modifying defaultValue and value attribute
|
||||
of input types is working as expected.
|
||||
</p>
|
||||
<form>
|
||||
<input id='a' type="color" value="#00ff00">
|
||||
<input id='b' type="text" value="foo">
|
||||
<input id='c' type="email" value="foo">
|
||||
<input id='d' type="date" value="2010-09-20">
|
||||
<input id='e' type="search" value="foo">
|
||||
<input id='f' type="tel" value="foo">
|
||||
<input id='g' type="url" value="foo">
|
||||
<input id='h' type="number" value="42">
|
||||
<input id='i' type="range" value="42" min="0" max="100">
|
||||
<input id='j' type="time" value="17:00:25.54">
|
||||
</form>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
|
||||
// [ element id | original defaultValue | another value | another default value]
|
||||
// Preferably use only valid values: the goal of this test isn't to test the
|
||||
// value sanitization algorithm (for input types which have one) as this is
|
||||
// already part of another test)
|
||||
var testData = [["a", "#00ff00", "#00aaaa", "#00ccaa"],
|
||||
["b", "foo", "bar", "tulip"],
|
||||
["c", "foo", "foo@bar.org", "tulip"],
|
||||
["d", "2010-09-20", "2012-09-21", ""],
|
||||
["e", "foo", "bar", "tulip"],
|
||||
["f", "foo", "bar", "tulip"],
|
||||
["g", "foo", "bar", "tulip"],
|
||||
["h", "42", "1337", "3"],
|
||||
["i", "42", "17", "3"],
|
||||
["j", "17:00:25.54", "07:00:25", "03:00:03"],
|
||||
];
|
||||
|
||||
for (var data of testData) {
|
||||
id = data[0];
|
||||
input = document.getElementById(id);
|
||||
originalDefaultValue = data[1];
|
||||
is(originalDefaultValue, input.defaultValue,
|
||||
"Default value isn't the expected one");
|
||||
is(originalDefaultValue, input.value,
|
||||
"input.value original value is different from defaultValue");
|
||||
input.defaultValue = data[2]
|
||||
is(input.defaultValue, input.value,
|
||||
"Changing default value before value was changed should change value too");
|
||||
input.value = data[3];
|
||||
input.defaultValue = originalDefaultValue;
|
||||
is(input.value, data[3],
|
||||
"Changing default value after value was changed should not change value");
|
||||
input.value = data[2];
|
||||
is(originalDefaultValue, input.defaultValue,
|
||||
"defaultValue shouldn't change when changing value");
|
||||
input.defaultValue = data[3];
|
||||
is(input.defaultValue, data[3],
|
||||
"defaultValue should have changed");
|
||||
// Change the value...
|
||||
input.value = data[2];
|
||||
is(input.value, data[2],
|
||||
"value should have changed");
|
||||
// ...then reset the form
|
||||
input.form.reset();
|
||||
is(input.defaultValue, input.value,
|
||||
"reset form should bring back the default value");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,585 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=549475
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 549475</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=549475">Mozilla Bug 549475</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<div id='content'>
|
||||
<form>
|
||||
</form>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
|
||||
/**
|
||||
* This files tests the 'value sanitization algorithm' for the various input
|
||||
* types. Note that an input's value is affected by more than just its type's
|
||||
* value sanitization algorithm; e.g. some type=range has actions that the user
|
||||
* agent must perform to change the element's value to avoid underflow/overflow
|
||||
* and step mismatch (when possible). We specifically avoid triggering these
|
||||
* other actions here so that this test only tests the value sanitization
|
||||
* algorithm for the various input types.
|
||||
*
|
||||
* XXXjwatt splitting out testing of the value sanitization algorithm and
|
||||
* "other things" that affect .value makes it harder to know what we're testing
|
||||
* and what we've missed, because what's included in the value sanitization
|
||||
* algorithm and what's not is different from input type to input type. It
|
||||
* seems to me it would be better to have a test (maybe one per type) focused
|
||||
* on testing .value for permutations of all other inputs that can affect it.
|
||||
* The value sanitization algorithm is just an internal spec concept after all.
|
||||
*/
|
||||
|
||||
// We buffer up the results of sets of sub-tests, and avoid outputting log
|
||||
// entries for them all if they all pass. Otherwise, we have an enormous amount
|
||||
// of test output.
|
||||
|
||||
var delayedTests = [];
|
||||
var anyFailedDelayedTests = false;
|
||||
|
||||
function delayed_is(actual, expected, description)
|
||||
{
|
||||
var result = actual == expected;
|
||||
delayedTests.push({ actual: actual, expected: expected, description: description });
|
||||
if (!result) {
|
||||
anyFailedDelayedTests = true;
|
||||
}
|
||||
}
|
||||
|
||||
function flushDelayedTests(description)
|
||||
{
|
||||
if (anyFailedDelayedTests) {
|
||||
info("Outputting individual results for \"" + description + "\" due to failures in subtests");
|
||||
for (var test of delayedTests) {
|
||||
is(test.actual, test.expected, test.description);
|
||||
}
|
||||
} else {
|
||||
ok(true, description + " (" + delayedTests.length + " subtests)");
|
||||
}
|
||||
delayedTests = [];
|
||||
anyFailedDelayedTests = false;
|
||||
}
|
||||
|
||||
// We are excluding "file" because it's too different from the other types.
|
||||
// And it has no sanitizing algorithm.
|
||||
var inputTypes =
|
||||
[
|
||||
"text", "password", "search", "tel", "hidden", "checkbox", "radio",
|
||||
"submit", "image", "reset", "button", "email", "url", "number", "date",
|
||||
"time", "range", "color", "month", "week", "datetime-local"
|
||||
];
|
||||
|
||||
var valueModeValue =
|
||||
[
|
||||
"text", "search", "url", "tel", "email", "password", "date", "datetime",
|
||||
"month", "week", "time", "datetime-local", "number", "range", "color",
|
||||
];
|
||||
|
||||
function sanitizeDate(aValue)
|
||||
{
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-date-string
|
||||
function getNumbersOfDaysInMonth(aMonth, aYear) {
|
||||
if (aMonth === 2) {
|
||||
return (aYear % 400 === 0 || (aYear % 100 != 0 && aYear % 4 === 0)) ? 29 : 28;
|
||||
}
|
||||
return (aMonth === 1 || aMonth === 3 || aMonth === 5 || aMonth === 7 ||
|
||||
aMonth === 8 || aMonth === 10 || aMonth === 12) ? 31 : 30;
|
||||
}
|
||||
|
||||
var match = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})$/.exec(aValue);
|
||||
if (!match) {
|
||||
return "";
|
||||
}
|
||||
var year = Number(match[1]);
|
||||
if (year === 0) {
|
||||
return "";
|
||||
}
|
||||
var month = Number(match[2]);
|
||||
if (month > 12 || month < 1) {
|
||||
return "";
|
||||
}
|
||||
var day = Number(match[3]);
|
||||
return 1 <= day && day <= getNumbersOfDaysInMonth(month, year) ? aValue : "";
|
||||
}
|
||||
|
||||
function sanitizeTime(aValue)
|
||||
{
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-time-string
|
||||
var match = /^([0-9]{2}):([0-9]{2})(.*)$/.exec(aValue);
|
||||
if (!match) {
|
||||
return "";
|
||||
}
|
||||
var hours = match[1];
|
||||
if (hours < 0 || hours > 23) {
|
||||
return "";
|
||||
}
|
||||
var minutes = match[2];
|
||||
if (minutes < 0 || minutes > 59) {
|
||||
return "";
|
||||
}
|
||||
var other = match[3];
|
||||
if (other == "") {
|
||||
return aValue;
|
||||
}
|
||||
match = /^:([0-9]{2})(.*)$/.exec(other);
|
||||
if (!match) {
|
||||
return "";
|
||||
}
|
||||
var seconds = match[1];
|
||||
if (seconds < 0 || seconds > 59) {
|
||||
return "";
|
||||
}
|
||||
var other = match[2];
|
||||
if (other == "") {
|
||||
return aValue;
|
||||
}
|
||||
match = /^.([0-9]{1,3})$/.exec(other);
|
||||
if (!match) {
|
||||
return "";
|
||||
}
|
||||
return aValue;
|
||||
}
|
||||
|
||||
function sanitizeDateTimeLocal(aValue)
|
||||
{
|
||||
// https://html.spec.whatwg.org/multipage/infrastructure.html#valid-local-date-and-time-string
|
||||
if (aValue.length < 16) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var sepIndex = aValue.indexOf("T");
|
||||
if (sepIndex == -1) {
|
||||
sepIndex = aValue.indexOf(" ");
|
||||
if (sepIndex == -1) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
var [date, time] = aValue.split(aValue[sepIndex]);
|
||||
if (!sanitizeDate(date)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!sanitizeTime(time)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Normalize datetime-local string.
|
||||
// https://html.spec.whatwg.org/multipage/infrastructure.html#valid-normalised-local-date-and-time-string
|
||||
if (aValue[sepIndex] == " ") {
|
||||
aValue = date + "T" + time;
|
||||
}
|
||||
|
||||
if ((aValue.length - sepIndex) == 6) {
|
||||
return aValue;
|
||||
}
|
||||
|
||||
if ((aValue.length - sepIndex) > 9) {
|
||||
var milliseconds = aValue.substring(sepIndex + 10);
|
||||
if (Number(milliseconds) != 0) {
|
||||
return aValue;
|
||||
}
|
||||
aValue = aValue.slice(0, sepIndex + 9);
|
||||
}
|
||||
|
||||
var seconds = aValue.substring(sepIndex + 7);
|
||||
if (Number(seconds) != 0) {
|
||||
return aValue;
|
||||
}
|
||||
aValue = aValue.slice(0, sepIndex + 6);
|
||||
|
||||
return aValue;
|
||||
}
|
||||
|
||||
function sanitizeValue(aType, aValue)
|
||||
{
|
||||
// http://www.whatwg.org/html/#value-sanitization-algorithm
|
||||
switch (aType) {
|
||||
case "text":
|
||||
case "password":
|
||||
case "search":
|
||||
case "tel":
|
||||
return aValue.replace(/[\n\r]/g, "");
|
||||
case "url":
|
||||
case "email":
|
||||
return aValue.replace(/[\n\r]/g, "").replace(/^[\u0020\u0009\t\u000a\u000c\u000d]+|[\u0020\u0009\t\u000a\u000c\u000d]+$/g, "");
|
||||
case "number":
|
||||
return isNaN(Number(aValue)) ? "" : aValue;
|
||||
case "range":
|
||||
var defaultMinimum = 0;
|
||||
var defaultMaximum = 100;
|
||||
var value = Number(aValue);
|
||||
if (isNaN(value)) {
|
||||
return ((defaultMaximum - defaultMinimum)/2).toString(); // "50"
|
||||
}
|
||||
if (value < defaultMinimum) {
|
||||
return defaultMinimum.toString();
|
||||
}
|
||||
if (value > defaultMaximum) {
|
||||
return defaultMaximum.toString();
|
||||
}
|
||||
return aValue;
|
||||
case "date":
|
||||
return sanitizeDate(aValue);
|
||||
case "time":
|
||||
return sanitizeTime(aValue);
|
||||
case "month":
|
||||
// https://html.spec.whatwg.org/multipage/infrastructure.html#valid-month-string
|
||||
var match = /^([0-9]{4,})-([0-9]{2})$/.exec(aValue);
|
||||
if (!match) {
|
||||
return "";
|
||||
}
|
||||
var year = Number(match[1]);
|
||||
if (year === 0) {
|
||||
return "";
|
||||
}
|
||||
var month = Number(match[2]);
|
||||
if (month > 12 || month < 1) {
|
||||
return "";
|
||||
}
|
||||
return aValue;
|
||||
case "week":
|
||||
// https://html.spec.whatwg.org/multipage/infrastructure.html#valid-week-string
|
||||
function isLeapYear(aYear) {
|
||||
return ((aYear % 4 == 0) && (aYear % 100 != 0)) || (aYear % 400 == 0);
|
||||
}
|
||||
function getDayofWeek(aYear, aMonth, aDay) { /* 0 = Sunday */
|
||||
// Tomohiko Sakamoto algorithm.
|
||||
var monthTable = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];
|
||||
aYear -= Number(aMonth < 3);
|
||||
|
||||
return (aYear + parseInt(aYear / 4) - parseInt(aYear / 100) +
|
||||
parseInt(aYear / 400) + monthTable[aMonth - 1] + aDay) % 7;
|
||||
}
|
||||
function getMaximumWeekInYear(aYear) {
|
||||
var day = getDayofWeek(aYear, 1, 1);
|
||||
return day == 4 || (day == 3 && isLeapYear(aYear)) ? 53 : 52;
|
||||
}
|
||||
|
||||
var match = /^([0-9]{4,})-W([0-9]{2})$/.exec(aValue);
|
||||
if (!match) {
|
||||
return "";
|
||||
}
|
||||
var year = Number(match[1]);
|
||||
if (year === 0) {
|
||||
return "";
|
||||
}
|
||||
var week = Number(match[2]);
|
||||
if (week > 53 || month < 1) {
|
||||
return "";
|
||||
}
|
||||
return 1 <= week && week <= getMaximumWeekInYear(year) ? aValue : "";
|
||||
case "datetime-local":
|
||||
return sanitizeDateTimeLocal(aValue);
|
||||
case "color":
|
||||
return /^#[0-9A-Fa-f]{6}$/.exec(aValue) ? aValue.toLowerCase() : "#000000";
|
||||
default:
|
||||
return aValue;
|
||||
}
|
||||
}
|
||||
|
||||
function checkSanitizing(element, inputTypeDescription)
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
// For text, password, search, tel, email:
|
||||
"\n\rfoo\n\r",
|
||||
"foo\n\rbar",
|
||||
" foo ",
|
||||
" foo\n\r bar ",
|
||||
// For url:
|
||||
"\r\n foobar \n\r",
|
||||
"\u000B foo \u000B",
|
||||
"\u000A foo \u000A",
|
||||
"\u000C foo \u000C",
|
||||
"\u000d foo \u000d",
|
||||
"\u0020 foo \u0020",
|
||||
" \u0009 foo \u0009 ",
|
||||
// For number and range:
|
||||
"42",
|
||||
"13.37",
|
||||
"1.234567898765432",
|
||||
"12foo",
|
||||
"1e2",
|
||||
"3E42",
|
||||
// For date:
|
||||
"1970-01-01",
|
||||
"1234-12-12",
|
||||
"1234567890-01-02",
|
||||
"2012-12-31",
|
||||
"2012-02-29",
|
||||
"2000-02-29",
|
||||
"1234",
|
||||
"1234-",
|
||||
"12345",
|
||||
"1234-01",
|
||||
"1234-012",
|
||||
"1234-01-",
|
||||
"12-12",
|
||||
"999-01-01",
|
||||
"1234-56-78-91",
|
||||
"1234-567-78",
|
||||
"1234--7-78",
|
||||
"abcd-12-12",
|
||||
"thisinotadate",
|
||||
"2012-13-01",
|
||||
"1234-12-42",
|
||||
" 2012-13-01",
|
||||
" 123-01-01",
|
||||
"2012- 3-01",
|
||||
"12- 10- 01",
|
||||
" 12-0-1",
|
||||
"2012-3-001",
|
||||
"2012-12-00",
|
||||
"2012-12-1r",
|
||||
"2012-11-31",
|
||||
"2011-02-29",
|
||||
"2100-02-29",
|
||||
"a2000-01-01",
|
||||
"2000a-01-0'",
|
||||
"20aa00-01-01",
|
||||
"2000a2000-01-01",
|
||||
"2000-1-1",
|
||||
"2000-1-01",
|
||||
"2000-01-1",
|
||||
"2000-01-01 ",
|
||||
"2000- 01-01",
|
||||
"-1970-01-01",
|
||||
"0000-00-00",
|
||||
"0001-00-00",
|
||||
"0000-01-01",
|
||||
"1234-12 12",
|
||||
"1234 12-12",
|
||||
"1234 12 12",
|
||||
// For time:
|
||||
"1",
|
||||
"10",
|
||||
"10:",
|
||||
"10:1",
|
||||
"21:21",
|
||||
":21:21",
|
||||
"-21:21",
|
||||
" 21:21",
|
||||
"21-21",
|
||||
"21:21:",
|
||||
"21:211",
|
||||
"121:211",
|
||||
"21:21 ",
|
||||
"00:00",
|
||||
"-1:00",
|
||||
"24:00",
|
||||
"00:60",
|
||||
"01:01",
|
||||
"23:59",
|
||||
"99:99",
|
||||
"8:30",
|
||||
"19:2",
|
||||
"19:a2",
|
||||
"4c:19",
|
||||
"10:.1",
|
||||
"1.:10",
|
||||
"13:37:42",
|
||||
"13:37.42",
|
||||
"13:37:42 ",
|
||||
"13:37:42.",
|
||||
"13:37:61.",
|
||||
"13:37:00",
|
||||
"13:37:99",
|
||||
"13:37:b5",
|
||||
"13:37:-1",
|
||||
"13:37:.1",
|
||||
"13:37:1.",
|
||||
"13:37:42.001",
|
||||
"13:37:42.001",
|
||||
"13:37:42.abc",
|
||||
"13:37:42.00c",
|
||||
"13:37:42.a23",
|
||||
"13:37:42.12e",
|
||||
"13:37:42.1e1",
|
||||
"13:37:42.e11",
|
||||
"13:37:42.1",
|
||||
"13:37:42.99",
|
||||
"13:37:42.0",
|
||||
"13:37:42.00",
|
||||
"13:37:42.000",
|
||||
"13:37:42.-1",
|
||||
"13:37:42.1.1",
|
||||
"13:37:42.1,1",
|
||||
"13:37:42.",
|
||||
"foo12:12",
|
||||
"13:37:42.100000000000",
|
||||
// For color
|
||||
"#00ff00",
|
||||
"#000000",
|
||||
"red",
|
||||
"#0f0",
|
||||
"#FFFFAA",
|
||||
"FFAABB",
|
||||
"fFAaBb",
|
||||
"FFAAZZ",
|
||||
"ABCDEF",
|
||||
"#7654321",
|
||||
// For month
|
||||
"1970-01",
|
||||
"1234-12",
|
||||
"123456789-01",
|
||||
"2013-13",
|
||||
"0000-00",
|
||||
"2015-00",
|
||||
"0001-01",
|
||||
"1-1",
|
||||
"888-05",
|
||||
"2013-3",
|
||||
"2013-may",
|
||||
"2000-1a",
|
||||
"2013-03-13",
|
||||
"december",
|
||||
"abcdef",
|
||||
"12",
|
||||
" 2013-03",
|
||||
"2013 - 03",
|
||||
"2013 03",
|
||||
"2013/03",
|
||||
// For week
|
||||
"1970-W01",
|
||||
"1970-W53",
|
||||
"1964-W53",
|
||||
"1900-W10",
|
||||
"2004-W53",
|
||||
"2065-W53",
|
||||
"2099-W53",
|
||||
"2010-W53",
|
||||
"2016-W30",
|
||||
"1900-W3",
|
||||
"2016-w30",
|
||||
"2016-30",
|
||||
"16-W30",
|
||||
"2016-Week30",
|
||||
"2000-100",
|
||||
"0000-W01",
|
||||
"00-W01",
|
||||
"123456-W05",
|
||||
"1985-W100",
|
||||
"week",
|
||||
// For datetime-local
|
||||
"1970-01-01T00:00",
|
||||
"1970-01-01Z12:00",
|
||||
"1970-01-01 00:00:00",
|
||||
"1970-01-01T00:00:00.0",
|
||||
"1970-01-01T00:00:00.00",
|
||||
"1970-01-01T00:00:00.000",
|
||||
"1970-01-01 00:00:00.20",
|
||||
"1969-12-31 23:59",
|
||||
"1969-12-31 23:59:00",
|
||||
"1969-12-31 23:59:00.000",
|
||||
"1969-12-31 23:59:00.30",
|
||||
"123456-01-01T12:00",
|
||||
"123456-01-01T12:00:00",
|
||||
"123456-01-01T12:00:00.0",
|
||||
"123456-01-01T12:00:00.00",
|
||||
"123456-01-01T12:00:00.000",
|
||||
"123456-01-01T12:00:30",
|
||||
"123456-01-01T12:00:00.123",
|
||||
"10000-12-31 20:00",
|
||||
"10000-12-31 20:00:00",
|
||||
"10000-12-31 20:00:00.0",
|
||||
"10000-12-31 20:00:00.00",
|
||||
"10000-12-31 20:00:00.000",
|
||||
"10000-12-31 20:00:30",
|
||||
"10000-12-31 20:00:00.123",
|
||||
"2016-13-01T12:00",
|
||||
"2016-12-32T12:00",
|
||||
"2016-11-08 15:40:30.0",
|
||||
"2016-11-08T15:40:30.00",
|
||||
"2016-11-07T17:30:10",
|
||||
"2016-12-1T12:45",
|
||||
"2016-12-01T12:45:30.123456",
|
||||
"2016-12-01T24:00",
|
||||
"2016-12-01T12:88:30",
|
||||
"2016-12-01T12:30:99",
|
||||
"2016-12-01T12:30:100",
|
||||
"2016-12-01",
|
||||
"2016-12-01T",
|
||||
"2016-Dec-01T00:00",
|
||||
"12-05-2016T00:00",
|
||||
"datetime-local"
|
||||
];
|
||||
|
||||
for (value of testData) {
|
||||
element.setAttribute('value', value);
|
||||
delayed_is(element.value, sanitizeValue(type, value),
|
||||
"The value has not been correctly sanitized for type=" + type);
|
||||
delayed_is(element.getAttribute('value'), value,
|
||||
"The content value should not have been sanitized");
|
||||
|
||||
if (type in valueModeValue) {
|
||||
element.setAttribute('value', 'tulip');
|
||||
element.value = value;
|
||||
delayed_is(element.value, sanitizeValue(type, value),
|
||||
"The value has not been correctly sanitized for type=" + type);
|
||||
delayed_is(element.getAttribute('value'), 'tulip',
|
||||
"The content value should not have been sanitized");
|
||||
}
|
||||
|
||||
element.setAttribute('value', '');
|
||||
form.reset();
|
||||
element.type = 'checkbox'; // We know this type has no sanitizing algorithm.
|
||||
element.setAttribute('value', value);
|
||||
delayed_is(element.value, value, "The value should not have been sanitized");
|
||||
element.type = type;
|
||||
delayed_is(element.value, sanitizeValue(type, value),
|
||||
"The value has not been correctly sanitized for type=" + type);
|
||||
delayed_is(element.getAttribute('value'), value,
|
||||
"The content value should not have been sanitized");
|
||||
|
||||
element.setAttribute('value', '');
|
||||
form.reset();
|
||||
element.setAttribute('value', value);
|
||||
form.reset();
|
||||
delayed_is(element.value, sanitizeValue(type, value),
|
||||
"The value has not been correctly sanitized for type=" + type);
|
||||
delayed_is(element.getAttribute('value'), value,
|
||||
"The content value should not have been sanitized");
|
||||
|
||||
// Cleaning-up.
|
||||
element.setAttribute('value', '');
|
||||
form.reset();
|
||||
}
|
||||
|
||||
flushDelayedTests(inputTypeDescription);
|
||||
}
|
||||
|
||||
for (type of inputTypes) {
|
||||
var form = document.forms[0];
|
||||
var element = document.createElement("input");
|
||||
element.style.display = "none";
|
||||
element.type = type;
|
||||
form.appendChild(element);
|
||||
|
||||
checkSanitizing(element, "type=" + type + ", no frame, no editor");
|
||||
|
||||
element.style.display = "";
|
||||
checkSanitizing(element, "type=" + type + ", frame, no editor");
|
||||
|
||||
element.focus();
|
||||
element.blur();
|
||||
checkSanitizing(element, "type=" + type + ", frame, editor");
|
||||
|
||||
element.style.display = "none";
|
||||
checkSanitizing(element, "type=" + type + ", no frame, editor");
|
||||
|
||||
form.removeChild(element);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,123 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=829606
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 829606</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 829606 **/
|
||||
/*
|
||||
* This test checks that setting .value on an text field (input or textarea)
|
||||
* doesn't scroll the field to its beginning.
|
||||
*/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gTestRunner = null;
|
||||
|
||||
function test(aElementName)
|
||||
{
|
||||
var element = document.getElementsByTagName(aElementName)[0];
|
||||
element.focus();
|
||||
|
||||
var baseSnapshot = snapshotWindow(window);
|
||||
|
||||
// This is a sanity check.
|
||||
var s2 = snapshotWindow(window);
|
||||
var results = compareSnapshots(baseSnapshot, snapshotWindow(window), true);
|
||||
ok(results[0], "sanity check: screenshots should be the same");
|
||||
|
||||
element.selectionStart = element.selectionEnd = element.value.length;
|
||||
|
||||
setTimeout(function() {
|
||||
sendString('f');
|
||||
|
||||
requestAnimationFrame(function() {
|
||||
var selectionAtTheEndSnapshot = snapshotWindow(window);
|
||||
results = compareSnapshots(baseSnapshot, selectionAtTheEndSnapshot, false);
|
||||
ok(results[0], "after appending a character, string should have changed");
|
||||
|
||||
element.value = element.value;
|
||||
var tmpSnapshot = snapshotWindow(window);
|
||||
|
||||
results = compareSnapshots(baseSnapshot, tmpSnapshot, false);
|
||||
ok(results[0], "re-settig the value should change nothing");
|
||||
|
||||
results = compareSnapshots(selectionAtTheEndSnapshot, tmpSnapshot, true);
|
||||
ok(results[0], "re-settig the value should change nothing");
|
||||
|
||||
element.selectionStart = element.selectionEnd = 0;
|
||||
element.blur();
|
||||
|
||||
gTestRunner.next();
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// This test checks that when a textarea has a long list of values and the
|
||||
// textarea's value is then changed, the values are shown correctly.
|
||||
function testCorrectUpdateOnScroll()
|
||||
{
|
||||
var textarea = document.createElement('textarea');
|
||||
textarea.rows = 5;
|
||||
textarea.cols = 10;
|
||||
textarea.value = 'a\nb\nc\nd';
|
||||
document.getElementById('content').appendChild(textarea);
|
||||
|
||||
var baseSnapshot = snapshotWindow(window);
|
||||
|
||||
textarea.value = '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n';
|
||||
textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
|
||||
|
||||
var fullSnapshot = snapshotWindow(window);
|
||||
var results = compareSnapshots(baseSnapshot, fullSnapshot, false);
|
||||
ok(results[0], "sanity check: screenshots should not be the same");
|
||||
|
||||
textarea.value = 'a\nb\nc\nd';
|
||||
|
||||
var tmpSnapshot = snapshotWindow(window);
|
||||
results = compareSnapshots(baseSnapshot, tmpSnapshot, true);
|
||||
ok(results[0], "textarea view should look like the beginning");
|
||||
|
||||
setTimeout(function() {
|
||||
gTestRunner.next();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function* runTest()
|
||||
{
|
||||
test('input');
|
||||
yield undefined;
|
||||
test('textarea');
|
||||
yield undefined;
|
||||
testCorrectUpdateOnScroll();
|
||||
yield undefined;
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
gTestRunner = runTest();
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
gTestRunner.next();
|
||||
});;
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=829606">Mozilla Bug 829606</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<textarea rows='1' cols='5' style='-moz-appearance:none;'>this is a \n long text</textarea>
|
||||
<input size='5' value="this is a very long text" style='-moz-appearance:none;'>
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,206 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
|
||||
-->
|
||||
<head>
|
||||
<title>Test key events for time control</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input id="input" type="time">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Turn off Spatial Navigation because it hijacks arrow keydown events:
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
var testData = [
|
||||
/**
|
||||
* keys: keys to send to the input element.
|
||||
* initialVal: initial value set to the input element.
|
||||
* expectedVal: expected value of the input element after sending the keys.
|
||||
*/
|
||||
{
|
||||
// Type 1030 and select AM.
|
||||
keys: ["1030", "KEY_ArrowDown"],
|
||||
initialVal: "",
|
||||
expectedVal: "10:30"
|
||||
},
|
||||
{
|
||||
// Type 3 in the hour field will automatically advance to the minute field.
|
||||
keys: ["330", "KEY_ArrowDown"],
|
||||
initialVal: "",
|
||||
expectedVal: "03:30"
|
||||
},
|
||||
{
|
||||
// Type 5 in the hour field will automatically advance to the minute field.
|
||||
// Type 7 in the minute field will automatically advance to the AM/PM field.
|
||||
keys: ["57", "KEY_ArrowDown"],
|
||||
initialVal: "",
|
||||
expectedVal: "05:07"
|
||||
},
|
||||
{
|
||||
// Advance to AM/PM field and change to PM.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_ArrowDown"],
|
||||
initialVal: "10:30",
|
||||
expectedVal: "22:30"
|
||||
},
|
||||
{
|
||||
// Right key should do the same thing as TAB key.
|
||||
keys: ["KEY_ArrowRight", "KEY_ArrowRight", "KEY_ArrowDown"],
|
||||
initialVal: "10:30",
|
||||
expectedVal: "22:30"
|
||||
},
|
||||
{
|
||||
// Advance to minute field then back to hour field and decrement.
|
||||
keys: ["KEY_ArrowRight", "KEY_ArrowLeft", "KEY_ArrowDown"],
|
||||
initialVal: "10:30",
|
||||
expectedVal: "09:30"
|
||||
},
|
||||
{
|
||||
// Focus starts on the first field, hour in this case, and increment.
|
||||
keys: ["KEY_ArrowUp"],
|
||||
initialVal: "16:00",
|
||||
expectedVal: "17:00"
|
||||
},
|
||||
{
|
||||
// Advance to minute field and decrement.
|
||||
keys: ["KEY_Tab", "KEY_ArrowDown"],
|
||||
initialVal: "16:00",
|
||||
expectedVal: "16:59"
|
||||
},
|
||||
{
|
||||
// Advance to minute field and increment.
|
||||
keys: ["KEY_Tab", "KEY_ArrowUp"],
|
||||
initialVal: "16:59",
|
||||
expectedVal: "16:00"
|
||||
},
|
||||
{
|
||||
// PageUp on hour field increments hour by 3.
|
||||
keys: ["KEY_PageUp"],
|
||||
initialVal: "05:00",
|
||||
expectedVal: "08:00"
|
||||
},
|
||||
{
|
||||
// PageDown on hour field decrements hour by 3.
|
||||
keys: ["KEY_PageDown"],
|
||||
initialVal: "05:00",
|
||||
expectedVal: "02:00"
|
||||
},
|
||||
{
|
||||
// PageUp on minute field increments minute by 10.
|
||||
keys: ["KEY_Tab", "KEY_PageUp"],
|
||||
initialVal: "14:00",
|
||||
expectedVal: "14:10"
|
||||
},
|
||||
{
|
||||
// PageDown on minute field decrements minute by 10.
|
||||
keys: ["KEY_Tab", "KEY_PageDown"],
|
||||
initialVal: "14:00",
|
||||
expectedVal: "14:50"
|
||||
},
|
||||
{
|
||||
// Home key on hour field sets it to the minimum hour, which is 1 in 12-hour
|
||||
// clock.
|
||||
keys: ["KEY_Home"],
|
||||
initialVal: "03:10",
|
||||
expectedVal: "01:10"
|
||||
},
|
||||
{
|
||||
// End key on hour field sets it to the maximum hour, which is 12 in 12-hour
|
||||
// clock.
|
||||
keys: ["KEY_End"],
|
||||
initialVal: "03:10",
|
||||
expectedVal: "00:10"
|
||||
},
|
||||
{
|
||||
// Home key on minute field sets it to the minimum minute, which is 0.
|
||||
keys: ["KEY_Tab", "KEY_Home"],
|
||||
initialVal: "19:30",
|
||||
expectedVal: "19:00"
|
||||
},
|
||||
{
|
||||
// End key on minute field sets it to the minimum minute, which is 59.
|
||||
keys: ["KEY_Tab", "KEY_End"],
|
||||
initialVal: "19:30",
|
||||
expectedVal: "19:59"
|
||||
},
|
||||
// Second field will show up when needed.
|
||||
{
|
||||
// PageUp on second field increments second by 10.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_PageUp"],
|
||||
initialVal: "08:10:10",
|
||||
expectedVal: "08:10:20"
|
||||
},
|
||||
{
|
||||
// PageDown on second field increments second by 10.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_PageDown"],
|
||||
initialVal: "08:10:10",
|
||||
expectedVal: "08:10:00"
|
||||
},
|
||||
{
|
||||
// Home key on second field sets it to the minimum second, which is 0.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_Home"],
|
||||
initialVal: "16:00:30",
|
||||
expectedVal: "16:00:00"
|
||||
},
|
||||
{
|
||||
// End key on second field sets it to the minimum second, which is 59.
|
||||
keys: ["KEY_Tab", "KEY_Tab", "KEY_End"],
|
||||
initialVal: "16:00:30",
|
||||
expectedVal: "16:00:59"
|
||||
},
|
||||
{
|
||||
// Incomplete value maps to empty .value.
|
||||
keys: ["1"],
|
||||
initialVal: "",
|
||||
expectedVal: ""
|
||||
},
|
||||
];
|
||||
|
||||
function sendKeys(aKeys, aElem) {
|
||||
for (let i = 0; i < aKeys.length; i++) {
|
||||
// Force layout flush between keys to ensure focus is correct.
|
||||
// This shouldn't be necessary; bug 1450219 tracks this.
|
||||
aElem.clientTop;
|
||||
let key = aKeys[i];
|
||||
if (key.startsWith("KEY_")) {
|
||||
synthesizeKey(key);
|
||||
} else {
|
||||
sendString(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
var elem = document.getElementById("input");
|
||||
|
||||
for (let { keys, initialVal, expectedVal } of testData) {
|
||||
elem.focus();
|
||||
elem.value = initialVal;
|
||||
sendKeys(keys, elem);
|
||||
is(elem.value, expectedVal,
|
||||
"Test with " + keys + ", result should be " + expectedVal);
|
||||
elem.value = "";
|
||||
elem.blur();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,134 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1374967
|
||||
-->
|
||||
<head>
|
||||
<title>Test second and millisecond fields in input type=time</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1374967">Mozilla Bug 1374967</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input id="input1" type="time">
|
||||
<input id="input2" type="time" value="12:30:40">
|
||||
<input id="input3" type="time" value="12:30:40.567">
|
||||
<input id="input4" type="time" step="1">
|
||||
<input id="input5" type="time" step="61">
|
||||
<input id="input6" type="time" step="120">
|
||||
<input id="input7" type="time" step="0.01">
|
||||
<input id="input8" type="time" step="0.001">
|
||||
<input id="input9" type="time" step="1.001">
|
||||
<input id="input10" type="time" min="01:30:05">
|
||||
<input id="input11" type="time" min="01:30:05.100">
|
||||
<input id="dummy">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
const NUM_OF_FIELDS_DEFAULT = 3;
|
||||
const NUM_OF_FIELDS_WITH_SECOND = NUM_OF_FIELDS_DEFAULT + 1;
|
||||
const NUM_OF_FIELDS_WITH_MILLISEC = NUM_OF_FIELDS_WITH_SECOND + 1;
|
||||
|
||||
function countNumberOfFields(aElement) {
|
||||
is(aElement.type, "time", "Input element type should be 'time'");
|
||||
|
||||
let inputRect = aElement.getBoundingClientRect();
|
||||
let firstField_X = 15;
|
||||
let firstField_Y = inputRect.height / 2;
|
||||
|
||||
// Make sure to start on the first field.
|
||||
synthesizeMouse(aElement, firstField_X, firstField_Y, {});
|
||||
is(document.activeElement, aElement, "Input element should be focused");
|
||||
|
||||
let n = 0;
|
||||
while (document.activeElement == aElement) {
|
||||
n++;
|
||||
synthesizeKey("KEY_Tab");
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
function test() {
|
||||
// Normal input time element.
|
||||
let elem = document.getElementById("input1");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_DEFAULT, "Default input time");
|
||||
|
||||
// Dynamically changing the value with second part.
|
||||
elem.value = "10:20:30";
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_SECOND,
|
||||
"Input time after changing value with second part");
|
||||
|
||||
// Dynamically changing the step to 1 millisecond.
|
||||
elem.step = "0.001";
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_MILLISEC,
|
||||
"Input time after changing step to 1 millisecond");
|
||||
|
||||
// Input time with value with second part.
|
||||
elem = document.getElementById("input2");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_SECOND,
|
||||
"Input time with value with second part");
|
||||
|
||||
// Input time with value with second and millisecond part.
|
||||
elem = document.getElementById("input3");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_MILLISEC,
|
||||
"Input time with value with second and millisecond part");
|
||||
|
||||
// Input time with step set as 1 second.
|
||||
elem = document.getElementById("input4");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_SECOND,
|
||||
"Input time with step set as 1 second");
|
||||
|
||||
// Input time with step set as 61 seconds.
|
||||
elem = document.getElementById("input5");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_SECOND,
|
||||
"Input time with step set as 61 seconds");
|
||||
|
||||
// Input time with step set as 2 minutes.
|
||||
elem = document.getElementById("input6");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_DEFAULT,
|
||||
"Input time with step set as 2 minutes");
|
||||
|
||||
// Input time with step set as 10 milliseconds.
|
||||
elem = document.getElementById("input7");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_MILLISEC,
|
||||
"Input time with step set as 10 milliseconds");
|
||||
|
||||
// Input time with step set as 100 milliseconds.
|
||||
elem = document.getElementById("input8");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_MILLISEC,
|
||||
"Input time with step set as 100 milliseconds");
|
||||
|
||||
// Input time with step set as 1001 milliseconds.
|
||||
elem = document.getElementById("input9");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_MILLISEC,
|
||||
"Input time with step set as 1001 milliseconds");
|
||||
|
||||
// Input time with min with second part and default step (60 seconds). Note
|
||||
// that step base is min, when there is a min.
|
||||
elem = document.getElementById("input10");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_SECOND,
|
||||
"Input time with min with second part");
|
||||
|
||||
// Input time with min with second and millisecond part and default step (60
|
||||
// seconds). Note that step base is min, when there is a min.
|
||||
elem = document.getElementById("input11");
|
||||
is(countNumberOfFields(elem), NUM_OF_FIELDS_WITH_MILLISEC,
|
||||
"Input time with min with second and millisecond part");
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,121 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=764481
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 764481</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=764481">Mozilla Bug 764481</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none" >
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
var input = document.createElement("input");
|
||||
|
||||
var testData = [
|
||||
{
|
||||
prefs: [["dom.forms.color", false]],
|
||||
inputType: "color",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.forms.color", true]],
|
||||
inputType: "color",
|
||||
expectedType: "color"
|
||||
}, {
|
||||
prefs: [["dom.experimental_forms", false], ["dom.forms.datetime", false]],
|
||||
inputType: "date",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.experimental_forms", true], ["dom.forms.datetime", false]],
|
||||
inputType: "date",
|
||||
expectedType: "date"
|
||||
}, {
|
||||
prefs: [["dom.experimental_forms", false], ["dom.forms.datetime", true]],
|
||||
inputType: "date",
|
||||
expectedType: "date"
|
||||
}, {
|
||||
prefs: [["dom.experimental_forms", false], ["dom.forms.datetime", false]],
|
||||
inputType: "time",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.experimental_forms", true], ["dom.forms.datetime", false]],
|
||||
inputType: "time",
|
||||
expectedType: "time"
|
||||
}, {
|
||||
prefs: [["dom.experimental_forms", false], ["dom.forms.datetime", true]],
|
||||
inputType: "time",
|
||||
expectedType: "time"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", false]],
|
||||
inputType: "month",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", true], ["dom.forms.datetime.others", false]],
|
||||
inputType: "month",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", true]],
|
||||
inputType: "month",
|
||||
expectedType: "month"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", false]],
|
||||
inputType: "week",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", true], ["dom.forms.datetime.others", false]],
|
||||
inputType: "week",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", true]],
|
||||
inputType: "week",
|
||||
expectedType: "week"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", false]],
|
||||
inputType: "datetime-local",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", true], ["dom.forms.datetime.others", false]],
|
||||
inputType: "datetime-local",
|
||||
expectedType: "text"
|
||||
}, {
|
||||
prefs: [["dom.forms.datetime", false], ["dom.forms.datetime.others", true]],
|
||||
inputType: "datetime-local",
|
||||
expectedType: "datetime-local"
|
||||
}
|
||||
];
|
||||
|
||||
function testInputTypePreference(aData) {
|
||||
return SpecialPowers.pushPrefEnv({'set': aData.prefs})
|
||||
.then(() => {
|
||||
// Change the type of input to text and then back to the tested input type,
|
||||
// so that HTMLInputElement::ParseAttribute gets called with the pref enabled.
|
||||
input.type = "text";
|
||||
input.type = aData.inputType;
|
||||
is(input.type, aData.expectedType, "input type should be '" +
|
||||
aData.expectedType + "'' when pref " + aData.prefs + " is set");
|
||||
is(input.getAttribute('type'), aData.inputType,
|
||||
"input 'type' attribute should not change");
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let promise = Promise.resolve();
|
||||
for (let i = 0; i < testData.length; i++) {
|
||||
let data = testData[i];
|
||||
promise = promise.then(() => testInputTypePreference(data));
|
||||
}
|
||||
|
||||
promise.catch(error => ok(false, "Promise reject: " + error))
|
||||
.then(() => SimpleTest.finish());
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,236 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=765772
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 765772</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 765772</a>
|
||||
<p id="display"></p>
|
||||
<iframe name="submit_frame" style="visibility: hidden;"></iframe>
|
||||
<div id="content">
|
||||
<form id='f' target="submit_frame" action="foo">
|
||||
<input name=i id="i" step='any' >
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/*
|
||||
* This test checks that when a user types in some input types, it will not be
|
||||
* in a state where the value will be un-sanitized and usable (by a script).
|
||||
*/
|
||||
|
||||
var input = document.getElementById('i');
|
||||
var form = document.getElementById('f');
|
||||
var submitFrame = document.getElementsByTagName('iframe')[0];
|
||||
var testData = [];
|
||||
var gCurrentTest = null;
|
||||
var gValidData = [];
|
||||
var gInvalidData = [];
|
||||
|
||||
function submitForm() {
|
||||
form.submit();
|
||||
}
|
||||
|
||||
function sendKeyEventToSubmitForm() {
|
||||
sendKey("return");
|
||||
}
|
||||
|
||||
function urlify(aStr) {
|
||||
return aStr.replace(/:/g, '%3A');
|
||||
}
|
||||
|
||||
function runTestsForNextInputType()
|
||||
{
|
||||
let {done} = testRunner.next();
|
||||
if (done) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function checkValueSubmittedIsValid()
|
||||
{
|
||||
is(frames['submit_frame'].location.href,
|
||||
'http://mochi.test:8888/tests/dom/html/test/forms/xbl/foo?i='
|
||||
+ urlify(gValidData[valueIndex++]),
|
||||
"The submitted value should not have been sanitized");
|
||||
|
||||
input.value = "";
|
||||
|
||||
if (valueIndex >= gValidData.length) {
|
||||
if (gCurrentTest.canHaveBadInputValidityState) {
|
||||
// Don't run the submission tests on the invalid input if submission
|
||||
// will be blocked by invalid input.
|
||||
runTestsForNextInputType();
|
||||
return;
|
||||
}
|
||||
valueIndex = 0;
|
||||
submitFrame.onload = checkValueSubmittedIsInvalid;
|
||||
testData = gInvalidData;
|
||||
}
|
||||
testSubmissions();
|
||||
}
|
||||
|
||||
function checkValueSubmittedIsInvalid()
|
||||
{
|
||||
is(frames['submit_frame'].location.href,
|
||||
'http://mochi.test:8888/tests/dom/html/test/forms/xbl/foo?i=',
|
||||
"The submitted value should have been sanitized");
|
||||
|
||||
valueIndex++;
|
||||
input.value = "";
|
||||
|
||||
if (valueIndex >= gInvalidData.length) {
|
||||
if (submitMethod == sendKeyEventToSubmitForm) {
|
||||
runTestsForNextInputType();
|
||||
return;
|
||||
}
|
||||
valueIndex = 0;
|
||||
submitMethod = sendKeyEventToSubmitForm;
|
||||
submitFrame.onload = checkValueSubmittedIsValid;
|
||||
testData = gValidData;
|
||||
}
|
||||
testSubmissions();
|
||||
}
|
||||
|
||||
function testSubmissions() {
|
||||
input.focus();
|
||||
sendString(testData[valueIndex]);
|
||||
submitMethod();
|
||||
}
|
||||
|
||||
var valueIndex = 0;
|
||||
var submitMethod = submitForm;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function* runTest()
|
||||
{
|
||||
SimpleTest.requestLongerTimeout(4);
|
||||
|
||||
var data = [
|
||||
{
|
||||
type: 'number',
|
||||
canHaveBadInputValidityState: true,
|
||||
validData: [
|
||||
"42",
|
||||
"-42", // should work for negative values
|
||||
"42.1234",
|
||||
"123.123456789123", // double precision
|
||||
"1e2", // e should be usable
|
||||
"2e1",
|
||||
"1e-1", // value after e can be negative
|
||||
"1E2", // E can be used instead of e
|
||||
],
|
||||
invalidData: [
|
||||
"e",
|
||||
"e2",
|
||||
"1e0.1",
|
||||
"foo",
|
||||
"42,13", // comma can't be used as a decimal separator
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'month',
|
||||
validData: [
|
||||
'0001-01',
|
||||
'2012-12',
|
||||
'100000-01',
|
||||
],
|
||||
invalidData: [
|
||||
'1-01',
|
||||
'-',
|
||||
'december',
|
||||
'2012-dec',
|
||||
'2012/12',
|
||||
'2012-99',
|
||||
'2012-1',
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'week',
|
||||
validData: [
|
||||
'0001-W01',
|
||||
'1970-W53',
|
||||
'100000-W52',
|
||||
'2016-W30',
|
||||
],
|
||||
invalidData: [
|
||||
'1-W01',
|
||||
'week',
|
||||
'2016-30',
|
||||
'2010-W80',
|
||||
'2000/W30',
|
||||
'1985-W00',
|
||||
'1000-W'
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'datetime-local',
|
||||
validData: [
|
||||
'0001-01-01T00:00',
|
||||
'2016-11-07T16:45',
|
||||
'2016-11-07T16:45:30',
|
||||
'2016-11-07T16:45:30.10',
|
||||
'2016-11-07T16:45:00.111',
|
||||
],
|
||||
invalidData: [
|
||||
'1-01-01T00:00',
|
||||
'1970-01-01T9:30',
|
||||
'2016/11/07T16:45',
|
||||
'2016-11-07T16.45',
|
||||
'T',
|
||||
'datetime-local'
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
for (test of data) {
|
||||
gCurrentTest = test;
|
||||
|
||||
input.type = test.type;
|
||||
gValidData = test.validData;
|
||||
gInvalidData = test.invalidData;
|
||||
|
||||
for (data of gValidData) {
|
||||
input.value = "";
|
||||
input.focus();
|
||||
sendString(data);
|
||||
input.blur();
|
||||
is(input.value, data, "valid user input should not be sanitized");
|
||||
}
|
||||
|
||||
for (data of gInvalidData) {
|
||||
input.value = "";
|
||||
input.focus();
|
||||
sendString(data);
|
||||
input.blur();
|
||||
is(input.value, "", "invalid user input should be sanitized");
|
||||
}
|
||||
|
||||
input.value = '';
|
||||
|
||||
testData = gValidData;
|
||||
valueIndex = 0;
|
||||
submitFrame.onload = checkValueSubmittedIsValid;
|
||||
testSubmissions();
|
||||
yield undefined;
|
||||
}
|
||||
}
|
||||
|
||||
var testRunner = runTest();
|
||||
|
||||
addLoadEvent(function () {
|
||||
testRunner.next();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,84 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=597650
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 597650</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=597650">Mozilla Bug 597650</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<label id="l">
|
||||
<input id="h"></input>
|
||||
<input type="text" id="i"></input>
|
||||
</label>
|
||||
<label id="lh" for="h"></label>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
/** Test for Bug 597650 **/
|
||||
label = document.getElementById("l");
|
||||
labelForH = document.getElementById("lh");
|
||||
inputI = document.getElementById("i");
|
||||
inputH = document.getElementById("h");
|
||||
|
||||
var labelableTypes = ["text", "search", "tel", "url", "email", "password",
|
||||
"datetime", "date", "month", "week", "time",
|
||||
"number", "range", "color", "checkbox", "radio",
|
||||
"file", "submit", "image", "reset", "button"];
|
||||
var nonLabelableTypes = ["hidden"];
|
||||
|
||||
for (var i in labelableTypes) {
|
||||
test(labelableTypes[i], true);
|
||||
}
|
||||
|
||||
for (var i in nonLabelableTypes) {
|
||||
test(nonLabelableTypes[i], false);
|
||||
}
|
||||
|
||||
function test(type, isLabelable) {
|
||||
inputH.type = type;
|
||||
if (isLabelable) {
|
||||
testControl(label, inputH, type, true);
|
||||
testControl(labelForH, inputH, type, true);
|
||||
} else {
|
||||
testControl(label, inputI, type, false);
|
||||
testControl(labelForH, null, type, false);
|
||||
|
||||
inputH.type = "text";
|
||||
testControl(label, inputH, "text", true);
|
||||
testControl(labelForH, inputH, "text", true);
|
||||
|
||||
inputH.type = type;
|
||||
testControl(label, inputI, type, false);
|
||||
testControl(labelForH, null, type, false);
|
||||
|
||||
label.removeChild(inputH);
|
||||
testControl(label, inputI, "text", true);
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = type;
|
||||
label.insertBefore(element, inputI);
|
||||
testControl(label, inputI, "text", true);
|
||||
}
|
||||
}
|
||||
|
||||
function testControl(label, control, type, labelable) {
|
||||
if (labelable) {
|
||||
is(label.control, control, "Input controls of type " + type
|
||||
+ " should be labeled");
|
||||
} else {
|
||||
is(label.control, control, "Input controls of type " + type
|
||||
+ " should be ignored by <label>");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,473 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=635499
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 635499</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 635499 **/
|
||||
|
||||
var data = [
|
||||
{ type: 'hidden', apply: false },
|
||||
{ type: 'text', apply: false },
|
||||
{ type: 'search', apply: false },
|
||||
{ type: 'tel', apply: false },
|
||||
{ type: 'url', apply: false },
|
||||
{ type: 'email', apply: false },
|
||||
{ type: 'password', apply: false },
|
||||
{ type: 'date', apply: true },
|
||||
{ type: 'month', apply: true },
|
||||
{ type: 'week', apply: true },
|
||||
{ type: 'time', apply: true },
|
||||
{ type: 'datetime-local', apply: true },
|
||||
{ type: 'number', apply: true },
|
||||
{ type: 'range', apply: true },
|
||||
{ type: 'color', apply: false },
|
||||
{ type: 'checkbox', apply: false },
|
||||
{ type: 'radio', apply: false },
|
||||
{ type: 'file', apply: false },
|
||||
{ type: 'submit', apply: false },
|
||||
{ type: 'image', apply: false },
|
||||
{ type: 'reset', apply: false },
|
||||
{ type: 'button', apply: false },
|
||||
];
|
||||
|
||||
var input = document.createElement("input");
|
||||
document.getElementById('content').appendChild(input);
|
||||
|
||||
/**
|
||||
* @aValidity - boolean indicating whether the element is expected to be valid
|
||||
* (aElement.validity.valid is true) or not. The value passed is ignored and
|
||||
* overridden with true if aApply is false.
|
||||
* @aApply - boolean indicating whether the min/max attributes apply to this
|
||||
* element type.
|
||||
* @aRangeApply - A boolean that's set to true if the current input type is a
|
||||
* "[candidate] for constraint validation" and it "[has] range limitations"
|
||||
* per http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-in-range
|
||||
* (in other words, one of the pseudo classes :in-range and :out-of-range
|
||||
* should apply (which, depends on aValidity)).
|
||||
* Else (neither :in-range or :out-of-range should match) set to false.
|
||||
*/
|
||||
function checkValidity(aElement, aValidity, aApply, aRangeApply)
|
||||
{
|
||||
aValidity = aApply ? aValidity : true;
|
||||
|
||||
is(aElement.validity.valid, aValidity,
|
||||
"element validity should be " + aValidity);
|
||||
is(aElement.validity.rangeOverflow, !aValidity,
|
||||
"element overflow status should be " + !aValidity);
|
||||
var overflowMsg =
|
||||
(aElement.type == "date" || aElement.type == "time" ||
|
||||
aElement.type == "month" || aElement.type == "week" ||
|
||||
aElement.type == "datetime-local") ?
|
||||
("Please select a value that is no later than " + aElement.max + ".") :
|
||||
("Please select a value that is no more than " + aElement.max + ".");
|
||||
is(aElement.validationMessage,
|
||||
aValidity ? "" : overflowMsg, "Checking range overflow validation message");
|
||||
|
||||
is(aElement.matches(":valid"), aElement.willValidate && aValidity,
|
||||
(aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
|
||||
is(aElement.matches(":invalid"), aElement.willValidate && !aValidity,
|
||||
(aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
|
||||
|
||||
if (!aRangeApply) {
|
||||
ok(!aElement.matches(":in-range"), ":in-range should not match");
|
||||
ok(!aElement.matches(":out-of-range"),
|
||||
":out-of-range should not match");
|
||||
} else {
|
||||
is(aElement.matches(":in-range"), aValidity,
|
||||
":in-range matches status should be " + aValidity);
|
||||
is(aElement.matches(":out-of-range"), !aValidity,
|
||||
":out-of-range matches status should be " + !aValidity);
|
||||
}
|
||||
}
|
||||
|
||||
for (var test of data) {
|
||||
input.type = test.type;
|
||||
var apply = test.apply;
|
||||
|
||||
// The element should be valid. Range should not apply when @min and @max are
|
||||
// undefined, except if the input type is 'range' (since that type has a
|
||||
// default minimum and maximum).
|
||||
if (input.type == 'range') {
|
||||
checkValidity(input, true, apply, true);
|
||||
} else {
|
||||
checkValidity(input, true, apply, false);
|
||||
}
|
||||
checkValidity(input, true, apply, test.type == 'range');
|
||||
|
||||
switch (input.type) {
|
||||
case 'hidden':
|
||||
case 'text':
|
||||
case 'search':
|
||||
case 'password':
|
||||
case 'url':
|
||||
case 'tel':
|
||||
case 'email':
|
||||
case 'number':
|
||||
case 'checkbox':
|
||||
case 'radio':
|
||||
case 'file':
|
||||
case 'submit':
|
||||
case 'reset':
|
||||
case 'button':
|
||||
case 'image':
|
||||
case 'color':
|
||||
input.max = '-1';
|
||||
break;
|
||||
case 'date':
|
||||
input.max = '2012-06-27';
|
||||
break;
|
||||
case 'time':
|
||||
input.max = '02:20';
|
||||
break;
|
||||
case 'range':
|
||||
// range is special, since setting max to -1 will make it invalid since
|
||||
// it's default would then be 0, meaning it suffers from overflow.
|
||||
input.max = '-1';
|
||||
checkValidity(input, false, apply, apply);
|
||||
// Now make it something that won't cause an error below:
|
||||
input.max = '10';
|
||||
break;
|
||||
case 'month':
|
||||
input.max = '2016-12';
|
||||
break;
|
||||
case 'week':
|
||||
input.max = '2016-W39';
|
||||
break;
|
||||
case 'datetime-local':
|
||||
input.max = '2016-12-31T23:59:59';
|
||||
break;
|
||||
default:
|
||||
ok(false, 'please, add a case for this new type (' + input.type + ')');
|
||||
}
|
||||
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
switch (input.type) {
|
||||
case 'text':
|
||||
case 'hidden':
|
||||
case 'search':
|
||||
case 'password':
|
||||
case 'tel':
|
||||
case 'radio':
|
||||
case 'checkbox':
|
||||
case 'reset':
|
||||
case 'button':
|
||||
case 'submit':
|
||||
case 'image':
|
||||
input.value = '0';
|
||||
checkValidity(input, true, apply, apply);
|
||||
break;
|
||||
case 'url':
|
||||
input.value = 'http://mozilla.org';
|
||||
checkValidity(input, true, apply, apply);
|
||||
break;
|
||||
case 'email':
|
||||
input.value = 'foo@bar.com';
|
||||
checkValidity(input, true, apply, apply);
|
||||
break;
|
||||
case 'file':
|
||||
var file = new File([''], '635499_file');
|
||||
|
||||
SpecialPowers.wrap(input).mozSetFileArray([file]);
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
break;
|
||||
case 'date':
|
||||
input.max = '2012-06-27';
|
||||
input.value = '2012-06-26';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2012-06-27';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2012-06-28';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '2012-06-30';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2012-07-05';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '1000-01-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '20120-01-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '0050-01-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '0049-01-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.max = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.max = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
break;
|
||||
case 'number':
|
||||
input.max = '2';
|
||||
input.value = '1';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '3';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '5';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '42';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.max = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
// Check that we correctly convert input.max to a double in validationMessage.
|
||||
if (input.type == 'number') {
|
||||
input.max = "4.333333333333333333333333333333333331";
|
||||
input.value = "5";
|
||||
is(input.validationMessage,
|
||||
"Please select a value that is no more than 4.33333333333333.",
|
||||
"validation message");
|
||||
}
|
||||
|
||||
break;
|
||||
case 'range':
|
||||
input.max = '2';
|
||||
input.value = '1';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '3';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
is(input.value, input.max, "the value should have been set to max");
|
||||
|
||||
input.max = '5';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '42';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
is(input.value, input.max, "the value should have been set to max");
|
||||
|
||||
input.max = '';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.max = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
// Check that we correctly convert input.max to a double in validationMessage.
|
||||
input.step = 'any';
|
||||
input.min = 5;
|
||||
input.max = 0.66666666666666666666666666666666666
|
||||
input.value = 1;
|
||||
is(input.validationMessage,
|
||||
"Please select a value that is no more than 0.666666666666667.",
|
||||
"validation message")
|
||||
|
||||
break;
|
||||
case 'time':
|
||||
// Don't worry about that.
|
||||
input.step = 'any';
|
||||
|
||||
input.max = '10:10';
|
||||
input.value = '10:09';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '10:10';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '10:10:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '10:10:00.000';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '10:11';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '10:10:00.001';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '01:00:00.01';
|
||||
input.value = '01:00:00.001';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '01:00:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '01:00:00.1';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.max = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
break;
|
||||
case 'month':
|
||||
input.value = '2016-06';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-12';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2017-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '2017-07';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2017-12';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '1000-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '20160-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '0050-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '0049-12';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.max = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.max = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
break;
|
||||
case 'week':
|
||||
input.value = '2016-W01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-W39';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2017-W01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '2017-W01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2017-W52';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '1000-W01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2100-W01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '0050-W01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '0049-W52';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.max = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.max = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
break;
|
||||
case 'datetime-local':
|
||||
input.value = '2016-01-01T12:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-12-31T23:59:59';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-12-31T23:59:59.123';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '2017-01-01T10:00';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '2017-01-01T10:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2017-01-01T10:00:30';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '1000-01-01T12:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2100-01-01T12:00';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.max = '0050-12-31T23:59:59.999';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '0050-12-31T23:59:59';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.max = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.max = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Cleaning up,
|
||||
input.removeAttribute('max');
|
||||
input.value = '';
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,473 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=635553
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 635553</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 635553 **/
|
||||
|
||||
var data = [
|
||||
{ type: 'hidden', apply: false },
|
||||
{ type: 'text', apply: false },
|
||||
{ type: 'search', apply: false },
|
||||
{ type: 'tel', apply: false },
|
||||
{ type: 'url', apply: false },
|
||||
{ type: 'email', apply: false },
|
||||
{ type: 'password', apply: false },
|
||||
{ type: 'date', apply: true },
|
||||
{ type: 'month', apply: true },
|
||||
{ type: 'week', apply: true },
|
||||
{ type: 'time', apply: true },
|
||||
{ type: 'datetime-local', apply: true },
|
||||
{ type: 'number', apply: true },
|
||||
{ type: 'range', apply: true },
|
||||
{ type: 'color', apply: false },
|
||||
{ type: 'checkbox', apply: false },
|
||||
{ type: 'radio', apply: false },
|
||||
{ type: 'file', apply: false },
|
||||
{ type: 'submit', apply: false },
|
||||
{ type: 'image', apply: false },
|
||||
{ type: 'reset', apply: false },
|
||||
{ type: 'button', apply: false },
|
||||
];
|
||||
|
||||
var input = document.createElement("input");
|
||||
document.getElementById('content').appendChild(input);
|
||||
|
||||
/**
|
||||
* @aValidity - boolean indicating whether the element is expected to be valid
|
||||
* (aElement.validity.valid is true) or not. The value passed is ignored and
|
||||
* overridden with true if aApply is false.
|
||||
* @aApply - boolean indicating whether the min/max attributes apply to this
|
||||
* element type.
|
||||
* @aRangeApply - A boolean that's set to true if the current input type is a
|
||||
* "[candidate] for constraint validation" and it "[has] range limitations"
|
||||
* per http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-in-range
|
||||
* (in other words, one of the pseudo classes :in-range and :out-of-range
|
||||
* should apply (which, depends on aValidity)).
|
||||
* Else (neither :in-range or :out-of-range should match) set to false.
|
||||
*/
|
||||
function checkValidity(aElement, aValidity, aApply, aRangeApply)
|
||||
{
|
||||
aValidity = aApply ? aValidity : true;
|
||||
|
||||
is(aElement.validity.valid, aValidity,
|
||||
"element validity should be " + aValidity);
|
||||
is(aElement.validity.rangeUnderflow, !aValidity,
|
||||
"element underflow status should be " + !aValidity);
|
||||
var underflowMsg =
|
||||
(aElement.type == "date" || aElement.type == "time" ||
|
||||
aElement.type == "month" || aElement.type == "week" ||
|
||||
aElement.type == "datetime-local") ?
|
||||
("Please select a value that is no earlier than " + aElement.min + ".") :
|
||||
("Please select a value that is no less than " + aElement.min + ".");
|
||||
is(aElement.validationMessage,
|
||||
aValidity ? "" : underflowMsg, "Checking range underflow validation message");
|
||||
|
||||
is(aElement.matches(":valid"), aElement.willValidate && aValidity,
|
||||
(aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
|
||||
is(aElement.matches(":invalid"), aElement.willValidate && !aValidity,
|
||||
(aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
|
||||
|
||||
if (!aRangeApply) {
|
||||
ok(!aElement.matches(":in-range"), ":in-range should not match");
|
||||
ok(!aElement.matches(":out-of-range"),
|
||||
":out-of-range should not match");
|
||||
} else {
|
||||
is(aElement.matches(":in-range"), aValidity,
|
||||
":in-range matches status should be " + aValidity);
|
||||
is(aElement.matches(":out-of-range"), !aValidity,
|
||||
":out-of-range matches status should be " + !aValidity);
|
||||
}
|
||||
}
|
||||
|
||||
for (var test of data) {
|
||||
input.type = test.type;
|
||||
var apply = test.apply;
|
||||
|
||||
if (test.todo) {
|
||||
todo_is(input.type, test.type, test.type + " isn't implemented yet");
|
||||
continue;
|
||||
}
|
||||
|
||||
// The element should be valid. Range should not apply when @min and @max are
|
||||
// undefined, except if the input type is 'range' (since that type has a
|
||||
// default minimum and maximum).
|
||||
if (input.type == 'range') {
|
||||
checkValidity(input, true, apply, true);
|
||||
} else {
|
||||
checkValidity(input, true, apply, false);
|
||||
}
|
||||
|
||||
switch (input.type) {
|
||||
case 'hidden':
|
||||
case 'text':
|
||||
case 'search':
|
||||
case 'password':
|
||||
case 'url':
|
||||
case 'tel':
|
||||
case 'email':
|
||||
case 'number':
|
||||
case 'checkbox':
|
||||
case 'radio':
|
||||
case 'file':
|
||||
case 'submit':
|
||||
case 'reset':
|
||||
case 'button':
|
||||
case 'image':
|
||||
case 'color':
|
||||
input.min = '999';
|
||||
break;
|
||||
case 'date':
|
||||
input.min = '2012-06-27';
|
||||
break;
|
||||
case 'time':
|
||||
input.min = '20:20';
|
||||
break;
|
||||
case 'range':
|
||||
// range is special, since setting min to 999 will make it invalid since
|
||||
// it's default maximum is 100, its value would be 999, and it would
|
||||
// suffer from overflow.
|
||||
break;
|
||||
case 'month':
|
||||
input.min = '2016-06';
|
||||
break;
|
||||
case 'week':
|
||||
input.min = '2016-W39';
|
||||
break;
|
||||
case 'datetime-local':
|
||||
input.min = '2017-01-01T00:00';
|
||||
break;
|
||||
default:
|
||||
ok(false, 'please, add a case for this new type (' + input.type + ')');
|
||||
}
|
||||
|
||||
// The element should still be valid and range should apply if it can.
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
switch (input.type) {
|
||||
case 'text':
|
||||
case 'hidden':
|
||||
case 'search':
|
||||
case 'password':
|
||||
case 'tel':
|
||||
case 'radio':
|
||||
case 'checkbox':
|
||||
case 'reset':
|
||||
case 'button':
|
||||
case 'submit':
|
||||
case 'image':
|
||||
case 'color':
|
||||
input.value = '0';
|
||||
checkValidity(input, true, apply, apply);
|
||||
break;
|
||||
case 'url':
|
||||
input.value = 'http://mozilla.org';
|
||||
checkValidity(input, true, apply, apply);
|
||||
break;
|
||||
case 'email':
|
||||
input.value = 'foo@bar.com';
|
||||
checkValidity(input, true, apply, apply);
|
||||
break;
|
||||
case 'file':
|
||||
var file = new File([''], '635499_file');
|
||||
|
||||
SpecialPowers.wrap(input).mozSetFileArray([file]);
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
break;
|
||||
case 'date':
|
||||
input.value = '2012-06-28';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2012-06-27';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2012-06-26';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '2012-02-29';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2012-02-28';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '1000-01-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '20120-01-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.min = '0050-01-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '0049-01-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.min = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
break;
|
||||
case 'number':
|
||||
input.min = '0';
|
||||
input.value = '1';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '0';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '-1';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '-1';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '-42';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.min = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
// Check that we correctly convert input.min to a double in
|
||||
// validationMessage.
|
||||
input.min = "4.333333333333333333333333333333333331";
|
||||
input.value = "2";
|
||||
is(input.validationMessage,
|
||||
"Please select a value that is no less than 4.33333333333333.",
|
||||
"validation message");
|
||||
break;
|
||||
case 'range':
|
||||
input.min = '0';
|
||||
input.value = '1';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '0';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '-1';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
is(input.value, input.min, "the value should have been set to min");
|
||||
|
||||
input.min = '-1';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '-42';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
is(input.value, input.min, "the value should have been set to min");
|
||||
|
||||
input.min = '';
|
||||
checkValidity(input, true, apply, true);
|
||||
|
||||
input.min = 'foo';
|
||||
checkValidity(input, true, apply, true);
|
||||
|
||||
// We don't check the conversion of input.min to a double in
|
||||
// validationMessage for 'range' since range will always clamp the value
|
||||
// up to at least the minimum (so we will never see the min in a
|
||||
// validationMessage).
|
||||
|
||||
break;
|
||||
case 'time':
|
||||
// Don't worry about that.
|
||||
input.step = 'any';
|
||||
|
||||
input.min = '20:20';
|
||||
input.value = '20:20:01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '20:20:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '10:00';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '20:20:00.001';
|
||||
input.value = '20:20';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '00:00';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '23:59';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '20:20:01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '20:20:00.01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '20:20:00.1';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.min = '00:00:00';
|
||||
input.value = '01:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '00:00:00.000';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.min = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.min = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
break;
|
||||
case 'month':
|
||||
input.value = '2016-07';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-06';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-05';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '2016-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2015-12';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '1000-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '10000-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.min = '0010-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '0001-01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.min = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
break;
|
||||
case 'week':
|
||||
input.value = '2016-W40';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-W39';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-W38';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '2016-W01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2015-W53';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '1000-W01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '10000-01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.min = '0010-W01';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '0001-W01';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.min = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
break;
|
||||
case 'datetime-local':
|
||||
input.value = '2017-12-31T23:59';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2017-01-01T00:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2017-01-01T00:00:00.123';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = 'foo';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2016-12-31T23:59';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '2016-01-01T00:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '2015-12-31T23:59';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '1000-01-01T00:00';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.value = '10000-01-01T00:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.min = '0010-01-01T12:00';
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
input.value = '0010-01-01T10:00';
|
||||
checkValidity(input, false, apply, apply);
|
||||
|
||||
input.min = '';
|
||||
checkValidity(input, true, apply, false);
|
||||
|
||||
input.min = 'foo';
|
||||
checkValidity(input, true, apply, false);
|
||||
break;
|
||||
default:
|
||||
ok(false, 'write tests for ' + input.type);
|
||||
}
|
||||
|
||||
// Cleaning up,
|
||||
input.removeAttribute('min');
|
||||
input.value = '';
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,111 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=565538
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 565538</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=565538">Mozilla Bug 565538</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 565538 **/
|
||||
|
||||
var gElementTestData = [
|
||||
/* element result */
|
||||
['input', true],
|
||||
['button', false],
|
||||
['fieldset', false],
|
||||
['label', false],
|
||||
['option', false],
|
||||
['optgroup', false],
|
||||
['output', false],
|
||||
['legend', false],
|
||||
['select', false],
|
||||
['textarea', false],
|
||||
['object', false],
|
||||
];
|
||||
|
||||
var gInputTestData = [
|
||||
/* type result */
|
||||
['password', true],
|
||||
['tel', true],
|
||||
['text', true],
|
||||
['button', false],
|
||||
['checkbox', false],
|
||||
['file', false],
|
||||
['hidden', false],
|
||||
['reset', false],
|
||||
['image', false],
|
||||
['radio', false],
|
||||
['submit', false],
|
||||
['search', true],
|
||||
['email', true],
|
||||
['url', true],
|
||||
['number', false],
|
||||
['range', false],
|
||||
['date', false],
|
||||
['time', false],
|
||||
['color', false],
|
||||
['month', false],
|
||||
['week', false],
|
||||
['datetime-local', false],
|
||||
];
|
||||
|
||||
function checkMozIsTextFieldDefined(aElement, aResult)
|
||||
{
|
||||
var element = document.createElement(aElement);
|
||||
|
||||
var msg = "mozIsTextField should be "
|
||||
if (aResult) {
|
||||
msg += "defined";
|
||||
} else {
|
||||
msg += "undefined";
|
||||
}
|
||||
|
||||
is('mozIsTextField' in element, aResult, msg);
|
||||
}
|
||||
|
||||
function checkMozIsTextFieldValue(aInput, aResult)
|
||||
{
|
||||
is(aInput.mozIsTextField(false), aResult,
|
||||
"mozIsTextField(false) should return " + aResult);
|
||||
|
||||
if (aInput.type == 'password') {
|
||||
ok(!aInput.mozIsTextField(true),
|
||||
"mozIsTextField(true) should return false for password");
|
||||
} else {
|
||||
is(aInput.mozIsTextField(true), aResult,
|
||||
"mozIsTextField(true) should return " + aResult);
|
||||
}
|
||||
}
|
||||
|
||||
function checkMozIsTextFieldValueTodo(aInput, aResult)
|
||||
{
|
||||
todo_is(aInput.mozIsTextField(false), aResult,
|
||||
"mozIsTextField(false) should return " + aResult);
|
||||
todo_is(aInput.mozIsTextField(true), aResult,
|
||||
"mozIsTextField(true) should return " + aResult);
|
||||
}
|
||||
|
||||
// Check if the method is defined for the correct elements.
|
||||
for (data of gElementTestData) {
|
||||
checkMozIsTextFieldDefined(data[0], data[1]);
|
||||
}
|
||||
|
||||
// Check if the method returns the correct value.
|
||||
var input = document.createElement('input');
|
||||
for (data of gInputTestData) {
|
||||
input.type = data[0];
|
||||
checkMozIsTextFieldValue(input, data[1]);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,84 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=556013
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 556013</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=556013">Mozilla Bug 556013</a>
|
||||
<p id="display"></p>
|
||||
<iframe style='width:50px; height: 50px;' name='t'></iframe>
|
||||
<div id="content">
|
||||
<form target='t' action='data:text/html,' novalidate>
|
||||
<input id='av' required>
|
||||
<input id='a' type='submit'>
|
||||
</form>
|
||||
<form target='t' action='data:text/html,' novalidate>
|
||||
<input id='bv' type='checkbox' required>
|
||||
<button id='b' type='submit'></button>
|
||||
</form>
|
||||
<form target='t' action='data:text/html,' novalidate>
|
||||
<input id='c' required>
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 556013 **/
|
||||
|
||||
/**
|
||||
* novalidate should prevent form validation, thus not blocking form submission.
|
||||
*
|
||||
* NOTE: if there is no invalidformsubmit observer, the form submission will
|
||||
* never be blocked and this test might be a false-positive but that should not
|
||||
* be a problem.
|
||||
*/
|
||||
document.forms[0].addEventListener("submit", function(aEvent) {
|
||||
ok(true, "novalidate has been correctly used for first form");
|
||||
document.getElementById('b').click();
|
||||
}, {once: true});
|
||||
|
||||
document.forms[1].addEventListener("submit", function(aEvent) {
|
||||
ok(true, "novalidate has been correctly used for second form");
|
||||
var c = document.getElementById('c');
|
||||
c.focus();
|
||||
synthesizeKey("KEY_Enter");
|
||||
}, {once: true});
|
||||
|
||||
document.forms[2].addEventListener("submit", function(aEvent) {
|
||||
ok(true, "novalidate has been correctly used for third form");
|
||||
SimpleTest.executeSoon(SimpleTest.finish);
|
||||
}, {once: true});
|
||||
|
||||
/**
|
||||
* We have to be sure invalid events are not send too.
|
||||
* They should be sent before the submit event so we can just create a test
|
||||
* failure if we got one. All of them should be catched if sent.
|
||||
* At worst, we got random green which isn't harmful.
|
||||
*/
|
||||
function invalidHandling(aEvent)
|
||||
{
|
||||
aEvent.target.removeEventListener("invalid", invalidHandling);
|
||||
ok(false, "invalid event should not be sent");
|
||||
}
|
||||
|
||||
document.getElementById('av').addEventListener("invalid", invalidHandling);
|
||||
document.getElementById('bv').addEventListener("invalid", invalidHandling);
|
||||
document.getElementById('c').addEventListener("invalid", invalidHandling);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// This is going to call all the tests (with a chain reaction).
|
||||
SimpleTest.waitForFocus(function() {
|
||||
document.getElementById('a').click();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,324 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=345512
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 345512</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
input { background-color: rgb(0,0,0) !important; }
|
||||
input:valid { background-color: rgb(0,255,0) !important; }
|
||||
input:invalid { background-color: rgb(255,0,0) !important; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345512">Mozilla Bug 345512</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<input id='i' pattern="tulip" oninvalid="invalidEventHandler(event);">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 345512 **/
|
||||
|
||||
var gInvalid = false;
|
||||
|
||||
function invalidEventHandler(e)
|
||||
{
|
||||
is(e.type, "invalid", "Invalid event type should be invalid");
|
||||
gInvalid = true;
|
||||
}
|
||||
|
||||
function completeValidityCheck(element, alwaysValid, isBarred)
|
||||
{
|
||||
// Check when pattern matches.
|
||||
if (element.type == 'email') {
|
||||
element.pattern = ".*@bar.com";
|
||||
element.value = "foo@bar.com";
|
||||
} else if (element.type == 'url') {
|
||||
element.pattern = "http://.*\\.com$";
|
||||
element.value = "http://mozilla.com";
|
||||
} else if (element.type == 'file') {
|
||||
element.pattern = "foo";
|
||||
SpecialPowers.wrap(element).mozSetFileArray([new File(["foo"], "foo")]);
|
||||
} else {
|
||||
element.pattern = "foo";
|
||||
element.value = "foo";
|
||||
}
|
||||
|
||||
checkValidPattern(element, true, isBarred);
|
||||
|
||||
// Check when pattern does not match.
|
||||
|
||||
if (element.type == 'email') {
|
||||
element.pattern = ".*@bar.com";
|
||||
element.value = "foo@foo.com";
|
||||
} else if (element.type == 'url') {
|
||||
element.pattern = "http://.*\\.com$";
|
||||
element.value = "http://mozilla.org";
|
||||
} else if (element.type == 'file') {
|
||||
element.pattern = "foo";
|
||||
SpecialPowers.wrap(element).mozSetFileArray([new File(["bar"], "bar")]);
|
||||
} else {
|
||||
element.pattern = "foo";
|
||||
element.value = "bar";
|
||||
}
|
||||
|
||||
if (!alwaysValid) {
|
||||
checkInvalidPattern(element, true);
|
||||
} else {
|
||||
checkValidPattern(element, true, isBarred);
|
||||
}
|
||||
}
|
||||
|
||||
function checkValidPattern(element, completeCheck, isBarred)
|
||||
{
|
||||
if (completeCheck) {
|
||||
gInvalid = false;
|
||||
|
||||
ok(!element.validity.patternMismatch,
|
||||
"Element should not suffer from pattern mismatch");
|
||||
ok(element.validity.valid, "Element should be valid");
|
||||
ok(element.checkValidity(), "Element should be valid");
|
||||
ok(!gInvalid, "Invalid event shouldn't have been thrown");
|
||||
is(element.validationMessage, '',
|
||||
"Validation message should be the empty string");
|
||||
if (element.type != 'radio' && element.type != 'checkbox') {
|
||||
is(window.getComputedStyle(element).getPropertyValue('background-color'),
|
||||
isBarred ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
|
||||
"The pseudo-class is not correctly applied");
|
||||
}
|
||||
} else {
|
||||
ok(!element.validity.patternMismatch,
|
||||
"Element should not suffer from pattern mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
function checkInvalidPattern(element, completeCheck)
|
||||
{
|
||||
if (completeCheck) {
|
||||
gInvalid = false;
|
||||
|
||||
ok(element.validity.patternMismatch,
|
||||
"Element should suffer from pattern mismatch");
|
||||
ok(!element.validity.valid, "Element should not be valid");
|
||||
ok(!element.checkValidity(), "Element should not be valid");
|
||||
ok(gInvalid, "Invalid event should have been thrown");
|
||||
is(element.validationMessage,
|
||||
"Please match the requested format.",
|
||||
"Validation message is not valid");
|
||||
} else {
|
||||
ok(element.validity.patternMismatch,
|
||||
"Element should suffer from pattern mismatch");
|
||||
}
|
||||
|
||||
if (element.type != 'radio' && element.type != 'checkbox') {
|
||||
is(window.getComputedStyle(element).getPropertyValue('background-color'),
|
||||
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||
}
|
||||
}
|
||||
|
||||
function checkSyntaxError(element)
|
||||
{
|
||||
ok(!element.validity.patternMismatch,
|
||||
"On SyntaxError, element should not suffer");
|
||||
}
|
||||
|
||||
function checkPatternValidity(element)
|
||||
{
|
||||
element.pattern = "foo";
|
||||
|
||||
element.value = '';
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "foo";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "bar";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.value = "foobar";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.value = "foofoo";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.pattern = "foo\"bar";
|
||||
element.value = "foo\"bar";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = 'foo"bar';
|
||||
checkValidPattern(element);
|
||||
|
||||
element.pattern = "foo'bar";
|
||||
element.value = "foo\'bar";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.pattern = "foo\\(bar";
|
||||
element.value = "foo(bar";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "foo";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.pattern = "foo\\)bar";
|
||||
element.value = "foo)bar";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "foo";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
// Check for 'i' flag disabled. Should be case sensitive.
|
||||
element.value = "Foo";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
// We can't check for the 'g' flag because we only test, we don't execute.
|
||||
// We can't check for the 'm' flag because .value shouldn't contain line breaks.
|
||||
|
||||
// We need '\\\\' because '\\' will produce '\\' and we want to escape the '\'
|
||||
// for the regexp.
|
||||
element.pattern = "foo\\\\bar";
|
||||
element.value = "foo\\bar";
|
||||
checkValidPattern(element);
|
||||
|
||||
// We may want to escape the ' in the pattern, but this is a SyntaxError
|
||||
// when unicode flag is set.
|
||||
element.pattern = "foo\\'bar";
|
||||
element.value = "foo'bar";
|
||||
checkSyntaxError(element);
|
||||
element.value = "baz";
|
||||
checkSyntaxError(element);
|
||||
|
||||
// We should check the pattern attribute do not pollute |RegExp.lastParen|.
|
||||
is(RegExp.lastParen, "", "RegExp.lastParen should be the empty string");
|
||||
|
||||
element.pattern = "(foo)";
|
||||
element.value = "foo";
|
||||
checkValidPattern(element);
|
||||
is(RegExp.lastParen, "", "RegExp.lastParen should be the empty string");
|
||||
|
||||
// That may sound weird but the empty string is a valid pattern value.
|
||||
element.pattern = "";
|
||||
element.value = "";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "foo";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
// Checking some complex patterns. As we are using js regexp mechanism, these
|
||||
// tests doesn't aim to test the regexp mechanism.
|
||||
element.pattern = "\\d{2}\\s\\d{2}\\s\\d{4}"
|
||||
element.value = "01 01 2010"
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "01/01/2010"
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.pattern = "[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z_+])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9}";
|
||||
element.value = "foo@bar.com";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "...@bar.com";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.pattern = "^(?:\\w{3,})$";
|
||||
element.value = "foo";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "f";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
// If @title is specified, it should be added in the validation message.
|
||||
if (element.type == 'email') {
|
||||
element.pattern = "foo@bar.com"
|
||||
element.value = "bar@foo.com";
|
||||
} else if (element.type == 'url') {
|
||||
element.pattern = "http://mozilla.com";
|
||||
element.value = "http://mozilla.org";
|
||||
} else {
|
||||
element.pattern = "foo";
|
||||
element.value = "bar";
|
||||
}
|
||||
element.title = "this is an explanation of the regexp";
|
||||
is(element.validationMessage,
|
||||
"Please match the requested format: " + element.title + ".",
|
||||
"Validation message is not valid");
|
||||
element.title = "";
|
||||
is(element.validationMessage,
|
||||
"Please match the requested format.",
|
||||
"Validation message is not valid");
|
||||
|
||||
element.pattern = "foo";
|
||||
if (element.type == 'email') {
|
||||
element.value = "bar@foo.com";
|
||||
} else if (element.type == 'url') {
|
||||
element.value = "http://mozilla.org";
|
||||
} else {
|
||||
element.value = "bar";
|
||||
}
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.removeAttribute('pattern');
|
||||
checkValidPattern(element, true);
|
||||
|
||||
// Unicode pattern
|
||||
for (var pattern of ["\\u{1F438}{2}", "\u{1F438}{2}",
|
||||
"\\uD83D\\uDC38{2}", "\uD83D\uDC38{2}",
|
||||
"\u{D83D}\u{DC38}{2}"]) {
|
||||
element.pattern = pattern;
|
||||
|
||||
element.value = "\u{1F438}\u{1F438}";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "\uD83D\uDC38\uD83D\uDC38";
|
||||
checkValidPattern(element);
|
||||
|
||||
element.value = "\uD83D\uDC38\uDC38";
|
||||
checkInvalidPattern(element);
|
||||
}
|
||||
|
||||
element.pattern = "\\u{D83D}\\u{DC38}{2}";
|
||||
|
||||
element.value = "\u{1F438}\u{1F438}";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.value = "\uD83D\uDC38\uD83D\uDC38";
|
||||
checkInvalidPattern(element);
|
||||
|
||||
element.value = "\uD83D\uDC38\uDC38";
|
||||
checkInvalidPattern(element);
|
||||
}
|
||||
|
||||
var input = document.getElementById('i');
|
||||
|
||||
// |validTypes| are the types which accept @pattern
|
||||
// and |invalidTypes| are the ones which do not accept it.
|
||||
var validTypes = Array('text', 'password', 'search', 'tel', 'email', 'url');
|
||||
var barredTypes = Array('hidden', 'reset', 'button');
|
||||
var invalidTypes = Array('checkbox', 'radio', 'file', 'number', 'range', 'date',
|
||||
'time', 'color', 'submit', 'image', 'month', 'week',
|
||||
'datetime-local');
|
||||
|
||||
for (type of validTypes) {
|
||||
input.type = type;
|
||||
completeValidityCheck(input, false);
|
||||
checkPatternValidity(input);
|
||||
}
|
||||
|
||||
for (type of barredTypes) {
|
||||
input.type = type;
|
||||
completeValidityCheck(input, true, true);
|
||||
}
|
||||
|
||||
for (type of invalidTypes) {
|
||||
input.type = type;
|
||||
completeValidityCheck(input, true);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,420 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=345822
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 345822</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345822">Mozilla Bug 345822</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<form>
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 345822 **/
|
||||
|
||||
function checkNotSufferingFromBeingMissing(element, doNotApply)
|
||||
{
|
||||
ok(!element.validity.valueMissing,
|
||||
"Element should not suffer from value missing");
|
||||
ok(element.validity.valid, "Element should be valid");
|
||||
ok(element.checkValidity(), "Element should be valid");
|
||||
is(element.validationMessage, "",
|
||||
"Validation message should be the empty string");
|
||||
|
||||
if (doNotApply) {
|
||||
ok(!element.matches(':valid'), ":valid should not apply");
|
||||
ok(!element.matches(':invalid'), ":invalid should not apply");
|
||||
ok(!element.matches(':-moz-ui-valid'), ":-moz-ui-valid should not apply");
|
||||
ok(!element.matches(':-moz-ui-invalid'), ":-moz-ui-invalid should not apply");
|
||||
} else {
|
||||
ok(element.matches(':valid'), ":valid should apply");
|
||||
ok(!element.matches(':invalid'), ":invalid should not apply");
|
||||
ok(element.matches(':-moz-ui-valid'), ":-moz-ui-valid should apply");
|
||||
ok(!element.matches(':-moz-ui-invalid'), ":-moz-ui-invalid should not apply");
|
||||
}
|
||||
}
|
||||
|
||||
function checkSufferingFromBeingMissing(element, hasMozUIInvalid)
|
||||
{
|
||||
ok(element.validity.valueMissing, "Element should suffer from value missing");
|
||||
ok(!element.validity.valid, "Element should not be valid");
|
||||
ok(!element.checkValidity(), "Element should not be valid");
|
||||
|
||||
if (element.type == 'checkbox')
|
||||
{
|
||||
is(element.validationMessage,
|
||||
"Please check this box if you want to proceed.",
|
||||
"Validation message is wrong");
|
||||
}
|
||||
else if (element.type == 'radio')
|
||||
{
|
||||
is(element.validationMessage,
|
||||
"Please select one of these options.",
|
||||
"Validation message is wrong");
|
||||
}
|
||||
else if (element.type == 'file')
|
||||
{
|
||||
is(element.validationMessage,
|
||||
"Please select a file.",
|
||||
"Validation message is wrong");
|
||||
}
|
||||
else if (element.type == 'number')
|
||||
{
|
||||
is(element.validationMessage,
|
||||
"Please enter a number.",
|
||||
"Validation message is wrong");
|
||||
}
|
||||
else // text fields
|
||||
{
|
||||
is(element.validationMessage,
|
||||
"Please fill out this field.",
|
||||
"Validation message is wrong");
|
||||
}
|
||||
|
||||
ok(!element.matches(':valid'), ":valid should apply");
|
||||
ok(element.matches(':invalid'), ":invalid should not apply");
|
||||
ok(!element.matches(':-moz-ui-valid'), ":-moz-ui-valid should not apply");
|
||||
is(element.matches(':-moz-ui-invalid'), hasMozUIInvalid, ":-moz-ui-invalid expected state is " + hasMozUIInvalid);
|
||||
}
|
||||
|
||||
function checkTextareaRequiredValidity()
|
||||
{
|
||||
var element = document.createElement('textarea');
|
||||
document.forms[0].appendChild(element);
|
||||
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.required = true;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.readOnly = true;
|
||||
checkNotSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.readOnly = false;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
SpecialPowers.wrap(element).value = 'foo';
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.focus();
|
||||
element.required = true;
|
||||
SpecialPowers.wrap(element).value = 'foobar';
|
||||
element.blur();
|
||||
element.form.reset();
|
||||
checkSufferingFromBeingMissing(element, false);
|
||||
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
element.form.reportValidity();
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.form.reset();
|
||||
checkSufferingFromBeingMissing(element, false);
|
||||
|
||||
// TODO: for the moment, a textarea outside of a document is mutable.
|
||||
SpecialPowers.wrap(element).value = ''; // To make -moz-ui-valid apply.
|
||||
element.required = false;
|
||||
document.forms[0].removeChild(element);
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
}
|
||||
|
||||
function checkInputRequiredNotApply(type, isBarred)
|
||||
{
|
||||
var element = document.createElement('input');
|
||||
element.type = type;
|
||||
document.forms[0].appendChild(element);
|
||||
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element, isBarred);
|
||||
|
||||
element.required = true;
|
||||
checkNotSufferingFromBeingMissing(element, isBarred);
|
||||
|
||||
element.required = false;
|
||||
|
||||
document.forms[0].removeChild(element);
|
||||
checkNotSufferingFromBeingMissing(element, isBarred);
|
||||
}
|
||||
|
||||
function checkInputRequiredValidity(type)
|
||||
{
|
||||
var element = document.createElement('input');
|
||||
element.type = type;
|
||||
document.forms[0].appendChild(element);
|
||||
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.required = true;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.readOnly = true;
|
||||
checkNotSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.readOnly = false;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
if (element.type == 'email') {
|
||||
SpecialPowers.wrap(element).value = 'foo@bar.com';
|
||||
} else if (element.type == 'url') {
|
||||
SpecialPowers.wrap(element).value = 'http://mozilla.org/';
|
||||
} else if (element.type == 'number') {
|
||||
SpecialPowers.wrap(element).value = '42';
|
||||
} else if (element.type == 'date') {
|
||||
SpecialPowers.wrap(element).value = '2010-10-10';
|
||||
} else if (element.type == 'time') {
|
||||
SpecialPowers.wrap(element).value = '21:21';
|
||||
} else if (element.type = 'month') {
|
||||
SpecialPowers.wrap(element).value = '2010-10';
|
||||
} else {
|
||||
SpecialPowers.wrap(element).value = 'foo';
|
||||
}
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.focus();
|
||||
element.required = true;
|
||||
SpecialPowers.wrap(element).value = 'foobar';
|
||||
element.blur();
|
||||
element.form.reset();
|
||||
checkSufferingFromBeingMissing(element, false);
|
||||
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
element.form.reportValidity();
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.form.reset();
|
||||
checkSufferingFromBeingMissing(element, false);
|
||||
|
||||
element.required = true;
|
||||
SpecialPowers.wrap(element).value = ''; // To make :-moz-ui-valid apply.
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
document.forms[0].removeChild(element);
|
||||
// Removing the child changes nothing about whether it's valid
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
}
|
||||
|
||||
function checkInputRequiredValidityForCheckbox()
|
||||
{
|
||||
var element = document.createElement('input');
|
||||
element.type = 'checkbox';
|
||||
document.forms[0].appendChild(element);
|
||||
|
||||
element.checked = false;
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.required = true;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.checked = true;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.checked = false;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.focus();
|
||||
element.required = true;
|
||||
element.checked = true;
|
||||
element.blur();
|
||||
element.form.reset();
|
||||
checkSufferingFromBeingMissing(element, false);
|
||||
|
||||
element.required = true;
|
||||
element.checked = false;
|
||||
element.form.reportValidity();
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.form.reset();
|
||||
checkSufferingFromBeingMissing(element, false);
|
||||
|
||||
element.required = true;
|
||||
element.checked = false;
|
||||
document.forms[0].removeChild(element);
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
}
|
||||
|
||||
function checkInputRequiredValidityForRadio()
|
||||
{
|
||||
var element = document.createElement('input');
|
||||
element.type = 'radio';
|
||||
element.name = 'test'
|
||||
document.forms[0].appendChild(element);
|
||||
|
||||
element.checked = false;
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.required = true;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.checked = true;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.checked = false;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
// A required radio button should not suffer from value missing if another
|
||||
// radio button from the same group is checked.
|
||||
var element2 = document.createElement('input');
|
||||
element2.type = 'radio';
|
||||
element2.name = 'test';
|
||||
|
||||
element2.checked = true;
|
||||
element2.required = false;
|
||||
document.forms[0].appendChild(element2);
|
||||
|
||||
// Adding a checked radio should make required radio in the group not
|
||||
// suffering from being missing.
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.checked = false;
|
||||
element2.checked = false;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
// The other radio button should not be disabled.
|
||||
// A disabled checked radio button in the radio group
|
||||
// is enough to not suffer from value missing.
|
||||
element2.checked = true;
|
||||
element2.disabled = true;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
// If a radio button is not required but another radio button is required in
|
||||
// the same group, the not required radio button should suffer from value
|
||||
// missing.
|
||||
element2.disabled = false;
|
||||
element2.checked = false;
|
||||
element.required = false;
|
||||
element2.required = true;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
checkSufferingFromBeingMissing(element2, true);
|
||||
|
||||
element.checked = true;
|
||||
checkNotSufferingFromBeingMissing(element2);
|
||||
|
||||
// The checked radio is not in the group anymore, element2 should be invalid.
|
||||
element.form.removeChild(element);
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
checkSufferingFromBeingMissing(element2, true);
|
||||
|
||||
element2.focus();
|
||||
element2.required = true;
|
||||
element2.checked = true;
|
||||
element2.blur();
|
||||
element2.form.reset();
|
||||
checkSufferingFromBeingMissing(element2, false);
|
||||
|
||||
element2.required = true;
|
||||
element2.checked = false;
|
||||
element2.form.reportValidity();
|
||||
checkSufferingFromBeingMissing(element2, true);
|
||||
|
||||
element2.form.reset();
|
||||
checkSufferingFromBeingMissing(element2, false);
|
||||
|
||||
element2.required = true;
|
||||
element2.checked = false;
|
||||
document.forms[0].removeChild(element2);
|
||||
checkSufferingFromBeingMissing(element2, true);
|
||||
}
|
||||
|
||||
function checkInputRequiredValidityForFile()
|
||||
{
|
||||
var element = document.createElement('input');
|
||||
element.type = 'file'
|
||||
document.forms[0].appendChild(element);
|
||||
|
||||
var file = new File([""], "345822_file");
|
||||
|
||||
SpecialPowers.wrap(element).value = "";
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.required = true;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
SpecialPowers.wrap(element).mozSetFileArray([file]);
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
SpecialPowers.wrap(element).value = "";
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.required = false;
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.focus();
|
||||
SpecialPowers.wrap(element).mozSetFileArray([file]);
|
||||
element.required = true;
|
||||
element.blur();
|
||||
element.form.reset();
|
||||
checkSufferingFromBeingMissing(element, false);
|
||||
|
||||
element.required = true;
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
element.form.reportValidity();
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
element.form.reset();
|
||||
checkSufferingFromBeingMissing(element, false);
|
||||
|
||||
element.required = true;
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
document.forms[0].removeChild(element);
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
}
|
||||
|
||||
checkTextareaRequiredValidity();
|
||||
|
||||
// The require attribute behavior depend of the input type.
|
||||
// First of all, checks for types that make the element barred from
|
||||
// constraint validation.
|
||||
var typeBarredFromConstraintValidation = ["hidden", "button", "reset"];
|
||||
for (type of typeBarredFromConstraintValidation) {
|
||||
checkInputRequiredNotApply(type, true);
|
||||
}
|
||||
|
||||
// Then, checks for the types which do not use the required attribute.
|
||||
var typeRequireNotApply = ['range', 'color', 'submit', 'image'];
|
||||
for (type of typeRequireNotApply) {
|
||||
checkInputRequiredNotApply(type, false);
|
||||
}
|
||||
|
||||
// Now, checking for all types which accept the required attribute.
|
||||
var typeRequireApply = ["text", "password", "search", "tel", "email", "url",
|
||||
"number", "date", "time", "month", "week",
|
||||
"datetime-local"];
|
||||
|
||||
for (type of typeRequireApply) {
|
||||
checkInputRequiredValidity(type);
|
||||
}
|
||||
|
||||
checkInputRequiredValidityForCheckbox();
|
||||
checkInputRequiredValidityForRadio();
|
||||
checkInputRequiredValidityForFile();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,104 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for HTMLTextAreaElement attributes reflection</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="../../reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for HTMLTextAreaElement attributes reflection **/
|
||||
|
||||
// .autofocus
|
||||
reflectBoolean({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "autofocus",
|
||||
});
|
||||
|
||||
//.cols
|
||||
reflectUnsignedInt({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "cols",
|
||||
nonZero: true,
|
||||
defaultValue: 20,
|
||||
fallback: true,
|
||||
});
|
||||
|
||||
todo("dirName" in document.createElement("textarea"),
|
||||
"dirName isn't implemented yet");
|
||||
|
||||
// .disabled
|
||||
reflectBoolean({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "disabled",
|
||||
});
|
||||
|
||||
// TODO: form (HTMLFormElement)
|
||||
|
||||
// .maxLength
|
||||
reflectInt({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "maxLength",
|
||||
nonNegative: true,
|
||||
});
|
||||
|
||||
// .name
|
||||
reflectString({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "name",
|
||||
otherValues: [ "isindex", "_charset_" ],
|
||||
});
|
||||
|
||||
// .placeholder
|
||||
reflectString({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "placeholder",
|
||||
otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
|
||||
});
|
||||
|
||||
// .readOnly
|
||||
reflectBoolean({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "readOnly",
|
||||
});
|
||||
|
||||
// .required
|
||||
reflectBoolean({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "required",
|
||||
});
|
||||
|
||||
// .rows
|
||||
reflectUnsignedInt({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "rows",
|
||||
nonZero: true,
|
||||
defaultValue: 2,
|
||||
fallback: true,
|
||||
});
|
||||
|
||||
// .wrap
|
||||
// TODO: make it an enumerated attributes limited to only known values, bug 670869.
|
||||
reflectString({
|
||||
element: document.createElement("textarea"),
|
||||
attribute: "wrap",
|
||||
otherValues: [ "soft", "hard" ],
|
||||
});
|
||||
|
||||
// .type doesn't reflect a content attribute.
|
||||
// .defaultValue doesn't reflect a content attribute.
|
||||
// .value doesn't reflect a content attribute.
|
||||
// .textLength doesn't reflect a content attribute.
|
||||
// .willValidate doesn't reflect a content attribute.
|
||||
// .validity doesn't reflect a content attribute.
|
||||
// .validationMessage doesn't reflect a content attribute.
|
||||
// .labels doesn't reflect a content attribute.
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,358 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=345624
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 345624</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
input, textarea, fieldset, button, select, keygen, output, object { background-color: rgb(0,0,0) !important; }
|
||||
:valid { background-color: rgb(0,255,0) !important; }
|
||||
:invalid { background-color: rgb(255,0,0) !important; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<fieldset id='f'></fieldset>
|
||||
<input id='i' oninvalid="invalidEventHandler(event);">
|
||||
<button id='b' oninvalid="invalidEventHandler(event);"></button>
|
||||
<select id='s' oninvalid="invalidEventHandler(event);"></select>
|
||||
<textarea id='t' oninvalid="invalidEventHandler(event);"></textarea>
|
||||
<output id='o' oninvalid="invalidEventHandler(event);"></output>
|
||||
<keygen id='k'></keygen>
|
||||
<object id='obj'></object>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 345624 **/
|
||||
|
||||
var gInvalid = false;
|
||||
|
||||
function invalidEventHandler(aEvent)
|
||||
{
|
||||
function checkInvalidEvent(aEvent)
|
||||
{
|
||||
is(aEvent.type, "invalid", "Invalid event type should be invalid");
|
||||
ok(!aEvent.bubbles, "Invalid event should not bubble");
|
||||
ok(aEvent.cancelable, "Invalid event should be cancelable");
|
||||
}
|
||||
|
||||
checkInvalidEvent(aEvent);
|
||||
|
||||
gInvalid = true;
|
||||
}
|
||||
|
||||
function checkConstraintValidationAPIExist(element)
|
||||
{
|
||||
ok('willValidate' in element, "willValidate is not available in the DOM");
|
||||
ok('validationMessage' in element, "validationMessage is not available in the DOM");
|
||||
ok('validity' in element, "validity is not available in the DOM");
|
||||
|
||||
if ('validity' in element) {
|
||||
validity = element.validity;
|
||||
ok('valueMissing' in validity, "validity.valueMissing is not available in the DOM");
|
||||
ok('typeMismatch' in validity, "validity.typeMismatch is not available in the DOM");
|
||||
ok('badInput' in validity, "validity.badInput is not available in the DOM");
|
||||
ok('patternMismatch' in validity, "validity.patternMismatch is not available in the DOM");
|
||||
ok('tooLong' in validity, "validity.tooLong is not available in the DOM");
|
||||
ok('rangeUnderflow' in validity, "validity.rangeUnderflow is not available in the DOM");
|
||||
ok('rangeOverflow' in validity, "validity.rangeOverflow is not available in the DOM");
|
||||
ok('stepMismatch' in validity, "validity.stepMismatch is not available in the DOM");
|
||||
ok('customError' in validity, "validity.customError is not available in the DOM");
|
||||
ok('valid' in validity, "validity.valid is not available in the DOM");
|
||||
}
|
||||
}
|
||||
|
||||
function checkConstraintValidationAPIDefaultValues(element)
|
||||
{
|
||||
// Not checking willValidate because the default value depends of the element
|
||||
|
||||
is(element.validationMessage, "", "validationMessage default value should be empty string");
|
||||
|
||||
ok(!element.validity.valueMissing, "The element should not suffer from a constraint validation");
|
||||
ok(!element.validity.typeMismatch, "The element should not suffer from a constraint validation");
|
||||
ok(!element.validity.badInput, "The element should not suffer from a constraint validation");
|
||||
ok(!element.validity.patternMismatch, "The element should not suffer from a constraint validation");
|
||||
ok(!element.validity.tooLong, "The element should not suffer from a constraint validation");
|
||||
ok(!element.validity.rangeUnderflow, "The element should not suffer from a constraint validation");
|
||||
ok(!element.validity.rangeOverflow, "The element should not suffer from a constraint validation");
|
||||
ok(!element.validity.stepMismatch, "The element should not suffer from a constraint validation");
|
||||
ok(!element.validity.customError, "The element should not suffer from a constraint validation");
|
||||
ok(element.validity.valid, "The element should be valid by default");
|
||||
|
||||
ok(element.checkValidity(), "The element should be valid by default");
|
||||
}
|
||||
|
||||
function checkDefaultPseudoClass()
|
||||
{
|
||||
is(window.getComputedStyle(document.getElementById('f'))
|
||||
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||
":valid should apply");
|
||||
|
||||
is(window.getComputedStyle(document.getElementById('o'))
|
||||
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||
":valid should apply");
|
||||
|
||||
is(window.getComputedStyle(document.getElementById('obj'))
|
||||
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
|
||||
"Nor :valid and :invalid should apply");
|
||||
|
||||
todo_is(window.getComputedStyle(document.getElementById('k'))
|
||||
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
|
||||
"Nor :valid and :invalid should apply");
|
||||
|
||||
is(window.getComputedStyle(document.getElementById('s'))
|
||||
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||
":valid pseudo-class should apply");
|
||||
|
||||
is(window.getComputedStyle(document.getElementById('i'))
|
||||
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||
":valid pseudo-class should apply");
|
||||
|
||||
is(window.getComputedStyle(document.getElementById('t'))
|
||||
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||
":valid pseudo-class should apply");
|
||||
|
||||
is(window.getComputedStyle(document.getElementById('b'))
|
||||
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||
":valid pseudo-class should apply");
|
||||
}
|
||||
|
||||
function checkSpecificWillValidate()
|
||||
{
|
||||
// fieldset, output, object, keygen (TODO) and select elements
|
||||
ok(!document.getElementById('f').willValidate, "Fielset element should be barred from constraint validation");
|
||||
ok(!document.getElementById('obj').willValidate, "Object element should be barred from constraint validation");
|
||||
todo(!document.getElementById('k').willValidate, "Keygen element should be barred from constraint validation");
|
||||
ok(document.getElementById('o').willValidate, "Output element should not be barred from constraint validation");
|
||||
ok(document.getElementById('s').willValidate, "Select element should not be barred from constraint validation");
|
||||
|
||||
// input element
|
||||
i = document.getElementById('i');
|
||||
i.type = "hidden";
|
||||
ok(!i.willValidate, "Hidden state input should be barred from constraint validation");
|
||||
is(window.getComputedStyle(i).getPropertyValue('background-color'),
|
||||
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||
i.type = "reset";
|
||||
ok(!i.willValidate, "Reset button state input should be barred from constraint validation");
|
||||
is(window.getComputedStyle(i).getPropertyValue('background-color'),
|
||||
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||
i.type = "button";
|
||||
ok(!i.willValidate, "Button state input should be barred from constraint validation");
|
||||
is(window.getComputedStyle(i).getPropertyValue('background-color'),
|
||||
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||
i.type = "image";
|
||||
ok(i.willValidate, "Image state input should not be barred from constraint validation");
|
||||
is(window.getComputedStyle(i).getPropertyValue('background-color'),
|
||||
"rgb(0, 255, 0)", ":valid and :invalid should apply");
|
||||
i.type = "submit";
|
||||
ok(i.willValidate, "Submit state input should not be barred from constraint validation");
|
||||
is(window.getComputedStyle(i).getPropertyValue('background-color'),
|
||||
"rgb(0, 255, 0)", ":valid and :invalid should apply");
|
||||
i.type = "number";
|
||||
ok(i.willValidate, "Number state input should not be barred from constraint validation");
|
||||
is(window.getComputedStyle(i).getPropertyValue('background-color'),
|
||||
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||
i.type = "";
|
||||
i.readOnly = 'true';
|
||||
ok(!i.willValidate, "Readonly input should be barred from constraint validation");
|
||||
is(window.getComputedStyle(i).getPropertyValue('background-color'),
|
||||
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||
i.removeAttribute('readOnly');
|
||||
ok(i.willValidate, "Default input element should not be barred from constraint validation");
|
||||
is(window.getComputedStyle(i).getPropertyValue('background-color'),
|
||||
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||
|
||||
// button element
|
||||
b = document.getElementById('b');
|
||||
b.type = "reset";
|
||||
ok(!b.willValidate, "Reset state button should be barred from constraint validation");
|
||||
is(window.getComputedStyle(b).getPropertyValue('background-color'),
|
||||
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||
b.type = "button";
|
||||
ok(!b.willValidate, "Button state button should be barred from constraint validation");
|
||||
is(window.getComputedStyle(b).getPropertyValue('background-color'),
|
||||
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||
b.type = "submit";
|
||||
ok(b.willValidate, "Submit state button should not be barred from constraint validation");
|
||||
is(window.getComputedStyle(b).getPropertyValue('background-color'),
|
||||
"rgb(0, 255, 0)", ":valid and :invalid should apply");
|
||||
b.type = "";
|
||||
ok(b.willValidate, "Default button element should not be barred from constraint validation");
|
||||
is(window.getComputedStyle(b).getPropertyValue('background-color'),
|
||||
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||
|
||||
// textarea element
|
||||
t = document.getElementById('t');
|
||||
t.readOnly = true;
|
||||
ok(!t.willValidate, "Readonly textarea should be barred from constraint validation");
|
||||
is(window.getComputedStyle(t).getPropertyValue('background-color'),
|
||||
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||
t.removeAttribute('readOnly');
|
||||
ok(t.willValidate, "Default textarea element should not be barred from constraint validation");
|
||||
is(window.getComputedStyle(t).getPropertyValue('background-color'),
|
||||
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||
|
||||
// TODO: PROGRESS
|
||||
// TODO: METER
|
||||
}
|
||||
|
||||
function checkCommonWillValidate(element)
|
||||
{
|
||||
// Not checking the default value because it has been checked previously.
|
||||
|
||||
// Not checking output elements because they can't be disabled.
|
||||
if (element.tagName != 'OUTPUT') {
|
||||
element.disabled = true;
|
||||
ok(!element.willValidate, "Disabled element should be barred from constraint validation");
|
||||
|
||||
is(window.getComputedStyle(element).getPropertyValue('background-color'),
|
||||
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||
|
||||
element.removeAttribute('disabled');
|
||||
}
|
||||
|
||||
// TODO: If an element has a datalist element ancestor, it is barred from constraint validation.
|
||||
}
|
||||
|
||||
function checkCustomError(element, isBarred)
|
||||
{
|
||||
element.setCustomValidity("message");
|
||||
if (!isBarred) {
|
||||
is(element.validationMessage, "message",
|
||||
"When the element has a custom validity message, validation message should return it");
|
||||
} else {
|
||||
is(element.validationMessage, "",
|
||||
"An element barred from constraint validation can't have a validation message");
|
||||
}
|
||||
ok(element.validity.customError, "The element should suffer from a custom error");
|
||||
ok(!element.validity.valid, "The element should not be valid with a custom error");
|
||||
|
||||
if (element.tagName == "FIELDSET") {
|
||||
is(window.getComputedStyle(element).getPropertyValue('background-color'),
|
||||
isBarred ? "rgb(0, 255, 0)" : "rgb(255, 0, 0)",
|
||||
":invalid pseudo-classs should apply" + element.tagName);
|
||||
}
|
||||
else {
|
||||
is(window.getComputedStyle(element).getPropertyValue('background-color'),
|
||||
isBarred ? "rgb(0, 0, 0)" : "rgb(255, 0, 0)",
|
||||
":invalid pseudo-classs should apply" + element.tagName);
|
||||
}
|
||||
|
||||
element.setCustomValidity("");
|
||||
is(element.validationMessage, "", "The element should not have a validation message when reseted");
|
||||
ok(!element.validity.customError, "The element should not suffer anymore from a custom error");
|
||||
ok(element.validity.valid, "The element should now be valid");
|
||||
|
||||
is(window.getComputedStyle(element).getPropertyValue('background-color'),
|
||||
isBarred && element.tagName != "FIELDSET" ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
|
||||
":valid pseudo-classs should apply");
|
||||
}
|
||||
|
||||
function checkCheckValidity(element)
|
||||
{
|
||||
element.setCustomValidity("message");
|
||||
ok(!element.checkValidity(), "checkValidity() should return false when the element is not valid");
|
||||
|
||||
ok(gInvalid, "Invalid event should have been handled");
|
||||
|
||||
gInvalid = false;
|
||||
element.setCustomValidity("");
|
||||
|
||||
ok(element.checkValidity(), "Element should be valid");
|
||||
ok(!gInvalid, "Invalid event should not have been handled");
|
||||
}
|
||||
|
||||
function checkValidityStateObjectAliveWithoutElement(element)
|
||||
{
|
||||
// We are creating a temporary element and getting it's ValidityState object.
|
||||
// Then, we make sure it is removed by the garbage collector and we check the
|
||||
// ValidityState default values (it should not crash).
|
||||
|
||||
var v = document.createElement(element).validity;
|
||||
SpecialPowers.gc();
|
||||
|
||||
ok(!v.valueMissing,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(!v.typeMismatch,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(!v.badInput,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(!v.patternMismatch,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(!v.tooLong,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(!v.rangeUnderflow,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(!v.rangeOverflow,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(!v.stepMismatch,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(!v.customError,
|
||||
"When the element is not alive, it shouldn't suffer from constraint validation");
|
||||
ok(v.valid, "When the element is not alive, it should be valid");
|
||||
}
|
||||
|
||||
checkConstraintValidationAPIExist(document.getElementById('f'));
|
||||
checkConstraintValidationAPIExist(document.getElementById('i'));
|
||||
checkConstraintValidationAPIExist(document.getElementById('b'));
|
||||
checkConstraintValidationAPIExist(document.getElementById('s'));
|
||||
checkConstraintValidationAPIExist(document.getElementById('t'));
|
||||
checkConstraintValidationAPIExist(document.getElementById('k'));
|
||||
checkConstraintValidationAPIExist(document.getElementById('o'));
|
||||
checkConstraintValidationAPIExist(document.getElementById('obj'));
|
||||
|
||||
checkConstraintValidationAPIDefaultValues(document.getElementById('f'));
|
||||
checkConstraintValidationAPIDefaultValues(document.getElementById('i'));
|
||||
checkConstraintValidationAPIDefaultValues(document.getElementById('b'));
|
||||
checkConstraintValidationAPIDefaultValues(document.getElementById('s'));
|
||||
checkConstraintValidationAPIDefaultValues(document.getElementById('t'));
|
||||
checkConstraintValidationAPIDefaultValues(document.getElementById('k'));
|
||||
checkConstraintValidationAPIDefaultValues(document.getElementById('o'));
|
||||
checkConstraintValidationAPIDefaultValues(document.getElementById('obj'));
|
||||
|
||||
checkDefaultPseudoClass();
|
||||
|
||||
checkSpecificWillValidate();
|
||||
|
||||
// Not checking button, fieldset, object and keygen
|
||||
// because they are always barred from constraint validation.
|
||||
checkCommonWillValidate(document.getElementById('i'));
|
||||
checkCommonWillValidate(document.getElementById('s'));
|
||||
checkCommonWillValidate(document.getElementById('t'));
|
||||
checkCommonWillValidate(document.getElementById('o'));
|
||||
|
||||
/* TODO: add "keygen" element */
|
||||
checkCustomError(document.getElementById('i'), false);
|
||||
checkCustomError(document.getElementById('s'), false);
|
||||
checkCustomError(document.getElementById('t'), false);
|
||||
checkCustomError(document.getElementById('o'), false);
|
||||
checkCustomError(document.getElementById('b'), false);
|
||||
checkCustomError(document.getElementById('f'), true);
|
||||
checkCustomError(document.getElementById('obj'), true);
|
||||
|
||||
// Not checking button, fieldset, object and keygen
|
||||
// because they are always barred from constraint validation.
|
||||
checkCheckValidity(document.getElementById('i'));
|
||||
checkCheckValidity(document.getElementById('s'));
|
||||
checkCheckValidity(document.getElementById('t'));
|
||||
checkCheckValidity(document.getElementById('o'));
|
||||
|
||||
/* TODO: add "keygen" element */
|
||||
checkValidityStateObjectAliveWithoutElement("fieldset");
|
||||
checkValidityStateObjectAliveWithoutElement("input");
|
||||
checkValidityStateObjectAliveWithoutElement("button");
|
||||
checkValidityStateObjectAliveWithoutElement("select");
|
||||
checkValidityStateObjectAliveWithoutElement("textarea");
|
||||
checkValidityStateObjectAliveWithoutElement("output");
|
||||
checkValidityStateObjectAliveWithoutElement("object");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test for constraint validation of form controls not in documents</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var input = document.createElement('input');
|
||||
input.required = true;
|
||||
assert_false(input.checkValidity());
|
||||
}, "Should validate input not in document");
|
||||
|
||||
test(function() {
|
||||
var textarea = document.createElement('textarea');
|
||||
textarea.required = true;
|
||||
assert_false(textarea.checkValidity());
|
||||
}, "Should validate textarea not in document");
|
||||
</script>
|
@ -1,57 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=874640
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 874640</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 874640 **/
|
||||
var states = [
|
||||
// dom.experimental_forms, dom.forms.datetime, dom.forms.datetime.others, expectedValueAsDate
|
||||
[ 'true', 'true', ,'true', 'true' ],
|
||||
[ 'true', 'false', 'false', 'true' ],
|
||||
[ 'false', 'true', 'false', 'true' ],
|
||||
[ 'false', 'false', 'true', 'true' ],
|
||||
[ 'false', 'false', 'false', 'false' ],
|
||||
'end'
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function runTest(iframe) {
|
||||
var state = states.shift();
|
||||
|
||||
if (state == 'end') {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set":[
|
||||
["dom.experimental_forms", state[0] === 'true'],
|
||||
["dom.forms.datetime", state[1] === 'true'],
|
||||
["dom.forms.datetime.others", state[2] === 'true']]},
|
||||
function() {
|
||||
iframe.srcdoc = '<script>' +
|
||||
'parent.is("valueAsDate" in document.createElement("input"), ' +
|
||||
state[3] + ', "valueAsDate presence state should be ' + state[3] + '");' +
|
||||
'<\/script>'
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=874640">Mozilla Bug 874640</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe onload='runTest(this);'></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,751 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=769370
|
||||
-->
|
||||
<head>
|
||||
<title>Test for input.valueAsDate</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=769370">Mozilla Bug 769370</a>
|
||||
<iframe name="testFrame" style="display: none"></iframe>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 769370**/
|
||||
|
||||
/**
|
||||
* This test is checking .valueAsDate.
|
||||
*/
|
||||
|
||||
var element = document.createElement("input");
|
||||
|
||||
var validTypes =
|
||||
[
|
||||
["text", false],
|
||||
["password", false],
|
||||
["search", false],
|
||||
["tel", false],
|
||||
["email", false],
|
||||
["url", false],
|
||||
["hidden", false],
|
||||
["checkbox", false],
|
||||
["radio", false],
|
||||
["file", false],
|
||||
["submit", false],
|
||||
["image", false],
|
||||
["reset", false],
|
||||
["button", false],
|
||||
["number", false],
|
||||
["range", false],
|
||||
["date", true],
|
||||
["time", true],
|
||||
["color", false],
|
||||
["month", true],
|
||||
["week", true],
|
||||
["datetime-local", true],
|
||||
];
|
||||
|
||||
function checkAvailability()
|
||||
{
|
||||
for (let data of validTypes) {
|
||||
var exceptionCatched = false;
|
||||
element.type = data[0];
|
||||
try {
|
||||
element.valueAsDate;
|
||||
} catch (e) {
|
||||
exceptionCatched = true;
|
||||
}
|
||||
is(exceptionCatched, false,
|
||||
"valueAsDate shouldn't throw exception on getting");
|
||||
|
||||
exceptionCatched = false;
|
||||
try {
|
||||
element.valueAsDate = new Date();
|
||||
} catch (e) {
|
||||
exceptionCatched = true;
|
||||
}
|
||||
is(exceptionCatched, !data[1], "valueAsDate for " + data[0] +
|
||||
" availability is not correct");
|
||||
}
|
||||
}
|
||||
|
||||
function checkGarbageValues()
|
||||
{
|
||||
for (let type of validTypes) {
|
||||
if (!type[1]) {
|
||||
continue;
|
||||
}
|
||||
type = type[0];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = type;
|
||||
|
||||
element.value = "test";
|
||||
element.valueAsDate = null;
|
||||
is(element.value, "", "valueAsDate should set the value to the empty string");
|
||||
|
||||
element.value = "test";
|
||||
element.valueAsDate = undefined;
|
||||
is(element.value, "", "valueAsDate should set the value to the empty string");
|
||||
|
||||
element.value = "test";
|
||||
element.valueAsDate = new Date(NaN);
|
||||
is(element.value, "", "valueAsDate should set the value to the empty string");
|
||||
|
||||
var illegalValues = [
|
||||
"foobar", 42, {}, function() { return 42; }, function() { return Date(); }
|
||||
];
|
||||
|
||||
for (let value of illegalValues) {
|
||||
try {
|
||||
var caught = false;
|
||||
element.valueAsDate = value;
|
||||
} catch(e) {
|
||||
is(e.name, "TypeError", "Exception should be 'TypeError'.");
|
||||
caught = true;
|
||||
}
|
||||
ok(caught, "Assigning " + value + " to .valueAsDate should throw");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkDateGet()
|
||||
{
|
||||
var validData =
|
||||
[
|
||||
[ "2012-07-12", 1342051200000 ],
|
||||
[ "1970-01-01", 0 ],
|
||||
[ "1970-01-02", 86400000 ],
|
||||
[ "1969-12-31", -86400000 ],
|
||||
[ "0311-01-31", -52350451200000 ],
|
||||
[ "275760-09-13", 8640000000000000 ],
|
||||
[ "0001-01-01", -62135596800000 ],
|
||||
[ "2012-02-29", 1330473600000 ],
|
||||
[ "2011-02-28", 1298851200000 ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
[ "invaliddate" ],
|
||||
[ "-001-12-31" ],
|
||||
[ "901-12-31" ],
|
||||
[ "1901-13-31" ],
|
||||
[ "1901-12-32" ],
|
||||
[ "1901-00-12" ],
|
||||
[ "1901-01-00" ],
|
||||
[ "1900-02-29" ],
|
||||
[ "0000-01-01" ],
|
||||
[ "" ],
|
||||
// This date is valid for the input element, but is out of
|
||||
// the date object range. In this case, on getting valueAsDate,
|
||||
// a Date object will be created, but it will have a NaN internal value,
|
||||
// and will return the string "Invalid Date".
|
||||
[ "275760-09-14", true ],
|
||||
];
|
||||
|
||||
element.type = "date";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsDate.valueOf(), data[1],
|
||||
"valueAsDate should return the " +
|
||||
"valid date object representing this date");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data[0];
|
||||
if (data[1]) {
|
||||
is(String(element.valueAsDate), "Invalid Date",
|
||||
"valueAsDate should return an invalid Date object " +
|
||||
"when the element value is not a valid date");
|
||||
} else {
|
||||
is(element.valueAsDate, null,
|
||||
"valueAsDate should return null " +
|
||||
"when the element value is not a valid date");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkDateSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
[ 1342051200000, "2012-07-12" ],
|
||||
[ 0, "1970-01-01" ],
|
||||
// Maximum valid date (limited by the ecma date object range).
|
||||
[ 8640000000000000, "275760-09-13" ],
|
||||
// Minimum valid date (limited by the input element minimum valid value).
|
||||
[ -62135596800000 , "0001-01-01" ],
|
||||
[ 1330473600000, "2012-02-29" ],
|
||||
[ 1298851200000, "2011-02-28" ],
|
||||
// "Values must be truncated to valid dates"
|
||||
[ 42.1234, "1970-01-01" ],
|
||||
[ 123.123456789123, "1970-01-01" ],
|
||||
[ 1e-1, "1970-01-01" ],
|
||||
[ 1298851200010, "2011-02-28" ],
|
||||
[ -1, "1969-12-31" ],
|
||||
[ -86400000, "1969-12-31" ],
|
||||
[ 86400000, "1970-01-02" ],
|
||||
// Negative years, this is out of range for the input element,
|
||||
// the corresponding date string is the empty string
|
||||
[ -62135596800001, "" ],
|
||||
// Invalid dates.
|
||||
];
|
||||
|
||||
element.type = "date";
|
||||
for (let data of testData) {
|
||||
element.valueAsDate = new Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate should set the value to "
|
||||
+ data[1]);
|
||||
element.valueAsDate = new testFrame.Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate with other-global date should " +
|
||||
"set the value to " + data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
function checkTimeGet()
|
||||
{
|
||||
var tests = [
|
||||
// Some invalid values to begin.
|
||||
{ value: "", result: null },
|
||||
{ value: "foobar", result: null },
|
||||
{ value: "00:", result: null },
|
||||
{ value: "24:00", result: null },
|
||||
{ value: "00:99", result: null },
|
||||
{ value: "00:00:", result: null },
|
||||
{ value: "00:00:99", result: null },
|
||||
{ value: "00:00:00:", result: null },
|
||||
{ value: "00:00:00.", result: null },
|
||||
{ value: "00:00:00.0000", result: null },
|
||||
// Some simple valid values.
|
||||
{ value: "00:00", result: { time: 0, hours: 0, minutes: 0, seconds: 0, ms: 0 } },
|
||||
{ value: "00:01", result: { time: 60000, hours: 0, minutes: 1, seconds: 0, ms: 0 } },
|
||||
{ value: "01:00", result: { time: 3600000, hours: 1, minutes: 0, seconds: 0, ms: 0 } },
|
||||
{ value: "01:01", result: { time: 3660000, hours: 1, minutes: 1, seconds: 0, ms: 0 } },
|
||||
{ value: "13:37", result: { time: 49020000, hours: 13, minutes: 37, seconds: 0, ms: 0 } },
|
||||
// Valid values including seconds.
|
||||
{ value: "00:00:01", result: { time: 1000, hours: 0, minutes: 0, seconds: 1, ms: 0 } },
|
||||
{ value: "13:37:42", result: { time: 49062000, hours: 13, minutes: 37, seconds: 42, ms: 0 } },
|
||||
// Valid values including seconds fractions.
|
||||
{ value: "00:00:00.001", result: { time: 1, hours: 0, minutes: 0, seconds: 0, ms: 1 } },
|
||||
{ value: "00:00:00.123", result: { time: 123, hours: 0, minutes: 0, seconds: 0, ms: 123 } },
|
||||
{ value: "00:00:00.100", result: { time: 100, hours: 0, minutes: 0, seconds: 0, ms: 100 } },
|
||||
{ value: "00:00:00.000", result: { time: 0, hours: 0, minutes: 0, seconds: 0, ms: 0 } },
|
||||
{ value: "20:17:31.142", result: { time: 73051142, hours: 20, minutes: 17, seconds: 31, ms: 142 } },
|
||||
// Highest possible value.
|
||||
{ value: "23:59:59.999", result: { time: 86399999, hours: 23, minutes: 59, seconds: 59, ms: 999 } },
|
||||
// Some values with one or two digits for the fraction of seconds.
|
||||
{ value: "00:00:00.1", result: { time: 100, hours: 0, minutes: 0, seconds: 0, ms: 100 } },
|
||||
{ value: "00:00:00.14", result: { time: 140, hours: 0, minutes: 0, seconds: 0, ms: 140 } },
|
||||
{ value: "13:37:42.7", result: { time: 49062700, hours: 13, minutes: 37, seconds: 42, ms: 700 } },
|
||||
{ value: "23:31:12.23", result: { time: 84672230, hours: 23, minutes: 31, seconds: 12, ms: 230 } },
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = 'time';
|
||||
|
||||
for (let test of tests) {
|
||||
element.value = test.value;
|
||||
if (test.result === null) {
|
||||
is(element.valueAsDate, null, "element.valueAsDate should return null");
|
||||
} else {
|
||||
var date = element.valueAsDate;
|
||||
isnot(date, null, "element.valueAsDate should not be null");
|
||||
|
||||
is(date.getTime(), test.result.time);
|
||||
is(date.getUTCHours(), test.result.hours);
|
||||
is(date.getUTCMinutes(), test.result.minutes);
|
||||
is(date.getUTCSeconds(), test.result.seconds);
|
||||
is(date.getUTCMilliseconds(), test.result.ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkTimeSet()
|
||||
{
|
||||
var tests = [
|
||||
// Simple tests.
|
||||
{ value: 0, result: "00:00" },
|
||||
{ value: 1, result: "00:00:00.001" },
|
||||
{ value: 100, result: "00:00:00.100" },
|
||||
{ value: 1000, result: "00:00:01" },
|
||||
{ value: 60000, result: "00:01" },
|
||||
{ value: 3600000, result: "01:00" },
|
||||
{ value: 83622234, result: "23:13:42.234" },
|
||||
// Some edge cases.
|
||||
{ value: 86400000, result: "00:00" },
|
||||
{ value: 86400001, result: "00:00:00.001" },
|
||||
{ value: 170022234, result: "23:13:42.234" },
|
||||
{ value: 432000000, result: "00:00" },
|
||||
{ value: -1, result: "23:59:59.999" },
|
||||
{ value: -86400000, result: "00:00" },
|
||||
{ value: -86400001, result: "23:59:59.999" },
|
||||
{ value: -56789, result: "23:59:03.211" },
|
||||
{ value: 0.9, result: "00:00" },
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = 'time';
|
||||
|
||||
for (let test of tests) {
|
||||
element.valueAsDate = new Date(test.value);
|
||||
is(element.value, test.result,
|
||||
"element.value should have been changed by setting valueAsDate");
|
||||
}
|
||||
}
|
||||
|
||||
function checkWithBustedPrototype()
|
||||
{
|
||||
for (let type of validTypes) {
|
||||
if (!type[1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
type = type[0];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = type;
|
||||
|
||||
var backupPrototype = {};
|
||||
backupPrototype.getUTCFullYear = Date.prototype.getUTCFullYear;
|
||||
backupPrototype.getUTCMonth = Date.prototype.getUTCMonth;
|
||||
backupPrototype.getUTCDate = Date.prototype.getUTCDate;
|
||||
backupPrototype.getTime = Date.prototype.getTime;
|
||||
backupPrototype.setUTCFullYear = Date.prototype.setUTCFullYear;
|
||||
|
||||
Date.prototype.getUTCFullYear = function() { return {}; };
|
||||
Date.prototype.getUTCMonth = function() { return {}; };
|
||||
Date.prototype.getUTCDate = function() { return {}; };
|
||||
Date.prototype.getTime = function() { return {}; };
|
||||
Date.prototype.setUTCFullYear = function(y,m,d) { };
|
||||
|
||||
element.valueAsDate = new Date();
|
||||
|
||||
isnot(element.valueAsDate, null, ".valueAsDate should not return null");
|
||||
// The object returned by element.valueAsDate should return a Date object
|
||||
// with the same prototype:
|
||||
is(element.valueAsDate.getUTCFullYear, Date.prototype.getUTCFullYear,
|
||||
"prototype is the same");
|
||||
is(element.valueAsDate.getUTCMonth, Date.prototype.getUTCMonth,
|
||||
"prototype is the same");
|
||||
is(element.valueAsDate.getUTCDate, Date.prototype.getUTCDate,
|
||||
"prototype is the same");
|
||||
is(element.valueAsDate.getTime, Date.prototype.getTime,
|
||||
"prototype is the same");
|
||||
is(element.valueAsDate.setUTCFullYear, Date.prototype.setUTCFullYear,
|
||||
"prototype is the same");
|
||||
|
||||
// However the Date should have the correct information.
|
||||
// Skip type=month for now, since .valueAsNumber returns number of months
|
||||
// and not milliseconds.
|
||||
if (type != "month") {
|
||||
var witnessDate = new Date(element.valueAsNumber);
|
||||
is(element.valueAsDate.valueOf(), witnessDate.valueOf(), "correct Date");
|
||||
}
|
||||
|
||||
// Same test as above but using NaN instead of {}.
|
||||
|
||||
Date.prototype.getUTCFullYear = function() { return NaN; };
|
||||
Date.prototype.getUTCMonth = function() { return NaN; };
|
||||
Date.prototype.getUTCDate = function() { return NaN; };
|
||||
Date.prototype.getTime = function() { return NaN; };
|
||||
Date.prototype.setUTCFullYear = function(y,m,d) { };
|
||||
|
||||
element.valueAsDate = new Date();
|
||||
|
||||
isnot(element.valueAsDate, null, ".valueAsDate should not return null");
|
||||
// The object returned by element.valueAsDate should return a Date object
|
||||
// with the same prototype:
|
||||
is(element.valueAsDate.getUTCFullYear, Date.prototype.getUTCFullYear,
|
||||
"prototype is the same");
|
||||
is(element.valueAsDate.getUTCMonth, Date.prototype.getUTCMonth,
|
||||
"prototype is the same");
|
||||
is(element.valueAsDate.getUTCDate, Date.prototype.getUTCDate,
|
||||
"prototype is the same");
|
||||
is(element.valueAsDate.getTime, Date.prototype.getTime,
|
||||
"prototype is the same");
|
||||
is(element.valueAsDate.setUTCFullYear, Date.prototype.setUTCFullYear,
|
||||
"prototype is the same");
|
||||
|
||||
// However the Date should have the correct information.
|
||||
// Skip type=month for now, since .valueAsNumber returns number of months
|
||||
// and not milliseconds.
|
||||
if (type != "month") {
|
||||
var witnessDate = new Date(element.valueAsNumber);
|
||||
is(element.valueAsDate.valueOf(), witnessDate.valueOf(), "correct Date");
|
||||
}
|
||||
|
||||
Date.prototype.getUTCFullYear = backupPrototype.getUTCFullYear;
|
||||
Date.prototype.getUTCMonth = backupPrototype.getUTCMonth;
|
||||
Date.prototype.getUTCDate = backupPrototype.getUTCDate;
|
||||
Date.prototype.getTime = backupPrototype.getTime;
|
||||
Date.prototype.setUTCFullYear = backupPrototype.setUTCFullYear;
|
||||
}
|
||||
}
|
||||
|
||||
function checkMonthGet()
|
||||
{
|
||||
var validData =
|
||||
[
|
||||
[ "2016-07", 1467331200000 ],
|
||||
[ "1970-01", 0 ],
|
||||
[ "1970-02", 2678400000 ],
|
||||
[ "1969-12", -2678400000 ],
|
||||
[ "0001-01", -62135596800000 ],
|
||||
[ "275760-09", 8639998963200000 ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
[ "invalidmonth" ],
|
||||
[ "0000-01" ],
|
||||
[ "2016-00" ],
|
||||
[ "123-01" ],
|
||||
[ "2017-13" ],
|
||||
[ "" ],
|
||||
// This month is valid for the input element, but is out of
|
||||
// the date object range. In this case, on getting valueAsDate,
|
||||
// a Date object will be created, but it will have a NaN internal value,
|
||||
// and will return the string "Invalid Date".
|
||||
[ "275760-10", true ],
|
||||
];
|
||||
|
||||
element.type = "month";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsDate.valueOf(), data[1],
|
||||
"valueAsDate should return the " +
|
||||
"valid date object representing this month");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data[0];
|
||||
if (data[1]) {
|
||||
is(String(element.valueAsDate), "Invalid Date",
|
||||
"valueAsDate should return an invalid Date object " +
|
||||
"when the element value is not a valid month");
|
||||
} else {
|
||||
is(element.valueAsDate, null,
|
||||
"valueAsDate should return null " +
|
||||
"when the element value is not a valid month");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkMonthSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
[ 1342051200000, "2012-07" ],
|
||||
[ 0, "1970-01" ],
|
||||
// Maximum valid month (limited by the ecma date object range).
|
||||
[ 8640000000000000, "275760-09" ],
|
||||
// Minimum valid month (limited by the input element minimum valid value).
|
||||
[ -62135596800000 , "0001-01" ],
|
||||
[ 1330473600000, "2012-02" ],
|
||||
[ 1298851200000, "2011-02" ],
|
||||
// "Values must be truncated to valid months"
|
||||
[ 42.1234, "1970-01" ],
|
||||
[ 123.123456789123, "1970-01" ],
|
||||
[ 1e-1, "1970-01" ],
|
||||
[ 1298851200010, "2011-02" ],
|
||||
[ -1, "1969-12" ],
|
||||
[ -86400000, "1969-12" ],
|
||||
[ 86400000, "1970-01" ],
|
||||
// Negative years, this is out of range for the input element,
|
||||
// the corresponding month string is the empty string
|
||||
[ -62135596800001, "" ],
|
||||
];
|
||||
|
||||
element.type = "month";
|
||||
for (let data of testData) {
|
||||
element.valueAsDate = new Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate should set the value to "
|
||||
+ data[1]);
|
||||
element.valueAsDate = new testFrame.Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate with other-global date should " +
|
||||
"set the value to " + data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
function checkWeekGet()
|
||||
{
|
||||
var validData =
|
||||
[
|
||||
// Common years starting on different days of week.
|
||||
[ "2007-W01", Date.UTC(2007, 0, 1) ], // Mon
|
||||
[ "2013-W01", Date.UTC(2012, 11, 31) ], // Tue
|
||||
[ "2014-W01", Date.UTC(2013, 11, 30) ], // Wed
|
||||
[ "2015-W01", Date.UTC(2014, 11, 29) ], // Thu
|
||||
[ "2010-W01", Date.UTC(2010, 0, 4) ], // Fri
|
||||
[ "2011-W01", Date.UTC(2011, 0, 3) ], // Sat
|
||||
[ "2017-W01", Date.UTC(2017, 0, 2) ], // Sun
|
||||
// Common years ending on different days of week.
|
||||
[ "2007-W52", Date.UTC(2007, 11, 24) ], // Mon
|
||||
[ "2013-W52", Date.UTC(2013, 11, 23) ], // Tue
|
||||
[ "2014-W52", Date.UTC(2014, 11, 22) ], // Wed
|
||||
[ "2015-W53", Date.UTC(2015, 11, 28) ], // Thu
|
||||
[ "2010-W52", Date.UTC(2010, 11, 27) ], // Fri
|
||||
[ "2011-W52", Date.UTC(2011, 11, 26) ], // Sat
|
||||
[ "2017-W52", Date.UTC(2017, 11, 25) ], // Sun
|
||||
// Leap years starting on different days of week.
|
||||
[ "1996-W01", Date.UTC(1996, 0, 1) ], // Mon
|
||||
[ "2008-W01", Date.UTC(2007, 11, 31) ], // Tue
|
||||
[ "2020-W01", Date.UTC(2019, 11, 30) ], // Wed
|
||||
[ "2004-W01", Date.UTC(2003, 11, 29) ], // Thu
|
||||
[ "2016-W01", Date.UTC(2016, 0, 4) ], // Fri
|
||||
[ "2000-W01", Date.UTC(2000, 0, 3) ], // Sat
|
||||
[ "2012-W01", Date.UTC(2012, 0, 2) ], // Sun
|
||||
// Leap years ending on different days of week.
|
||||
[ "2012-W52", Date.UTC(2012, 11, 24) ], // Mon
|
||||
[ "2024-W52", Date.UTC(2024, 11, 23) ], // Tue
|
||||
[ "1980-W52", Date.UTC(1980, 11, 22) ], // Wed
|
||||
[ "1992-W53", Date.UTC(1992, 11, 28) ], // Thu
|
||||
[ "2004-W53", Date.UTC(2004, 11, 27) ], // Fri
|
||||
[ "1988-W52", Date.UTC(1988, 11, 26) ], // Sat
|
||||
[ "2000-W52", Date.UTC(2000, 11, 25) ], // Sun
|
||||
// Other normal cases.
|
||||
[ "2016-W36", 1473033600000 ],
|
||||
[ "1969-W52", -864000000 ],
|
||||
[ "1970-W01", -259200000 ],
|
||||
[ "275760-W37", 8639999568000000 ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
[ "invalidweek" ],
|
||||
[ "0000-W01" ],
|
||||
[ "2016-W00" ],
|
||||
[ "123-W01" ],
|
||||
[ "2016-W53" ],
|
||||
[ "" ],
|
||||
// This week is valid for the input element, but is out of
|
||||
// the date object range. In this case, on getting valueAsDate,
|
||||
// a Date object will be created, but it will have a NaN internal value,
|
||||
// and will return the string "Invalid Date".
|
||||
[ "275760-W38", true ],
|
||||
];
|
||||
|
||||
element.type = "week";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsDate.valueOf(), data[1],
|
||||
"valueAsDate should return the " +
|
||||
"valid date object representing this week");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data[0];
|
||||
if (data[1]) {
|
||||
is(String(element.valueAsDate), "Invalid Date",
|
||||
"valueAsDate should return an invalid Date object " +
|
||||
"when the element value is not a valid week");
|
||||
} else {
|
||||
is(element.valueAsDate, null,
|
||||
"valueAsDate should return null " +
|
||||
"when the element value is not a valid week");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkWeekSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
// Common years starting on different days of week.
|
||||
[ Date.UTC(2007, 0, 1), "2007-W01" ], // Mon
|
||||
[ Date.UTC(2013, 0, 1), "2013-W01" ], // Tue
|
||||
[ Date.UTC(2014, 0, 1), "2014-W01" ], // Wed
|
||||
[ Date.UTC(2015, 0, 1), "2015-W01" ], // Thu
|
||||
[ Date.UTC(2010, 0, 1), "2009-W53" ], // Fri
|
||||
[ Date.UTC(2011, 0, 1), "2010-W52" ], // Sat
|
||||
[ Date.UTC(2017, 0, 1), "2016-W52" ], // Sun
|
||||
// Common years ending on different days of week.
|
||||
[ Date.UTC(2007, 11, 31), "2008-W01" ], // Mon
|
||||
[ Date.UTC(2013, 11, 31), "2014-W01" ], // Tue
|
||||
[ Date.UTC(2014, 11, 31), "2015-W01" ], // Wed
|
||||
[ Date.UTC(2015, 11, 31), "2015-W53" ], // Thu
|
||||
[ Date.UTC(2010, 11, 31), "2010-W52" ], // Fri
|
||||
[ Date.UTC(2011, 11, 31), "2011-W52" ], // Sat
|
||||
[ Date.UTC(2017, 11, 31), "2017-W52" ], // Sun
|
||||
// Leap years starting on different days of week.
|
||||
[ Date.UTC(1996, 0, 1), "1996-W01" ], // Mon
|
||||
[ Date.UTC(2008, 0, 1), "2008-W01" ], // Tue
|
||||
[ Date.UTC(2020, 0, 1), "2020-W01" ], // Wed
|
||||
[ Date.UTC(2004, 0, 1), "2004-W01" ], // Thu
|
||||
[ Date.UTC(2016, 0, 1), "2015-W53" ], // Fri
|
||||
[ Date.UTC(2000, 0, 1), "1999-W52" ], // Sat
|
||||
[ Date.UTC(2012, 0, 1), "2011-W52" ], // Sun
|
||||
// Leap years ending on different days of week.
|
||||
[ Date.UTC(2012, 11, 31), "2013-W01" ], // Mon
|
||||
[ Date.UTC(2024, 11, 31), "2025-W01" ], // Tue
|
||||
[ Date.UTC(1980, 11, 31), "1981-W01" ], // Wed
|
||||
[ Date.UTC(1992, 11, 31), "1992-W53" ], // Thu
|
||||
[ Date.UTC(2004, 11, 31), "2004-W53" ], // Fri
|
||||
[ Date.UTC(1988, 11, 31), "1988-W52" ], // Sat
|
||||
[ Date.UTC(2000, 11, 31), "2000-W52" ], // Sun
|
||||
// Other normal cases.
|
||||
[ Date.UTC(2016, 8, 9), "2016-W36" ],
|
||||
[ Date.UTC(2010, 0, 3), "2009-W53" ],
|
||||
[ Date.UTC(2010, 0, 4), "2010-W01" ],
|
||||
[ Date.UTC(2010, 0, 10), "2010-W01" ],
|
||||
[ Date.UTC(2010, 0, 11), "2010-W02" ],
|
||||
[ 0, "1970-W01" ],
|
||||
// Maximum valid month (limited by the ecma date object range).
|
||||
[ 8640000000000000, "275760-W37" ],
|
||||
// Minimum valid month (limited by the input element minimum valid value).
|
||||
[ -62135596800000 , "0001-W01" ],
|
||||
// "Values must be truncated to valid week"
|
||||
[ 42.1234, "1970-W01" ],
|
||||
[ 123.123456789123, "1970-W01" ],
|
||||
[ 1e-1, "1970-W01" ],
|
||||
[ -1.1, "1970-W01" ],
|
||||
[ -345600000, "1969-W52" ],
|
||||
// Negative years, this is out of range for the input element,
|
||||
// the corresponding week string is the empty string
|
||||
[ -62135596800001, "" ],
|
||||
];
|
||||
|
||||
element.type = "week";
|
||||
for (let data of testData) {
|
||||
element.valueAsDate = new Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate should set the value to "
|
||||
+ data[1]);
|
||||
element.valueAsDate = new testFrame.Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate with other-global date should " +
|
||||
"set the value to " + data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
function checkDatetimeLocalGet()
|
||||
{
|
||||
var validData =
|
||||
[
|
||||
// Simple cases.
|
||||
[ "2016-12-27T10:30", Date.UTC(2016, 11, 27, 10, 30, 0) ],
|
||||
[ "2016-12-27T10:30:40", Date.UTC(2016, 11, 27, 10, 30, 40) ],
|
||||
[ "2016-12-27T10:30:40.567", Date.UTC(2016, 11, 27, 10, 30, 40, 567) ],
|
||||
[ "1969-12-31T12:00:00", Date.UTC(1969, 11, 31, 12, 0, 0) ],
|
||||
[ "1970-01-01T00:00", 0 ],
|
||||
// Leap years.
|
||||
[ "1804-02-29 12:34", Date.UTC(1804, 1, 29, 12, 34, 0) ],
|
||||
[ "2016-02-29T12:34", Date.UTC(2016, 1, 29, 12, 34, 0) ],
|
||||
[ "2016-12-31T12:34:56", Date.UTC(2016, 11, 31, 12, 34, 56) ],
|
||||
[ "2016-01-01T12:34:56.789", Date.UTC(2016, 0, 1, 12, 34, 56, 789) ],
|
||||
[ "2017-01-01 12:34:56.789", Date.UTC(2017, 0, 1, 12, 34, 56, 789) ],
|
||||
// Maximum valid datetime-local (limited by the ecma date object range).
|
||||
[ "275760-09-13T00:00", 8640000000000000 ],
|
||||
// Minimum valid datetime-local (limited by the input element minimum valid value).
|
||||
[ "0001-01-01T00:00", -62135596800000 ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
[ "invaliddateime-local" ],
|
||||
[ "0000-01-01T00:00" ],
|
||||
[ "2016-12-25T00:00Z" ],
|
||||
[ "2015-02-29T12:34" ],
|
||||
[ "1-1-1T12:00" ],
|
||||
[ "" ],
|
||||
// This datetime-local is valid for the input element, but is out of the
|
||||
// date object range. In this case, on getting valueAsDate, a Date object
|
||||
// will be created, but it will have a NaN internal value, and will return
|
||||
// the string "Invalid Date".
|
||||
[ "275760-09-13T12:00", true ],
|
||||
];
|
||||
|
||||
element.type = "datetime-local";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsDate.valueOf(), data[1],
|
||||
"valueAsDate should return the " +
|
||||
"valid date object representing this datetime-local");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data[0];
|
||||
if (data[1]) {
|
||||
is(String(element.valueAsDate), "Invalid Date",
|
||||
"valueAsDate should return an invalid Date object " +
|
||||
"when the element value is not a valid datetime-local");
|
||||
} else {
|
||||
is(element.valueAsDate, null,
|
||||
"valueAsDate should return null " +
|
||||
"when the element value is not a valid datetime-local");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkDatetimeLocalSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
// Simple cases.
|
||||
[ Date.UTC(2016, 11, 27, 10, 30, 0), "2016-12-27T10:30" ],
|
||||
[ Date.UTC(2016, 11, 27, 10, 30, 30), "2016-12-27T10:30:30" ],
|
||||
[ Date.UTC(1999, 11, 31, 23, 59, 59), "1999-12-31T23:59:59" ],
|
||||
[ Date.UTC(1999, 11, 31, 23, 59, 59, 999), "1999-12-31T23:59:59.999" ],
|
||||
[ Date.UTC(123456, 7, 8, 9, 10), "123456-08-08T09:10" ],
|
||||
[ 0, "1970-01-01T00:00" ],
|
||||
// Maximum valid datetime-local (limited by the ecma date object range).
|
||||
[ 8640000000000000, "275760-09-13T00:00" ],
|
||||
// Minimum valid datetime-local (limited by the input element minimum valid value).
|
||||
[ -62135596800000, "0001-01-01T00:00" ],
|
||||
// Leap years.
|
||||
[ Date.UTC(1804, 1, 29, 12, 34, 0), "1804-02-29T12:34" ],
|
||||
[ Date.UTC(2016, 1, 29, 12, 34, 0), "2016-02-29T12:34" ],
|
||||
[ Date.UTC(2016, 11, 31, 12, 34, 56), "2016-12-31T12:34:56" ],
|
||||
[ Date.UTC(2016, 0, 1, 12, 34, 56, 789), "2016-01-01T12:34:56.789" ],
|
||||
[ Date.UTC(2017, 0, 1, 12, 34, 56, 789), "2017-01-01T12:34:56.789" ],
|
||||
// "Values must be truncated to valid datetime-local"
|
||||
[ 123.123456789123, "1970-01-01T00:00:00.123" ],
|
||||
[ 1e-1, "1970-01-01T00:00" ],
|
||||
[ -1.1, "1969-12-31T23:59:59.999" ],
|
||||
[ -345600000, "1969-12-28T00:00" ],
|
||||
// Negative years, this is out of range for the input element,
|
||||
// the corresponding datetime-local string is the empty string
|
||||
[ -62135596800001, "" ],
|
||||
];
|
||||
|
||||
element.type = "datetime-local";
|
||||
for (let data of testData) {
|
||||
element.valueAsDate = new Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate should set the value to " +
|
||||
data[1]);
|
||||
element.valueAsDate = new testFrame.Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate with other-global date should " +
|
||||
"set the value to " + data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
checkAvailability();
|
||||
checkGarbageValues();
|
||||
checkWithBustedPrototype();
|
||||
|
||||
// Test <input type='date'>.
|
||||
checkDateGet();
|
||||
checkDateSet();
|
||||
|
||||
// Test <input type='time'>.
|
||||
checkTimeGet();
|
||||
checkTimeSet();
|
||||
|
||||
// Test <input type='month'>.
|
||||
checkMonthGet();
|
||||
checkMonthSet();
|
||||
|
||||
// Test <input type='week'>.
|
||||
checkWeekGet();
|
||||
checkWeekSet();
|
||||
|
||||
// Test <input type='datetime-local'>.
|
||||
checkDatetimeLocalGet();
|
||||
checkDatetimeLocalSet();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,858 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=636737
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug input.valueAsNumber</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636737">Mozilla Bug 636737</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 636737 **/
|
||||
|
||||
/**
|
||||
* This test is checking .valueAsNumber.
|
||||
*/
|
||||
|
||||
function checkAvailability()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
["text", false],
|
||||
["password", false],
|
||||
["search", false],
|
||||
["tel", false],
|
||||
["email", false],
|
||||
["url", false],
|
||||
["hidden", false],
|
||||
["checkbox", false],
|
||||
["radio", false],
|
||||
["file", false],
|
||||
["submit", false],
|
||||
["image", false],
|
||||
["reset", false],
|
||||
["button", false],
|
||||
["number", true],
|
||||
["range", true],
|
||||
["date", true],
|
||||
["time", true],
|
||||
["color", false],
|
||||
["month", true],
|
||||
["week", true],
|
||||
["datetime-local", true],
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
|
||||
for (let data of testData) {
|
||||
var exceptionCatched = false;
|
||||
element.type = data[0];
|
||||
try {
|
||||
element.valueAsNumber;
|
||||
} catch (e) {
|
||||
exceptionCatched = true;
|
||||
}
|
||||
is(exceptionCatched, false,
|
||||
"valueAsNumber shouldn't throw exception on getting");
|
||||
|
||||
exceptionCatched = false;
|
||||
try {
|
||||
element.valueAsNumber = 42;
|
||||
} catch (e) {
|
||||
exceptionCatched = true;
|
||||
}
|
||||
is(exceptionCatched, !data[1], "valueAsNumber for " + data[0] +
|
||||
" availability is not correct");
|
||||
}
|
||||
}
|
||||
|
||||
function checkNumberGet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
["42", 42],
|
||||
["-42", -42], // should work for negative values
|
||||
["42.1234", 42.1234],
|
||||
["123.123456789123", 123.123456789123], // double precision
|
||||
["1e2", 100], // e should be usable
|
||||
["2e1", 20],
|
||||
["1e-1", 0.1], // value after e can be negative
|
||||
["1E2", 100], // E can be used instead of e
|
||||
["e", null],
|
||||
["e2", null],
|
||||
["1e0.1", null],
|
||||
["", null], // the empty string is not a number
|
||||
["foo", null],
|
||||
["42,13", null], // comma can't be used as a decimal separator
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "number";
|
||||
for (let data of testData) {
|
||||
element.value = data[0];
|
||||
|
||||
// Given that NaN != NaN, we have to use null when the expected value is NaN.
|
||||
if (data[1] != null) {
|
||||
is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
|
||||
"floating point representation of the value");
|
||||
} else {
|
||||
ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
|
||||
"when the element value is not a number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkNumberSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
[42, "42"],
|
||||
[-42, "-42"], // should work for negative values
|
||||
[42.1234, "42.1234"],
|
||||
[123.123456789123, "123.123456789123"], // double precision
|
||||
[1e2, "100"], // e should be usable
|
||||
[2e1, "20"],
|
||||
[1e-1, "0.1"], // value after e can be negative
|
||||
[1E2, "100"], // E can be used instead of e
|
||||
// Setting a string will set NaN.
|
||||
["foo", ""],
|
||||
// "" is converted to 0.
|
||||
["", "0"],
|
||||
[42, "42"], // Keep this here, it is used by the next test.
|
||||
// Setting Infinity should throw and not change the current value.
|
||||
[Infinity, "42", true],
|
||||
[-Infinity, "42", true],
|
||||
// Setting NaN should change the value to the empty string.
|
||||
[NaN, ""],
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "number";
|
||||
for (let data of testData) {
|
||||
var caught = false;
|
||||
try {
|
||||
element.valueAsNumber = data[0];
|
||||
is(element.value, data[1],
|
||||
"valueAsNumber should be able to set the value");
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
}
|
||||
|
||||
if (data[2]) {
|
||||
ok(caught, "valueAsNumber should have thrown");
|
||||
is(element.value, data[1], "value should not have changed");
|
||||
} else {
|
||||
ok(!caught, "valueAsNumber should not have thrown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkRangeGet()
|
||||
{
|
||||
// For type=range we should never get NaN since the user agent is required
|
||||
// to fix up the input's value to be something sensible.
|
||||
|
||||
var min = -200;
|
||||
var max = 200;
|
||||
var defaultValue = min + (max - min)/2;
|
||||
|
||||
var testData =
|
||||
[
|
||||
["42", 42],
|
||||
["-42", -42], // should work for negative values
|
||||
["42.1234", 42.1234],
|
||||
["123.123456789123", 123.123456789123], // double precision
|
||||
["1e2", 100], // e should be usable
|
||||
["2e1", 20],
|
||||
["1e-1", 0.1], // value after e can be negative
|
||||
["1E2", 100], // E can be used instead of e
|
||||
["e", defaultValue],
|
||||
["e2", defaultValue],
|
||||
["1e0.1", defaultValue],
|
||||
["", defaultValue],
|
||||
["foo", defaultValue],
|
||||
["42,13", defaultValue],
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "range";
|
||||
element.setAttribute("min", min); // avoids out of range sanitization
|
||||
element.setAttribute("max", max);
|
||||
element.setAttribute("step", "any"); // avoids step mismatch sanitization
|
||||
for (let data of testData) {
|
||||
element.value = data[0];
|
||||
|
||||
// Given that NaN != NaN, we have to use null when the expected value is NaN.
|
||||
is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
|
||||
"floating point representation of the value");
|
||||
}
|
||||
}
|
||||
|
||||
function checkRangeSet()
|
||||
{
|
||||
var min = -200;
|
||||
var max = 200;
|
||||
var defaultValue = String(min + (max - min)/2);
|
||||
|
||||
var testData =
|
||||
[
|
||||
[42, "42"],
|
||||
[-42, "-42"], // should work for negative values
|
||||
[42.1234, "42.1234"],
|
||||
[123.123456789123, "123.123456789123"], // double precision
|
||||
[1e2, "100"], // e should be usable
|
||||
[2e1, "20"],
|
||||
[1e-1, "0.1"], // value after e can be negative
|
||||
[1E2, "100"], // E can be used instead of e
|
||||
["foo", defaultValue],
|
||||
["", defaultValue],
|
||||
[42, "42"], // Keep this here, it is used by the next test.
|
||||
// Setting Infinity should throw and not change the current value.
|
||||
[Infinity, "42", true],
|
||||
[-Infinity, "42", true],
|
||||
// Setting NaN should change the value to the empty string.
|
||||
[NaN, defaultValue],
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "range";
|
||||
element.setAttribute("min", min); // avoids out of range sanitization
|
||||
element.setAttribute("max", max);
|
||||
element.setAttribute("step", "any"); // avoids step mismatch sanitization
|
||||
for (let data of testData) {
|
||||
var caught = false;
|
||||
try {
|
||||
element.valueAsNumber = data[0];
|
||||
is(element.value, data[1],
|
||||
"valueAsNumber should be able to set the value");
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
}
|
||||
|
||||
if (data[2]) {
|
||||
ok(caught, "valueAsNumber should have thrown");
|
||||
is(element.value, data[1], "value should not have changed");
|
||||
} else {
|
||||
ok(!caught, "valueAsNumber should not have thrown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkDateGet()
|
||||
{
|
||||
var validData =
|
||||
[
|
||||
[ "2012-07-12", 1342051200000 ],
|
||||
[ "1970-01-01", 0 ],
|
||||
// We are supposed to support at least until this date.
|
||||
// (corresponding to the date object maximal value)
|
||||
[ "275760-09-13", 8640000000000000 ],
|
||||
// Minimum valid date (limited by the input element minimum valid value)
|
||||
[ "0001-01-01", -62135596800000 ],
|
||||
[ "2012-02-29", 1330473600000 ],
|
||||
[ "2011-02-28", 1298851200000 ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
"invaliddate",
|
||||
"",
|
||||
"275760-09-14",
|
||||
"999-12-31",
|
||||
"-001-12-31",
|
||||
"0000-01-01",
|
||||
"2011-02-29",
|
||||
"1901-13-31",
|
||||
"1901-12-32",
|
||||
"1901-00-12",
|
||||
"1901-01-00",
|
||||
"1900-02-29",
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "date";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
|
||||
"timestamp representing this date");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data;
|
||||
ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
|
||||
"when the element value is not a valid date");
|
||||
}
|
||||
}
|
||||
|
||||
function checkDateSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
[ 1342051200000, "2012-07-12" ],
|
||||
[ 0, "1970-01-01" ],
|
||||
// Maximum valid date (limited by the ecma date object range).
|
||||
[ 8640000000000000, "275760-09-13" ],
|
||||
// Minimum valid date (limited by the input element minimum valid value)
|
||||
[ -62135596800000, "0001-01-01" ],
|
||||
[ 1330473600000, "2012-02-29" ],
|
||||
[ 1298851200000, "2011-02-28" ],
|
||||
// "Values must be truncated to valid dates"
|
||||
[ 42.1234, "1970-01-01" ],
|
||||
[ 123.123456789123, "1970-01-01" ],
|
||||
[ 1e2, "1970-01-01" ],
|
||||
[ 1E9, "1970-01-12" ],
|
||||
[ 1e-1, "1970-01-01" ],
|
||||
[ 2e10, "1970-08-20" ],
|
||||
[ 1298851200010, "2011-02-28" ],
|
||||
[ -1, "1969-12-31" ],
|
||||
[ -86400000, "1969-12-31" ],
|
||||
[ 86400000, "1970-01-02" ],
|
||||
// Invalid numbers.
|
||||
// Those are implicitly converted to numbers
|
||||
[ "", "1970-01-01" ],
|
||||
[ true, "1970-01-01" ],
|
||||
[ false, "1970-01-01" ],
|
||||
[ null, "1970-01-01" ],
|
||||
// Those are converted to NaN, the corresponding date string is the empty string
|
||||
[ "invaliddatenumber", "" ],
|
||||
[ NaN, "" ],
|
||||
[ undefined, "" ],
|
||||
// Out of range, the corresponding date string is the empty string
|
||||
[ -62135596800001, "" ],
|
||||
// Infinity will keep the current value and throw (so we need to set a current value).
|
||||
[ 1298851200010, "2011-02-28" ],
|
||||
[ Infinity, "2011-02-28", true ],
|
||||
[ -Infinity, "2011-02-28", true ],
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "date";
|
||||
for (let data of testData) {
|
||||
var caught = false;
|
||||
|
||||
try {
|
||||
element.valueAsNumber = data[0];
|
||||
is(element.value, data[1], "valueAsNumber should set the value to " + data[1]);
|
||||
} catch(e) {
|
||||
caught = true;
|
||||
}
|
||||
|
||||
if (data[2]) {
|
||||
ok(caught, "valueAsNumber should have thrown");
|
||||
is(element.value, data[1], "the value should not have changed");
|
||||
} else {
|
||||
ok(!caught, "valueAsNumber should not have thrown");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function checkTimeGet()
|
||||
{
|
||||
var tests = [
|
||||
// Some invalid values to begin.
|
||||
{ value: "", result: NaN },
|
||||
{ value: "foobar", result: NaN },
|
||||
{ value: "00:", result: NaN },
|
||||
{ value: "24:00", result: NaN },
|
||||
{ value: "00:99", result: NaN },
|
||||
{ value: "00:00:", result: NaN },
|
||||
{ value: "00:00:99", result: NaN },
|
||||
{ value: "00:00:00:", result: NaN },
|
||||
{ value: "00:00:00.", result: NaN },
|
||||
{ value: "00:00:00.0000", result: NaN },
|
||||
// Some simple valid values.
|
||||
{ value: "00:00", result: 0 },
|
||||
{ value: "00:01", result: 60000 },
|
||||
{ value: "01:00", result: 3600000 },
|
||||
{ value: "01:01", result: 3660000 },
|
||||
{ value: "13:37", result: 49020000 },
|
||||
// Valid values including seconds.
|
||||
{ value: "00:00:01", result: 1000 },
|
||||
{ value: "13:37:42", result: 49062000 },
|
||||
// Valid values including seconds fractions.
|
||||
{ value: "00:00:00.001", result: 1 },
|
||||
{ value: "00:00:00.123", result: 123 },
|
||||
{ value: "00:00:00.100", result: 100 },
|
||||
{ value: "00:00:00.000", result: 0 },
|
||||
{ value: "20:17:31.142", result: 73051142 },
|
||||
// Highest possible value.
|
||||
{ value: "23:59:59.999", result: 86399999 },
|
||||
// Some values with one or two digits for the fraction of seconds.
|
||||
{ value: "00:00:00.1", result: 100 },
|
||||
{ value: "00:00:00.14", result: 140 },
|
||||
{ value: "13:37:42.7", result: 49062700 },
|
||||
{ value: "23:31:12.23", result: 84672230 },
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = 'time';
|
||||
|
||||
for (let test of tests) {
|
||||
element.value = test.value;
|
||||
if (isNaN(test.result)) {
|
||||
ok(isNaN(element.valueAsNumber),
|
||||
"invalid value should have .valueAsNumber return NaN");
|
||||
} else {
|
||||
is(element.valueAsNumber, test.result,
|
||||
".valueAsNumber should return " + test.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkTimeSet()
|
||||
{
|
||||
var tests = [
|
||||
// Some NaN values (should set to empty string).
|
||||
{ value: NaN, result: "" },
|
||||
{ value: "foobar", result: "" },
|
||||
{ value: function() {}, result: "" },
|
||||
// Inifinity (should throw).
|
||||
{ value: Infinity, throw: true },
|
||||
{ value: -Infinity, throw: true },
|
||||
// "" converts to 0... JS is fun :)
|
||||
{ value: "", result: "00:00" },
|
||||
// Simple tests.
|
||||
{ value: 0, result: "00:00" },
|
||||
{ value: 1, result: "00:00:00.001" },
|
||||
{ value: 100, result: "00:00:00.100" },
|
||||
{ value: 1000, result: "00:00:01" },
|
||||
{ value: 60000, result: "00:01" },
|
||||
{ value: 3600000, result: "01:00" },
|
||||
{ value: 83622234, result: "23:13:42.234" },
|
||||
// Some edge cases.
|
||||
{ value: 86400000, result: "00:00" },
|
||||
{ value: 86400001, result: "00:00:00.001" },
|
||||
{ value: 170022234, result: "23:13:42.234" },
|
||||
{ value: 432000000, result: "00:00" },
|
||||
{ value: -1, result: "23:59:59.999" },
|
||||
{ value: -86400000, result: "00:00" },
|
||||
{ value: -86400001, result: "23:59:59.999" },
|
||||
{ value: -56789, result: "23:59:03.211" },
|
||||
{ value: 0.9, result: "00:00" },
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = 'time';
|
||||
|
||||
for (let test of tests) {
|
||||
try {
|
||||
var caught = false;
|
||||
element.valueAsNumber = test.value;
|
||||
is(element.value, test.result, "value should return " + test.result);
|
||||
} catch(e) {
|
||||
caught = true;
|
||||
}
|
||||
|
||||
if (!test.throw) {
|
||||
test.throw = false;
|
||||
}
|
||||
|
||||
is(caught, test.throw, "the test throwing status should be " + test.throw);
|
||||
}
|
||||
}
|
||||
|
||||
function checkMonthGet()
|
||||
{
|
||||
var validData =
|
||||
[
|
||||
[ "2016-07", 558 ],
|
||||
[ "1970-01", 0 ],
|
||||
[ "1969-12", -1 ],
|
||||
[ "0001-01", -23628 ],
|
||||
[ "10000-12", 96371 ],
|
||||
[ "275760-09", 3285488 ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
"invalidmonth",
|
||||
"0000-01",
|
||||
"2000-00",
|
||||
"2012-13",
|
||||
// Out of range.
|
||||
"275760-10",
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "month";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
|
||||
"integer value representing this month");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data;
|
||||
ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
|
||||
"when the element value is not a valid month");
|
||||
}
|
||||
}
|
||||
|
||||
function checkMonthSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
[ 558, "2016-07" ],
|
||||
[ 0, "1970-01" ],
|
||||
[ -1, "1969-12" ],
|
||||
[ 96371, "10000-12" ],
|
||||
[ 12, "1971-01" ],
|
||||
[ -12, "1969-01" ],
|
||||
// Maximum valid month (limited by the ecma date object range)
|
||||
[ 3285488, "275760-09" ],
|
||||
// Minimum valid month (limited by the input element minimum valid value)
|
||||
[ -23628, "0001-01" ],
|
||||
// "Values must be truncated to valid months"
|
||||
[ 0.3, "1970-01" ],
|
||||
[ -1.1, "1969-11" ],
|
||||
[ 1e2, "1978-05" ],
|
||||
[ 1e-1, "1970-01" ],
|
||||
// Invalid numbers.
|
||||
// Those are implicitly converted to numbers
|
||||
[ "", "1970-01" ],
|
||||
[ true, "1970-02" ],
|
||||
[ false, "1970-01" ],
|
||||
[ null, "1970-01" ],
|
||||
// Those are converted to NaN, the corresponding month string is the empty string
|
||||
[ "invalidmonth", "" ],
|
||||
[ NaN, "" ],
|
||||
[ undefined, "" ],
|
||||
// Out of range, the corresponding month string is the empty string
|
||||
[ -23629, "" ],
|
||||
[ 3285489, "" ],
|
||||
// Infinity will keep the current value and throw (so we need to set a current value)
|
||||
[ 558, "2016-07" ],
|
||||
[ Infinity, "2016-07", true ],
|
||||
[ -Infinity, "2016-07", true ],
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "month";
|
||||
for (let data of testData) {
|
||||
var caught = false;
|
||||
|
||||
try {
|
||||
element.valueAsNumber = data[0];
|
||||
is(element.value, data[1], "valueAsNumber should set the value to " + data[1]);
|
||||
} catch(e) {
|
||||
caught = true;
|
||||
}
|
||||
|
||||
if (data[2]) {
|
||||
ok(caught, "valueAsNumber should have thrown");
|
||||
is(element.value, data[1], "the value should not have changed");
|
||||
} else {
|
||||
ok(!caught, "valueAsNumber should not have thrown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkWeekGet()
|
||||
{
|
||||
var validData =
|
||||
[
|
||||
// Common years starting on different days of week.
|
||||
[ "2007-W01", Date.UTC(2007, 0, 1) ], // Mon
|
||||
[ "2013-W01", Date.UTC(2012, 11, 31) ], // Tue
|
||||
[ "2014-W01", Date.UTC(2013, 11, 30) ], // Wed
|
||||
[ "2015-W01", Date.UTC(2014, 11, 29) ], // Thu
|
||||
[ "2010-W01", Date.UTC(2010, 0, 4) ], // Fri
|
||||
[ "2011-W01", Date.UTC(2011, 0, 3) ], // Sat
|
||||
[ "2017-W01", Date.UTC(2017, 0, 2) ], // Sun
|
||||
// Common years ending on different days of week.
|
||||
[ "2007-W52", Date.UTC(2007, 11, 24) ], // Mon
|
||||
[ "2013-W52", Date.UTC(2013, 11, 23) ], // Tue
|
||||
[ "2014-W52", Date.UTC(2014, 11, 22) ], // Wed
|
||||
[ "2015-W53", Date.UTC(2015, 11, 28) ], // Thu
|
||||
[ "2010-W52", Date.UTC(2010, 11, 27) ], // Fri
|
||||
[ "2011-W52", Date.UTC(2011, 11, 26) ], // Sat
|
||||
[ "2017-W52", Date.UTC(2017, 11, 25) ], // Sun
|
||||
// Leap years starting on different days of week.
|
||||
[ "1996-W01", Date.UTC(1996, 0, 1) ], // Mon
|
||||
[ "2008-W01", Date.UTC(2007, 11, 31) ], // Tue
|
||||
[ "2020-W01", Date.UTC(2019, 11, 30) ], // Wed
|
||||
[ "2004-W01", Date.UTC(2003, 11, 29) ], // Thu
|
||||
[ "2016-W01", Date.UTC(2016, 0, 4) ], // Fri
|
||||
[ "2000-W01", Date.UTC(2000, 0, 3) ], // Sat
|
||||
[ "2012-W01", Date.UTC(2012, 0, 2) ], // Sun
|
||||
// Leap years ending on different days of week.
|
||||
[ "2012-W52", Date.UTC(2012, 11, 24) ], // Mon
|
||||
[ "2024-W52", Date.UTC(2024, 11, 23) ], // Tue
|
||||
[ "1980-W52", Date.UTC(1980, 11, 22) ], // Wed
|
||||
[ "1992-W53", Date.UTC(1992, 11, 28) ], // Thu
|
||||
[ "2004-W53", Date.UTC(2004, 11, 27) ], // Fri
|
||||
[ "1988-W52", Date.UTC(1988, 11, 26) ], // Sat
|
||||
[ "2000-W52", Date.UTC(2000, 11, 25) ], // Sun
|
||||
// Other normal cases.
|
||||
[ "2015-W53", Date.UTC(2015, 11, 28) ],
|
||||
[ "2016-W36", Date.UTC(2016, 8, 5) ],
|
||||
[ "1970-W01", Date.UTC(1969, 11, 29) ],
|
||||
[ "275760-W37", Date.UTC(275760, 8, 8) ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
"invalidweek",
|
||||
"0000-W01",
|
||||
"2016-W00",
|
||||
"2016-W53",
|
||||
// Out of range.
|
||||
"275760-W38",
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "week";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
|
||||
"integer value representing this week");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data;
|
||||
ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
|
||||
"when the element value is not a valid week");
|
||||
}
|
||||
}
|
||||
|
||||
function checkWeekSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
// Common years starting on different days of week.
|
||||
[ Date.UTC(2007, 0, 1), "2007-W01" ], // Mon
|
||||
[ Date.UTC(2013, 0, 1), "2013-W01" ], // Tue
|
||||
[ Date.UTC(2014, 0, 1), "2014-W01" ], // Wed
|
||||
[ Date.UTC(2015, 0, 1), "2015-W01" ], // Thu
|
||||
[ Date.UTC(2010, 0, 1), "2009-W53" ], // Fri
|
||||
[ Date.UTC(2011, 0, 1), "2010-W52" ], // Sat
|
||||
[ Date.UTC(2017, 0, 1), "2016-W52" ], // Sun
|
||||
// Common years ending on different days of week.
|
||||
[ Date.UTC(2007, 11, 31), "2008-W01" ], // Mon
|
||||
[ Date.UTC(2013, 11, 31), "2014-W01" ], // Tue
|
||||
[ Date.UTC(2014, 11, 31), "2015-W01" ], // Wed
|
||||
[ Date.UTC(2015, 11, 31), "2015-W53" ], // Thu
|
||||
[ Date.UTC(2010, 11, 31), "2010-W52" ], // Fri
|
||||
[ Date.UTC(2011, 11, 31), "2011-W52" ], // Sat
|
||||
[ Date.UTC(2017, 11, 31), "2017-W52" ], // Sun
|
||||
// Leap years starting on different days of week.
|
||||
[ Date.UTC(1996, 0, 1), "1996-W01" ], // Mon
|
||||
[ Date.UTC(2008, 0, 1), "2008-W01" ], // Tue
|
||||
[ Date.UTC(2020, 0, 1), "2020-W01" ], // Wed
|
||||
[ Date.UTC(2004, 0, 1), "2004-W01" ], // Thu
|
||||
[ Date.UTC(2016, 0, 1), "2015-W53" ], // Fri
|
||||
[ Date.UTC(2000, 0, 1), "1999-W52" ], // Sat
|
||||
[ Date.UTC(2012, 0, 1), "2011-W52" ], // Sun
|
||||
// Leap years ending on different days of week.
|
||||
[ Date.UTC(2012, 11, 31), "2013-W01" ], // Mon
|
||||
[ Date.UTC(2024, 11, 31), "2025-W01" ], // Tue
|
||||
[ Date.UTC(1980, 11, 31), "1981-W01" ], // Wed
|
||||
[ Date.UTC(1992, 11, 31), "1992-W53" ], // Thu
|
||||
[ Date.UTC(2004, 11, 31), "2004-W53" ], // Fri
|
||||
[ Date.UTC(1988, 11, 31), "1988-W52" ], // Sat
|
||||
[ Date.UTC(2000, 11, 31), "2000-W52" ], // Sun
|
||||
// Other normal cases.
|
||||
[ Date.UTC(2008, 8, 26), "2008-W39" ],
|
||||
[ Date.UTC(2016, 0, 4), "2016-W01" ],
|
||||
[ Date.UTC(2016, 0, 10), "2016-W01" ],
|
||||
[ Date.UTC(2016, 0, 11), "2016-W02" ],
|
||||
// Maximum valid week (limited by the ecma date object range).
|
||||
[ 8640000000000000, "275760-W37" ],
|
||||
// Minimum valid week (limited by the input element minimum valid value)
|
||||
[ -62135596800000, "0001-W01" ],
|
||||
// "Values must be truncated to valid weeks"
|
||||
[ 0.3, "1970-W01" ],
|
||||
[ 1e-1, "1970-W01" ],
|
||||
[ -1.1, "1970-W01" ],
|
||||
[ -345600000, "1969-W52" ],
|
||||
// Invalid numbers.
|
||||
// Those are implicitly converted to numbers
|
||||
[ "", "1970-W01" ],
|
||||
[ true, "1970-W01" ],
|
||||
[ false, "1970-W01" ],
|
||||
[ null, "1970-W01" ],
|
||||
// Those are converted to NaN, the corresponding week string is the empty string
|
||||
[ "invalidweek", "" ],
|
||||
[ NaN, "" ],
|
||||
[ undefined, "" ],
|
||||
// Infinity will keep the current value and throw (so we need to set a current value).
|
||||
[ Date.UTC(2016, 8, 8), "2016-W36" ],
|
||||
[ Infinity, "2016-W36", true ],
|
||||
[ -Infinity, "2016-W36", true ],
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "week";
|
||||
for (let data of testData) {
|
||||
var caught = false;
|
||||
|
||||
try {
|
||||
element.valueAsNumber = data[0];
|
||||
is(element.value, data[1], "valueAsNumber should set the value to " +
|
||||
data[1]);
|
||||
} catch(e) {
|
||||
caught = true;
|
||||
}
|
||||
|
||||
if (data[2]) {
|
||||
ok(caught, "valueAsNumber should have thrown");
|
||||
is(element.value, data[1], "the value should not have changed");
|
||||
} else {
|
||||
ok(!caught, "valueAsNumber should not have thrown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkDatetimeLocalGet() {
|
||||
var validData =
|
||||
[
|
||||
// Simple cases.
|
||||
[ "2016-12-20T09:58", Date.UTC(2016, 11, 20, 9, 58) ],
|
||||
[ "2016-12-20T09:58:30", Date.UTC(2016, 11, 20, 9, 58, 30) ],
|
||||
[ "2016-12-20T09:58:30.123", Date.UTC(2016, 11, 20, 9, 58, 30, 123) ],
|
||||
[ "2017-01-01T10:00", Date.UTC(2017, 0, 1, 10, 0, 0) ],
|
||||
[ "1969-12-31T12:00:00", Date.UTC(1969, 11, 31, 12, 0, 0) ],
|
||||
[ "1970-01-01T00:00", 0 ],
|
||||
// Leap years.
|
||||
[ "1804-02-29 12:34", Date.UTC(1804, 1, 29, 12, 34, 0) ],
|
||||
[ "2016-02-29T12:34", Date.UTC(2016, 1, 29, 12, 34, 0) ],
|
||||
[ "2016-12-31T12:34:56", Date.UTC(2016, 11, 31, 12, 34, 56) ],
|
||||
[ "2016-01-01T12:34:56.789", Date.UTC(2016, 0, 1, 12, 34, 56, 789) ],
|
||||
[ "2017-01-01 12:34:56.789", Date.UTC(2017, 0, 1, 12, 34, 56, 789) ],
|
||||
// Maximum valid datetime-local (limited by the ecma date object range).
|
||||
[ "275760-09-13T00:00", 8640000000000000 ],
|
||||
// Minimum valid datetime-local (limited by the input element minimum valid value).
|
||||
[ "0001-01-01T00:00", -62135596800000 ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
"invaliddatetime-local",
|
||||
"0000-01-01T00:00",
|
||||
"2016-12-25T00:00Z",
|
||||
"2015-02-29T12:34",
|
||||
"1-1-1T12:00",
|
||||
// Out of range.
|
||||
"275760-09-13T12:00",
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "datetime-local";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
|
||||
"integer value representing this datetime-local");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data;
|
||||
ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
|
||||
"when the element value is not a valid datetime-local");
|
||||
}
|
||||
}
|
||||
|
||||
function checkDatetimeLocalSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
// Simple cases.
|
||||
[ Date.UTC(2016, 11, 20, 9, 58, 0), "2016-12-20T09:58", ],
|
||||
[ Date.UTC(2016, 11, 20, 9, 58, 30), "2016-12-20T09:58:30" ],
|
||||
[ Date.UTC(2016, 11, 20, 9, 58, 30, 123), "2016-12-20T09:58:30.123" ],
|
||||
[ Date.UTC(2017, 0, 1, 10, 0, 0), "2017-01-01T10:00" ],
|
||||
[ Date.UTC(1969, 11, 31, 12, 0, 0), "1969-12-31T12:00" ],
|
||||
[ 0, "1970-01-01T00:00" ],
|
||||
// Maximum valid week (limited by the ecma date object range).
|
||||
[ 8640000000000000, "275760-09-13T00:00" ],
|
||||
// Minimum valid datetime-local (limited by the input element minimum valid value).
|
||||
[ -62135596800000, "0001-01-01T00:00" ],
|
||||
// Leap years.
|
||||
[ Date.UTC(1804, 1, 29, 12, 34, 0), "1804-02-29T12:34" ],
|
||||
[ Date.UTC(2016, 1, 29, 12, 34, 0), "2016-02-29T12:34" ],
|
||||
[ Date.UTC(2016, 11, 31, 12, 34, 56), "2016-12-31T12:34:56" ],
|
||||
[ Date.UTC(2016, 0, 1, 12, 34, 56, 789), "2016-01-01T12:34:56.789" ],
|
||||
[ Date.UTC(2017, 0, 1, 12, 34, 56, 789), "2017-01-01T12:34:56.789" ],
|
||||
// "Values must be truncated to valid datetime-local"
|
||||
[ 0.3, "1970-01-01T00:00" ],
|
||||
[ 1e-1, "1970-01-01T00:00" ],
|
||||
[ -1 , "1969-12-31T23:59:59.999" ],
|
||||
[ -345600000, "1969-12-28T00:00" ],
|
||||
// Invalid numbers.
|
||||
// Those are implicitly converted to numbers
|
||||
[ "", "1970-01-01T00:00" ],
|
||||
[ true, "1970-01-01T00:00:00.001" ],
|
||||
[ false, "1970-01-01T00:00" ],
|
||||
[ null, "1970-01-01T00:00" ],
|
||||
// Those are converted to NaN, the corresponding week string is the empty string
|
||||
[ "invaliddatetime-local", "" ],
|
||||
[ NaN, "" ],
|
||||
[ undefined, "" ],
|
||||
// Infinity will keep the current value and throw (so we need to set a current value).
|
||||
[ Date.UTC(2016, 11, 27, 15, 10, 0), "2016-12-27T15:10" ],
|
||||
[ Infinity, "2016-12-27T15:10", true ],
|
||||
[ -Infinity, "2016-12-27T15:10", true ],
|
||||
];
|
||||
|
||||
var element = document.createElement('input');
|
||||
element.type = "datetime-local";
|
||||
for (let data of testData) {
|
||||
var caught = false;
|
||||
|
||||
try {
|
||||
element.valueAsNumber = data[0];
|
||||
is(element.value, data[1], "valueAsNumber should set the value to " +
|
||||
data[1]);
|
||||
} catch(e) {
|
||||
caught = true;
|
||||
}
|
||||
|
||||
if (data[2]) {
|
||||
ok(caught, "valueAsNumber should have thrown");
|
||||
is(element.value, data[1], "the value should not have changed");
|
||||
} else {
|
||||
ok(!caught, "valueAsNumber should not have thrown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkAvailability();
|
||||
|
||||
// <input type='number'> test
|
||||
checkNumberGet();
|
||||
checkNumberSet();
|
||||
|
||||
// <input type='range'> test
|
||||
checkRangeGet();
|
||||
checkRangeSet();
|
||||
|
||||
// <input type='date'> test
|
||||
checkDateGet();
|
||||
checkDateSet();
|
||||
|
||||
// <input type='time'> test
|
||||
checkTimeGet();
|
||||
checkTimeSet();
|
||||
|
||||
// <input type='month'> test
|
||||
checkMonthGet();
|
||||
checkMonthSet();
|
||||
|
||||
// <input type='week'> test
|
||||
checkWeekGet();
|
||||
checkWeekSet();
|
||||
|
||||
// <input type='datetime-local'> test
|
||||
checkDatetimeLocalGet();
|
||||
checkDatetimeLocalSet();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -30,20 +30,20 @@ class DateTimePickerChild extends ActorChild {
|
||||
*/
|
||||
close() {
|
||||
this.removeListeners();
|
||||
let dateTimeBoxElement = this._inputElement.dateTimeBoxElement;
|
||||
if (!dateTimeBoxElement) {
|
||||
if (!this._inputElement.dateTimeBoxElement) {
|
||||
this._inputElement = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dateTimeBoxElement instanceof Ci.nsIDateTimeInputArea) {
|
||||
dateTimeBoxElement.wrappedJSObject.setPickerState(false);
|
||||
if (this._inputElement.dateTimeBoxElement instanceof Ci.nsIDateTimeInputArea) {
|
||||
this._inputElement.dateTimeBoxElement.setPickerState(false);
|
||||
} else if (this._inputElement.openOrClosedShadowRoot) {
|
||||
// dateTimeBoxElement is within UA Widget Shadow DOM.
|
||||
// An event dispatch to it can't be accessed by document.
|
||||
let win = this._inputElement.ownerGlobal;
|
||||
dateTimeBoxElement.dispatchEvent(
|
||||
new win.CustomEvent("MozSetDateTimePickerState", { detail: false }));
|
||||
this._inputElement.dateTimeBoxElement.dispatchEvent(
|
||||
new win.CustomEvent("MozSetDateTimePickerState",
|
||||
{ detail: false }, win));
|
||||
}
|
||||
|
||||
this._inputElement = null;
|
||||
@ -104,21 +104,19 @@ class DateTimePickerChild extends ActorChild {
|
||||
break;
|
||||
}
|
||||
case "FormDateTime:PickerValueChanged": {
|
||||
let dateTimeBoxElement = this._inputElement.dateTimeBoxElement;
|
||||
if (!dateTimeBoxElement) {
|
||||
if (!this._inputElement.dateTimeBoxElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
let win = this._inputElement.ownerGlobal;
|
||||
|
||||
if (dateTimeBoxElement instanceof Ci.nsIDateTimeInputArea) {
|
||||
dateTimeBoxElement.wrappedJSObject.setValueFromPicker(Cu.cloneInto(aMessage.data, win));
|
||||
if (this._inputElement.dateTimeBoxElement instanceof Ci.nsIDateTimeInputArea) {
|
||||
this._inputElement.dateTimeBoxElement.setValueFromPicker(aMessage.data);
|
||||
} else if (this._inputElement.openOrClosedShadowRoot) {
|
||||
// dateTimeBoxElement is within UA Widget Shadow DOM.
|
||||
// An event dispatch to it can't be accessed by document.
|
||||
dateTimeBoxElement.dispatchEvent(
|
||||
let win = this._inputElement.ownerGlobal;
|
||||
this._inputElement.dateTimeBoxElement.dispatchEvent(
|
||||
new win.CustomEvent("MozPickerValueChanged",
|
||||
{ detail: Cu.cloneInto(aMessage.data, win) }));
|
||||
{ detail: Cu.cloneInto(aMessage.data, win) }, win));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -149,20 +147,20 @@ class DateTimePickerChild extends ActorChild {
|
||||
|
||||
this._inputElement = aEvent.originalTarget;
|
||||
|
||||
let dateTimeBoxElement = this._inputElement.dateTimeBoxElement;
|
||||
if (!dateTimeBoxElement) {
|
||||
if (!this._inputElement.dateTimeBoxElement) {
|
||||
throw new Error("How do we get this event without a UA Widget or XBL binding?");
|
||||
}
|
||||
|
||||
if (dateTimeBoxElement instanceof Ci.nsIDateTimeInputArea) {
|
||||
dateTimeBoxElement.wrappedJSObject.setPickerState(true);
|
||||
if (this._inputElement.dateTimeBoxElement instanceof Ci.nsIDateTimeInputArea) {
|
||||
this._inputElement.dateTimeBoxElement.setPickerState(true);
|
||||
} else if (this._inputElement.openOrClosedShadowRoot) {
|
||||
// dateTimeBoxElement is within UA Widget Shadow DOM.
|
||||
// An event dispatch to it can't be accessed by document, because
|
||||
// the event is not composed.
|
||||
let win = this._inputElement.ownerGlobal;
|
||||
dateTimeBoxElement.dispatchEvent(
|
||||
new win.CustomEvent("MozSetDateTimePickerState", { detail: true }));
|
||||
this._inputElement.dateTimeBoxElement.dispatchEvent(
|
||||
new win.CustomEvent("MozSetDateTimePickerState",
|
||||
{ detail: true }, win));
|
||||
}
|
||||
|
||||
this.addListeners();
|
||||
|
@ -1,7 +0,0 @@
|
||||
[DEFAULT]
|
||||
prefs = dom.ua_widget.enabled=false
|
||||
support-files =
|
||||
../head.js
|
||||
|
||||
[browser_datetime_datepicker.js]
|
||||
uses-unsafe-cpows = true
|
@ -1,292 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const MONTH_YEAR = ".month-year",
|
||||
DAYS_VIEW = ".days-view",
|
||||
BTN_PREV_MONTH = ".prev",
|
||||
BTN_NEXT_MONTH = ".next";
|
||||
const DATE_FORMAT = new Intl.DateTimeFormat("en-US", { year: "numeric", month: "long", timeZone: "UTC" }).format;
|
||||
const DATE_FORMAT_LOCAL = new Intl.DateTimeFormat("en-US", { year: "numeric", month: "long" }).format;
|
||||
|
||||
// Create a list of abbreviations for calendar class names
|
||||
const W = "weekend",
|
||||
O = "outside",
|
||||
S = "selection",
|
||||
R = "out-of-range",
|
||||
T = "today",
|
||||
P = "off-step";
|
||||
|
||||
// Calendar classlist for 2016-12. Used to verify the classNames are correct.
|
||||
const calendarClasslist_201612 = [
|
||||
[W, O], [O], [O], [O], [], [], [W],
|
||||
[W], [], [], [], [], [], [W],
|
||||
[W], [], [], [], [S], [], [W],
|
||||
[W], [], [], [], [], [], [W],
|
||||
[W], [], [], [], [], [], [W],
|
||||
[W, O], [O], [O], [O], [O], [O], [W, O],
|
||||
];
|
||||
|
||||
function getCalendarText() {
|
||||
return helper.getChildren(DAYS_VIEW).map(child => child.textContent);
|
||||
}
|
||||
|
||||
function getCalendarClassList() {
|
||||
return helper.getChildren(DAYS_VIEW).map(child => Array.from(child.classList));
|
||||
}
|
||||
|
||||
function mergeArrays(a, b) {
|
||||
return a.map((classlist, index) => classlist.concat(b[index]));
|
||||
}
|
||||
|
||||
let helper = new DateTimeTestHelper();
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
helper.cleanup();
|
||||
});
|
||||
|
||||
/**
|
||||
* Test that date picker opens to today's date when input field is blank
|
||||
*/
|
||||
add_task(async function test_datepicker_today() {
|
||||
const date = new Date();
|
||||
|
||||
await helper.openPicker("data:text/html, <input type='date'>");
|
||||
|
||||
if (date.getMonth() === new Date().getMonth()) {
|
||||
Assert.equal(helper.getElement(MONTH_YEAR).textContent, DATE_FORMAT_LOCAL(date));
|
||||
} else {
|
||||
Assert.ok(true, "Skipping datepicker today test if month changes when opening picker.");
|
||||
}
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
/**
|
||||
* Test that date picker opens to the correct month, with calendar days
|
||||
* displayed correctly, given a date value is set.
|
||||
*/
|
||||
add_task(async function test_datepicker_open() {
|
||||
const inputValue = "2016-12-15";
|
||||
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}">`);
|
||||
|
||||
Assert.equal(helper.getElement(MONTH_YEAR).textContent, DATE_FORMAT(new Date(inputValue)));
|
||||
Assert.deepEqual(
|
||||
getCalendarText(),
|
||||
[
|
||||
"27", "28", "29", "30", "1", "2", "3",
|
||||
"4", "5", "6", "7", "8", "9", "10",
|
||||
"11", "12", "13", "14", "15", "16", "17",
|
||||
"18", "19", "20", "21", "22", "23", "24",
|
||||
"25", "26", "27", "28", "29", "30", "31",
|
||||
"1", "2", "3", "4", "5", "6", "7",
|
||||
],
|
||||
"2016-12",
|
||||
);
|
||||
Assert.deepEqual(
|
||||
getCalendarClassList(),
|
||||
calendarClasslist_201612,
|
||||
"2016-12 classNames"
|
||||
);
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
/**
|
||||
* When the prev month button is clicked, calendar should display the dates for
|
||||
* the previous month.
|
||||
*/
|
||||
add_task(async function test_datepicker_prev_month_btn() {
|
||||
const inputValue = "2016-12-15";
|
||||
const prevMonth = "2016-11-01";
|
||||
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}">`);
|
||||
helper.click(helper.getElement(BTN_PREV_MONTH));
|
||||
|
||||
Assert.equal(helper.getElement(MONTH_YEAR).textContent, DATE_FORMAT(new Date(prevMonth)));
|
||||
Assert.deepEqual(
|
||||
getCalendarText(),
|
||||
[
|
||||
"30", "31", "1", "2", "3", "4", "5",
|
||||
"6", "7", "8", "9", "10", "11", "12",
|
||||
"13", "14", "15", "16", "17", "18", "19",
|
||||
"20", "21", "22", "23", "24", "25", "26",
|
||||
"27", "28", "29", "30", "1", "2", "3",
|
||||
"4", "5", "6", "7", "8", "9", "10",
|
||||
],
|
||||
"2016-11",
|
||||
);
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
/**
|
||||
* When the next month button is clicked, calendar should display the dates for
|
||||
* the next month.
|
||||
*/
|
||||
add_task(async function test_datepicker_next_month_btn() {
|
||||
const inputValue = "2016-12-15";
|
||||
const nextMonth = "2017-01-01";
|
||||
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}">`);
|
||||
helper.click(helper.getElement(BTN_NEXT_MONTH));
|
||||
|
||||
Assert.equal(helper.getElement(MONTH_YEAR).textContent, DATE_FORMAT(new Date(nextMonth)));
|
||||
Assert.deepEqual(
|
||||
getCalendarText(),
|
||||
[
|
||||
"25", "26", "27", "28", "29", "30", "31",
|
||||
"1", "2", "3", "4", "5", "6", "7",
|
||||
"8", "9", "10", "11", "12", "13", "14",
|
||||
"15", "16", "17", "18", "19", "20", "21",
|
||||
"22", "23", "24", "25", "26", "27", "28",
|
||||
"29", "30", "31", "1", "2", "3", "4",
|
||||
],
|
||||
"2017-01",
|
||||
);
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
/**
|
||||
* When a date on the calendar is clicked, date picker should close and set
|
||||
* value to the input box.
|
||||
*/
|
||||
add_task(async function test_datepicker_clicked() {
|
||||
const inputValue = "2016-12-15";
|
||||
const firstDayOnCalendar = "2016-11-27";
|
||||
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}">`);
|
||||
// Click the first item (top-left corner) of the calendar
|
||||
helper.click(helper.getElement(DAYS_VIEW).children[0]);
|
||||
await ContentTask.spawn(helper.tab.linkedBrowser, {}, async function() {
|
||||
let inputEl = content.document.querySelector("input");
|
||||
await ContentTaskUtils.waitForEvent(inputEl, "input");
|
||||
});
|
||||
|
||||
let value = await ContentTask.spawn(gBrowser.selectedBrowser, null, async () => {
|
||||
return content.document.querySelector("input").value;
|
||||
});
|
||||
Assert.equal(value, firstDayOnCalendar);
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
/**
|
||||
* Make sure picker is in correct state when it is reopened.
|
||||
*/
|
||||
add_task(async function test_datepicker_reopen_state() {
|
||||
const inputValue = "2016-12-15";
|
||||
const nextMonth = "2017-01-01";
|
||||
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}">`);
|
||||
// Navigate to the next month but does not commit the change
|
||||
Assert.equal(helper.getElement(MONTH_YEAR).textContent, DATE_FORMAT(new Date(inputValue)));
|
||||
helper.click(helper.getElement(BTN_NEXT_MONTH));
|
||||
Assert.equal(helper.getElement(MONTH_YEAR).textContent, DATE_FORMAT(new Date(nextMonth)));
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
|
||||
|
||||
// Ensures the picker opens to the month of the input value
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("input", {}, gBrowser.selectedBrowser);
|
||||
await helper.waitForPickerReady();
|
||||
Assert.equal(helper.getElement(MONTH_YEAR).textContent, DATE_FORMAT(new Date(inputValue)));
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
/**
|
||||
* When min and max attributes are set, calendar should show some dates as
|
||||
* out-of-range.
|
||||
*/
|
||||
add_task(async function test_datepicker_min_max() {
|
||||
const inputValue = "2016-12-15";
|
||||
const inputMin = "2016-12-05";
|
||||
const inputMax = "2016-12-25";
|
||||
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}" min="${inputMin}" max="${inputMax}">`);
|
||||
|
||||
Assert.deepEqual(
|
||||
getCalendarClassList(),
|
||||
mergeArrays(calendarClasslist_201612, [
|
||||
// R denotes out-of-range
|
||||
[R], [R], [R], [R], [R], [R], [R],
|
||||
[R], [], [], [], [], [], [],
|
||||
[], [], [], [], [], [], [],
|
||||
[], [], [], [], [], [], [],
|
||||
[], [R], [R], [R], [R], [R], [R],
|
||||
[R], [R], [R], [R], [R], [R], [R],
|
||||
]),
|
||||
"2016-12 with min & max",
|
||||
);
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
/**
|
||||
* When step attribute is set, calendar should show some dates as off-step.
|
||||
*/
|
||||
add_task(async function test_datepicker_step() {
|
||||
const inputValue = "2016-12-15";
|
||||
const inputStep = "5";
|
||||
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}" step="${inputStep}">`);
|
||||
|
||||
Assert.deepEqual(
|
||||
getCalendarClassList(),
|
||||
mergeArrays(calendarClasslist_201612, [
|
||||
// P denotes off-step
|
||||
[P], [P], [P], [], [P], [P], [P],
|
||||
[P], [], [P], [P], [P], [P], [],
|
||||
[P], [P], [P], [P], [], [P], [P],
|
||||
[P], [P], [], [P], [P], [P], [P],
|
||||
[], [P], [P], [P], [P], [], [P],
|
||||
[P], [P], [P], [], [P], [P], [P],
|
||||
]),
|
||||
"2016-12 with step",
|
||||
);
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
add_task(async function test_datepicker_abs_min() {
|
||||
const inputValue = "0001-01-01";
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}">`);
|
||||
|
||||
Assert.deepEqual(
|
||||
getCalendarText(),
|
||||
[
|
||||
"", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "10", "11", "12", "13",
|
||||
"14", "15", "16", "17", "18", "19", "20",
|
||||
"21", "22", "23", "24", "25", "26", "27",
|
||||
"28", "29", "30", "31", "1", "2", "3",
|
||||
"4", "5", "6", "7", "8", "9", "10",
|
||||
],
|
||||
"0001-01",
|
||||
);
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
||||
|
||||
add_task(async function test_datepicker_abs_max() {
|
||||
const inputValue = "275760-09-13";
|
||||
await helper.openPicker(`data:text/html, <input type="date" value="${inputValue}">`);
|
||||
|
||||
Assert.deepEqual(
|
||||
getCalendarText(),
|
||||
[
|
||||
"31", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "10", "11", "12", "13",
|
||||
"", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "",
|
||||
],
|
||||
"275760-09",
|
||||
);
|
||||
|
||||
await helper.tearDown();
|
||||
});
|
@ -6,10 +6,7 @@
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'browser/browser.ini',
|
||||
'browser/xbl/browser.ini',
|
||||
]
|
||||
BROWSER_CHROME_MANIFESTS += ['browser/browser.ini']
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += [
|
||||
'chrome/chrome.ini',
|
||||
|
Loading…
Reference in New Issue
Block a user