blob: 33508fb3289be3736f6f467957dc6614bec2bc9b [file] [log] [blame]
var validator = {
test_tooLong: function(ctl, data) {
var self = this;
test(function() {
self.pre_check(ctl, 'tooLong');
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.tooLong,
'The validity.tooLong should be true' + condStr);
else
assert_false(
ctl.validity.tooLong,
'The validity.tooLong should be false' + condStr);
});
}, data.name);
},
test_tooShort: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "tooShort");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.tooShort,
'The validity.tooShort should be true' + condStr);
else
assert_false(
ctl.validity.tooShort,
'The validity.tooShort should be false' + condStr);
});
}, data.name);
},
test_patternMismatch: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "patternMismatch");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.patternMismatch,
'The validity.patternMismatch should be true' + condStr);
else
assert_false(
ctl.validity.patternMismatch,
'The validity.patternMismatch should be false' + condStr);
});
}, data.name);
},
test_valueMissing: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "valueMissing");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.valueMissing,
'The validity.valueMissing should be true' + condStr);
else
assert_false(
ctl.validity.valueMissing,
'The validity.valueMissing should be false' + condStr);
});
}, data.name);
},
test_typeMismatch: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "typeMismatch");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.typeMismatch,
'The validity.typeMismatch should be true' + condStr);
else
assert_false(
ctl.validity.typeMismatch,
'The validity.typeMismatch should be false' + condStr);
});
}, data.name);
},
test_rangeOverflow: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "rangeOverflow");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.rangeOverflow,
'The validity.rangeOverflow should be true' + condStr);
else
assert_false(
ctl.validity.rangeOverflow,
'The validity.rangeOverflow should be false' + condStr);
});
}, data.name);
},
test_rangeUnderflow: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "rangeUnderflow");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.rangeUnderflow,
'The validity.rangeUnderflow should be true' + condStr);
else
assert_false(
ctl.validity.rangeUnderflow,
'The validity.rangeUnderflow should be false' + condStr);
});
}, data.name);
},
test_stepMismatch: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "stepMismatch");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.stepMismatch,
'The validity.stepMismatch should be true' + condStr);
else
assert_false(
ctl.validity.stepMismatch,
'The validity.stepMismatch should be false' + condStr);
});
}, data.name);
},
test_badInput: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "badInput");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.badInput,
'The validity.badInput should be true' + condStr);
else
assert_false(
ctl.validity.badInput,
'The validity.badInput should be false' + condStr);
});
}, data.name);
},
test_customError: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "customError");
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected) {
assert_true(
ctl.validity.customError,
'The validity.customError attribute should be true' + condStr);
// validationMessage returns the empty string if ctl is barred from
// constraint validation, which happens if ctl is disabled or readOnly.
if (ctl.disabled || ctl.readOnly) {
assert_equals(
ctl.validationMessage, '',
'The validationMessage attribute must be empty' + condStr);
} else {
assert_equals(
ctl.validationMessage, data.conditions.message,
'The validationMessage attribute should be \'' +
data.conditions.message + '\'' + condStr);
}
} else {
assert_false(
ctl.validity.customError,
'The validity.customError attribute should be false' + condStr);
assert_equals(
ctl.validationMessage, '',
'The validationMessage attribute must be empty' + condStr);
}
});
}, data.name);
},
test_isValid: function(ctl, data) {
var self = this;
test(function () {
self.iterate_over(ctl, data).forEach(function(val) {
const {ctl, expected, condStr} = val;
if (expected)
assert_true(
ctl.validity.valid,
'The validity.valid should be true' + condStr);
else
assert_false(
ctl.validity.valid,
'The validity.valid should be false' + condStr);
});
}, data.name);
},
test_willValidate: function(ctl, data) {
var self = this;
test(function () {
self.pre_check(ctl, "willValidate");
self.set_conditions(ctl, data.conditions);
if (data.ancestor) {
var dl = document.createElement("datalist");
dl.appendChild(ctl);
}
if (data.expected)
assert_true(ctl.willValidate, "The willValidate attribute should be true.");
else
assert_false(ctl.willValidate, "The willValidate attribute should be false.");
}, data.name);
},
test_checkValidity: function(ctl, data) {
var self = this;
test(function () {
var eventFired = false;
self.pre_check(ctl, "checkValidity");
self.set_conditions(ctl, data.conditions);
if (data.dirty)
self.set_dirty(ctl);
on_event(ctl, "invalid", function(e){
assert_equals(e.type, "invalid", "The invalid event should be fired.");
eventFired = true;
});
if (data.expected) {
assert_true(ctl.checkValidity(), "The checkValidity method should be true.");
assert_false(eventFired, "The invalid event should not be fired.");
} else {
assert_false(ctl.checkValidity(), "The checkValidity method should be false.");
assert_true(eventFired, "The invalid event should be fired.");
}
}, data.name);
test(function () {
var fm = document.createElement("form");
var ctl2 = ctl.cloneNode(true);
self.pre_check(ctl, "checkValidity");
self.set_conditions(ctl2, data.conditions);
fm.appendChild(ctl2);
document.body.appendChild(fm);
if (data.dirty)
self.set_dirty(ctl2);
var result = fm.checkValidity();
document.body.removeChild(fm);
if (data.expected)
assert_true(result, "The checkValidity method of the element's form owner should return true.");
else
assert_false(result, "The checkValidity method of the element's form owner should return false.");
}, data.name + " (in a form)");
},
test_reportValidity: function(ctl, data) {
var self = this;
test(function () {
var eventFired = false;
self.pre_check(ctl, "reportValidity");
self.set_conditions(ctl, data.conditions);
if (data.dirty)
self.set_dirty(ctl);
on_event(ctl, "invalid", function(e){
assert_equals(e.type, "invalid", "The invalid event should be fired.");
eventFired = true;
});
if (data.expected) {
assert_true(ctl.reportValidity(), "The reportValidity method should be true.");
assert_false(eventFired, "The invalid event should not be fired.");
} else {
assert_false(ctl.reportValidity(), "The reportValidity method should be false.");
assert_true(eventFired, "The invalid event should be fired.");
}
}, data.name);
test(function () {
var fm = document.createElement("form");
var ctl2 = ctl.cloneNode(true);
self.pre_check(ctl, "reportValidity");
self.set_conditions(ctl2, data.conditions);
fm.appendChild(ctl2);
document.body.appendChild(fm);
if (data.dirty)
self.set_dirty(ctl2);
var result = fm.reportValidity();
document.body.removeChild(fm);
if (data.expected)
assert_true(result, "The reportValidity method of the element's form owner should return true.");
else
assert_false(result, "The reportValidity method of the element's form owner should return false.");
}, data.name + " (in a form)");
},
test_support_type: function(ctl, typ, testName) {
test(function () {
assert_equals(ctl.type, typ, "The " + typ + " type should be supported.");
}, testName);
},
set_conditions: function(ctl, obj) {
[
"checked",
"disabled",
"max",
"maxlength",
"min",
"minlength",
"multiple",
"pattern",
"required",
"selected",
"step",
"value"
].forEach(function(item) {
ctl.removeAttribute(item);
});
for (var attr in obj) {
if (attr === "message")
ctl.setCustomValidity(obj[attr]);
else if (attr === "checked" || obj[attr] || obj[attr] === "")
ctl[attr] = obj[attr];
}
},
set_dirty: function(ctl) {
ctl.focus();
var old_value = ctl.value;
ctl.value = "a";
ctl.value = old_value;
},
pre_check: function(ctl, item) {
switch (item) {
case "willValidate":
assert_true(item in ctl, "The " + item + " attribute doesn't exist.");
break;
case "checkValidity":
case "reportValidity":
assert_true(item in ctl, "The " + item + " method doesn't exist.");
break;
case "tooLong":
case "tooShort":
case "patternMismatch":
case "typeMismatch":
case "stepMismatch":
case "rangeOverflow":
case "rangeUnderflow":
case "valueMissing":
case "badInput":
case "valid":
assert_true("validity" in ctl, "The validity attribute doesn't exist.");
assert_true(item in ctl.validity, "The " + item + " attribute doesn't exist.");
break;
case "customError":
assert_true("validity" in ctl, "The validity attribute doesn't exist.");
assert_true("setCustomValidity" in ctl, "The validity attribute doesn't exist.");
assert_true("validationMessage" in ctl, "The validity attribute doesn't exist.");
assert_true(item in ctl.validity, "The " + item + " attribute doesn't exist.");
break;
}
},
iterate_over: function(ctl, data) {
// Iterate over normal, disabled, readonly, and both (if applicable).
var ctlNormal = ctl.cloneNode(true);
this.set_conditions(ctlNormal, data.conditions);
if (data.dirty)
this.set_dirty(ctlNormal);
var ctlDisabled = ctl.cloneNode(true);
this.set_conditions(ctlDisabled, data.conditions);
if (data.dirty)
this.set_dirty(ctlDisabled);
ctlDisabled.disabled = true;
var expectedImmutable =
data.expectedImmutable !== undefined ? data.expectedImmutable : data.expected;
var variants = [
{ctl: ctlNormal, expected: data.expected, condStr: '.'},
{ctl: ctlDisabled, expected: expectedImmutable, condStr: ', when control is disabled.'},
];
if ('readOnly' in ctl) {
var ctlReadonly = ctl.cloneNode(true);
this.set_conditions(ctlReadonly, data.conditions);
if (data.dirty)
this.set_dirty(ctlReadonly);
ctlReadonly.readOnly = true;
var ctlBoth = ctl.cloneNode(true);
this.set_conditions(ctlBoth, data.conditions);
if (data.dirty)
this.set_dirty(ctlBoth);
ctlBoth.disabled = true;
ctlBoth.readOnly = true;
variants.push({
ctl: ctlReadonly,
expected: expectedImmutable,
condStr: ', when control is readonly.'
});
variants.push({
ctl: ctlBoth,
expected: expectedImmutable,
condStr: ', when control is disabled & readonly.'
});
}
return variants;
},
run_test: function(testee, method) {
var testMethod = "test_" + method;
if (typeof this[testMethod] !== "function") {
return false;
}
var ele = null,
prefix = "";
for (var i = 0; i < testee.length; i++) {
if (testee[i].types.length > 0) {
for (var typ in testee[i].types) {
ele = document.createElement(testee[i].tag);
document.body.appendChild(ele);
try {
ele.type = testee[i].types[typ];
} catch (e) {
//Do nothing, avoid the runtime error breaking the test
}
prefix = "[" + testee[i].tag.toUpperCase() + " in " + testee[i].types[typ].toUpperCase() + " status] ";
if (ele.type != testee[i].types[typ]) {
this.test_support_type(
ele,
testee[i].types[typ],
prefix + "The " + testee[i].types[typ] + " type must be supported."
);
continue;
}
for (var j = 0; j < testee[i].testData.length; j++) {
testee[i].testData[j].name = testee[i].testData[j].name.replace(/\[.*\]\s/g, prefix);
this[testMethod](ele, testee[i].testData[j]);
}
}
} else {
ele = document.createElement(testee[i].tag);
document.body.appendChild(ele);
prefix = "[" + testee[i].tag + "] ";
if (testElements[i].tag === "select") {
ele.add(new Option('test1', '')); // Placeholder
ele.add(new Option("test2", 1));
}
for (var item in testee[i].testData) {
testee[i].testData[item].name = testee[i].testData[item].name.replace("[target]", prefix);
this[testMethod](ele, testee[i].testData[item]);
}
}
}
}
}