test_required_attribute.html (12176B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=345822 5 --> 6 <head> 7 <title>Test for Bug 345822</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 10 </head> 11 <body> 12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345822">Mozilla Bug 345822</a> 13 <p id="display"></p> 14 <div id="content"> 15 <form> 16 </form> 17 </div> 18 <pre id="test"> 19 <script type="application/javascript"> 20 21 /** Test for Bug 345822 */ 22 23 function fmtElement(element) { 24 return `<${element.tagName} type='${element.type}' value='${element.value}'>`; 25 } 26 27 function checkNotSufferingFromBeingMissing(element, doNotApply) 28 { 29 ok(!element.validity.valueMissing, 30 `${fmtElement(element)} should not suffer from value missing`); 31 ok(element.validity.valid, `${fmtElement(element)} should be valid`); 32 ok(element.checkValidity(), `${fmtElement(element)} should be valid`); 33 is(element.validationMessage, "", 34 "Validation message should be the empty string for " + fmtElement(element)); 35 36 if (doNotApply) { 37 ok(!element.matches(':valid'), ":valid should not apply to " + fmtElement(element)); 38 ok(!element.matches(':invalid'), ":invalid should not apply to " + fmtElement(element)); 39 } else { 40 ok(element.matches(':valid'), ":valid should apply to " + fmtElement(element)); 41 ok(!element.matches(':invalid'), ":invalid should not apply to " + fmtElement(element)); 42 } 43 } 44 45 function checkSufferingFromBeingMissing(element) 46 { 47 ok(element.validity.valueMissing, "Element should suffer from value missing"); 48 ok(!element.validity.valid, "Element should not be valid"); 49 ok(!element.checkValidity(), "Element should not be valid"); 50 51 if (element.type == 'checkbox') 52 { 53 is(element.validationMessage, 54 "Please check this box if you want to proceed.", 55 "Validation message is wrong"); 56 } 57 else if (element.type == 'radio') 58 { 59 is(element.validationMessage, 60 "Please select one of these options.", 61 "Validation message is wrong"); 62 } 63 else if (element.type == 'file') 64 { 65 is(element.validationMessage, 66 "Please select a file.", 67 "Validation message is wrong"); 68 } 69 else if (element.type == 'number') 70 { 71 is(element.validationMessage, 72 "Please enter a number.", 73 "Validation message is wrong"); 74 } 75 else // text fields 76 { 77 is(element.validationMessage, 78 "Please fill out this field.", 79 "Validation message is wrong"); 80 } 81 82 ok(!element.matches(':valid'), ":valid should apply"); 83 ok(element.matches(':invalid'), ":invalid should not apply"); 84 } 85 86 function checkTextareaRequiredValidity() 87 { 88 var element = document.createElement('textarea'); 89 document.forms[0].appendChild(element); 90 91 SpecialPowers.wrap(element).value = ''; 92 element.required = false; 93 checkNotSufferingFromBeingMissing(element); 94 95 element.required = true; 96 checkSufferingFromBeingMissing(element); 97 98 element.readOnly = true; 99 checkNotSufferingFromBeingMissing(element, true); 100 101 element.readOnly = false; 102 checkSufferingFromBeingMissing(element); 103 104 SpecialPowers.wrap(element).value = 'foo'; 105 checkNotSufferingFromBeingMissing(element); 106 107 SpecialPowers.wrap(element).value = ''; 108 checkSufferingFromBeingMissing(element); 109 110 element.required = false; 111 checkNotSufferingFromBeingMissing(element); 112 113 element.focus(); 114 element.required = true; 115 SpecialPowers.wrap(element).value = 'foobar'; 116 element.blur(); 117 element.form.reset(); 118 checkSufferingFromBeingMissing(element); 119 120 SpecialPowers.wrap(element).value = ''; 121 element.form.reportValidity(); 122 checkSufferingFromBeingMissing(element); 123 124 element.form.reset(); 125 checkSufferingFromBeingMissing(element); 126 127 // TODO: for the moment, a textarea outside of a document is mutable. 128 SpecialPowers.wrap(element).value = ''; // To make -moz-ui-valid apply. 129 element.required = false; 130 document.forms[0].removeChild(element); 131 checkNotSufferingFromBeingMissing(element); 132 } 133 134 function checkInputRequiredNotApply(type, isBarred) 135 { 136 var element = document.createElement('input'); 137 element.type = type; 138 document.forms[0].appendChild(element); 139 140 SpecialPowers.wrap(element).value = ''; 141 element.required = false; 142 checkNotSufferingFromBeingMissing(element, isBarred); 143 144 element.required = true; 145 checkNotSufferingFromBeingMissing(element, isBarred); 146 147 element.required = false; 148 149 document.forms[0].removeChild(element); 150 checkNotSufferingFromBeingMissing(element, isBarred); 151 } 152 153 function getValidExampleInputValue(type) 154 { 155 switch (type) { 156 case 'email': 157 return 'foo@bar.com'; 158 case 'url': 159 return 'http://mozilla.org/'; 160 case 'number': 161 return '42'; 162 case 'date': 163 return '2010-10-10'; 164 case 'time': 165 return '21:21'; 166 case 'datetime-local': 167 return '2010-10-10T21:21'; 168 case 'month': 169 return '2010-10'; 170 case 'week': 171 return '2010-W42'; 172 default: 173 return 'foo'; 174 } 175 } 176 177 function checkInputRequiredValidity(type) 178 { 179 var element = document.createElement('input'); 180 element.type = type; 181 document.forms[0].appendChild(element); 182 183 SpecialPowers.wrap(element).value = ''; 184 element.required = false; 185 checkNotSufferingFromBeingMissing(element); 186 187 element.required = true; 188 checkSufferingFromBeingMissing(element); 189 190 element.readOnly = true; 191 checkNotSufferingFromBeingMissing(element, true); 192 193 element.readOnly = false; 194 checkSufferingFromBeingMissing(element); 195 196 SpecialPowers.wrap(element).value = getValidExampleInputValue(type); 197 checkNotSufferingFromBeingMissing(element); 198 199 SpecialPowers.wrap(element).value = ''; 200 checkSufferingFromBeingMissing(element); 201 202 element.focus(); 203 element.required = true; 204 SpecialPowers.wrap(element).value = 'foobar'; 205 element.blur(); 206 element.form.reset(); 207 checkSufferingFromBeingMissing(element); 208 209 SpecialPowers.wrap(element).value = ''; 210 element.form.reportValidity(); 211 checkSufferingFromBeingMissing(element); 212 213 element.form.reset(); 214 checkSufferingFromBeingMissing(element); 215 216 element.required = true; 217 SpecialPowers.wrap(element).value = ''; // To make :-moz-ui-valid apply. 218 checkSufferingFromBeingMissing(element); 219 document.forms[0].removeChild(element); 220 // Removing the child changes nothing about whether it's valid 221 checkSufferingFromBeingMissing(element); 222 } 223 224 function checkInputRequiredValidityForCheckbox() 225 { 226 var element = document.createElement('input'); 227 element.type = 'checkbox'; 228 document.forms[0].appendChild(element); 229 230 element.checked = false; 231 element.required = false; 232 checkNotSufferingFromBeingMissing(element); 233 234 element.required = true; 235 checkSufferingFromBeingMissing(element); 236 237 element.checked = true; 238 checkNotSufferingFromBeingMissing(element); 239 240 element.checked = false; 241 checkSufferingFromBeingMissing(element); 242 243 element.required = false; 244 checkNotSufferingFromBeingMissing(element); 245 246 element.focus(); 247 element.required = true; 248 element.checked = true; 249 element.blur(); 250 element.form.reset(); 251 checkSufferingFromBeingMissing(element); 252 253 element.required = true; 254 element.checked = false; 255 element.form.reportValidity(); 256 checkSufferingFromBeingMissing(element); 257 258 element.form.reset(); 259 checkSufferingFromBeingMissing(element); 260 261 element.required = true; 262 element.checked = false; 263 document.forms[0].removeChild(element); 264 checkSufferingFromBeingMissing(element); 265 } 266 267 function checkInputRequiredValidityForRadio() 268 { 269 var element = document.createElement('input'); 270 element.type = 'radio'; 271 element.name = 'test' 272 document.forms[0].appendChild(element); 273 274 element.checked = false; 275 element.required = false; 276 checkNotSufferingFromBeingMissing(element); 277 278 element.required = true; 279 checkSufferingFromBeingMissing(element); 280 281 element.checked = true; 282 checkNotSufferingFromBeingMissing(element); 283 284 element.checked = false; 285 checkSufferingFromBeingMissing(element); 286 287 // A required radio button should not suffer from value missing if another 288 // radio button from the same group is checked. 289 var element2 = document.createElement('input'); 290 element2.type = 'radio'; 291 element2.name = 'test'; 292 293 element2.checked = true; 294 element2.required = false; 295 document.forms[0].appendChild(element2); 296 297 // Adding a checked radio should make required radio in the group not 298 // suffering from being missing. 299 checkNotSufferingFromBeingMissing(element); 300 301 element.checked = false; 302 element2.checked = false; 303 checkSufferingFromBeingMissing(element); 304 305 // The other radio button should not be disabled. 306 // A disabled checked radio button in the radio group 307 // is enough to not suffer from value missing. 308 element2.checked = true; 309 element2.disabled = true; 310 checkNotSufferingFromBeingMissing(element); 311 312 // If a radio button is not required but another radio button is required in 313 // the same group, the not required radio button should suffer from value 314 // missing. 315 element2.disabled = false; 316 element2.checked = false; 317 element.required = false; 318 element2.required = true; 319 checkSufferingFromBeingMissing(element); 320 checkSufferingFromBeingMissing(element2); 321 322 element.checked = true; 323 checkNotSufferingFromBeingMissing(element2); 324 325 // The checked radio is not in the group anymore, element2 should be invalid. 326 element.form.removeChild(element); 327 checkNotSufferingFromBeingMissing(element); 328 checkSufferingFromBeingMissing(element2); 329 330 element2.focus(); 331 element2.required = true; 332 element2.checked = true; 333 element2.blur(); 334 element2.form.reset(); 335 checkSufferingFromBeingMissing(element2); 336 337 element2.required = true; 338 element2.checked = false; 339 element2.form.reportValidity(); 340 checkSufferingFromBeingMissing(element2); 341 342 element2.form.reset(); 343 checkSufferingFromBeingMissing(element2); 344 345 element2.required = true; 346 element2.checked = false; 347 document.forms[0].removeChild(element2); 348 checkSufferingFromBeingMissing(element2); 349 } 350 351 function checkInputRequiredValidityForFile() 352 { 353 var element = document.createElement('input'); 354 element.type = 'file' 355 document.forms[0].appendChild(element); 356 357 var file = new File([""], "345822_file"); 358 359 SpecialPowers.wrap(element).value = ""; 360 element.required = false; 361 checkNotSufferingFromBeingMissing(element); 362 363 element.required = true; 364 checkSufferingFromBeingMissing(element); 365 366 SpecialPowers.wrap(element).mozSetFileArray([file]); 367 checkNotSufferingFromBeingMissing(element); 368 369 SpecialPowers.wrap(element).value = ""; 370 checkSufferingFromBeingMissing(element); 371 372 element.required = false; 373 checkNotSufferingFromBeingMissing(element); 374 375 element.focus(); 376 SpecialPowers.wrap(element).mozSetFileArray([file]); 377 element.required = true; 378 element.blur(); 379 element.form.reset(); 380 checkSufferingFromBeingMissing(element); 381 382 element.required = true; 383 SpecialPowers.wrap(element).value = ''; 384 element.form.reportValidity(); 385 checkSufferingFromBeingMissing(element); 386 387 element.form.reset(); 388 checkSufferingFromBeingMissing(element); 389 390 element.required = true; 391 SpecialPowers.wrap(element).value = ''; 392 document.forms[0].removeChild(element); 393 checkSufferingFromBeingMissing(element); 394 } 395 396 checkTextareaRequiredValidity(); 397 398 // The require attribute behavior depend of the input type. 399 // First of all, checks for types that make the element barred from 400 // constraint validation. 401 var typeBarredFromConstraintValidation = ["hidden", "button", "reset"]; 402 for (type of typeBarredFromConstraintValidation) { 403 checkInputRequiredNotApply(type, true); 404 } 405 406 // Then, checks for the types which do not use the required attribute. 407 var typeRequireNotApply = ['range', 'color', 'submit', 'image']; 408 for (type of typeRequireNotApply) { 409 checkInputRequiredNotApply(type, false); 410 } 411 412 // Now, checking for all types which accept the required attribute. 413 var typeRequireApply = ["text", "password", "search", "tel", "email", "url", 414 "number", "date", "time", "month", "week", 415 "datetime-local"]; 416 417 for (type of typeRequireApply) { 418 checkInputRequiredValidity(type); 419 } 420 421 checkInputRequiredValidityForCheckbox(); 422 checkInputRequiredValidityForRadio(); 423 checkInputRequiredValidityForFile(); 424 425 </script> 426 </pre> 427 </body> 428 </html>