test_step_attribute.html (36421B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=635553 5 --> 6 <head> 7 <title>Test for Bug 635553</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=635499">Mozilla Bug 635499</a> 13 <p id="display"></p> 14 <div id="content" style="display: none"> 15 </div> 16 <pre id="test"> 17 <script type="application/javascript"> 18 19 /** Test for Bug 635553 */ 20 21 var data = [ 22 { type: 'hidden', apply: false }, 23 { type: 'text', apply: false }, 24 { type: 'search', apply: false }, 25 { type: 'tel', apply: false }, 26 { type: 'url', apply: false }, 27 { type: 'email', apply: false }, 28 { type: 'password', apply: false }, 29 { type: 'date', apply: true }, 30 { type: 'month', apply: true }, 31 { type: 'week', apply: true }, 32 { type: 'time', apply: true }, 33 { type: 'datetime-local', apply: true }, 34 { type: 'number', apply: true }, 35 { type: 'range', apply: true }, 36 { type: 'color', apply: false }, 37 { type: 'checkbox', apply: false }, 38 { type: 'radio', apply: false }, 39 { type: 'file', apply: false }, 40 { type: 'submit', apply: false }, 41 { type: 'image', apply: false }, 42 { type: 'reset', apply: false }, 43 { type: 'button', apply: false }, 44 ]; 45 46 function getFreshElement(type) { 47 var elmt = document.createElement('input'); 48 elmt.type = type; 49 return elmt; 50 } 51 52 function checkValidity(aElement, aValidity, aApply, aData) 53 { 54 aValidity = aApply ? aValidity : true; 55 56 is(aElement.validity.valid, aValidity, 57 "element validity should be " + aValidity); 58 is(aElement.validity.stepMismatch, !aValidity, 59 "element step mismatch status should be " + !aValidity); 60 61 if (aValidity) { 62 is(aElement.validationMessage, "", "There should be no validation message."); 63 } else { 64 if (aElement.validity.rangeUnderflow) { 65 var underflowMsg = 66 (aElement.type == "date" || aElement.type == "time") ? 67 ("Please select a value that is no earlier than " + aElement.min + ".") : 68 ("Please select a value that is no less than " + aElement.min + "."); 69 is(aElement.validationMessage, underflowMsg, 70 "Checking range underflow validation message."); 71 } else if (aData.low == aData.high) { 72 is(aElement.validationMessage, "Please select a valid value. " + 73 "The nearest valid value is " + aData.low + ".", 74 "There should be a validation message."); 75 } else { 76 is(aElement.validationMessage, "Please select a valid value. " + 77 "The two nearest valid values are " + aData.low + " and " + aData.high + ".", 78 "There should be a validation message."); 79 } 80 } 81 82 is(aElement.matches(":valid"), aElement.willValidate && aValidity, 83 (aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply"); 84 is(aElement.matches(":invalid"), aElement.willValidate && !aValidity, 85 (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply"); 86 } 87 88 for (var test of data) { 89 var input = getFreshElement(test.type); 90 var apply = test.apply; 91 92 if (test.todo) { 93 todo_is(input.type, test.type, test.type + " isn't implemented yet"); 94 continue; 95 } 96 97 // The element should be valid, there should be no step mismatch. 98 checkValidity(input, true, apply); 99 100 // Checks to do for all types that support step: 101 // - check for @step=0, 102 // - check for @step behind removed, 103 // - check for @step being 'any' with different case variations. 104 switch (input.type) { 105 case 'text': 106 case 'hidden': 107 case 'search': 108 case 'password': 109 case 'tel': 110 case 'radio': 111 case 'checkbox': 112 case 'reset': 113 case 'button': 114 case 'submit': 115 case 'image': 116 case 'color': 117 input.value = '0'; 118 checkValidity(input, true, apply); 119 break; 120 case 'url': 121 input.value = 'http://mozilla.org'; 122 checkValidity(input, true, apply); 123 break; 124 case 'email': 125 input.value = 'foo@bar.com'; 126 checkValidity(input, true, apply); 127 break; 128 case 'file': 129 var file = new File([''], '635499_file'); 130 131 SpecialPowers.wrap(input).mozSetFileArray([file]); 132 checkValidity(input, true, apply); 133 134 break; 135 case 'date': 136 // For date, the step is calulated on the timestamp since 1970-01-01 137 // which mean that for all dates prior to the epoch, this timestamp is < 0 138 // and the behavior might differ, therefore we have to test for these cases. 139 140 // When step is invalid, every date is valid 141 input.step = 0; 142 input.value = '2012-07-05'; 143 checkValidity(input, true, apply); 144 145 input.step = 'foo'; 146 input.value = '1970-01-01'; 147 checkValidity(input, true, apply); 148 149 input.step = '-1'; 150 input.value = '1969-12-12'; 151 checkValidity(input, true, apply); 152 153 input.removeAttribute('step'); 154 input.value = '1500-01-01'; 155 checkValidity(input, true, apply); 156 157 input.step = 'any'; 158 input.value = '1966-12-12'; 159 checkValidity(input, true, apply); 160 161 input.step = 'ANY'; 162 input.value = '2013-02-03'; 163 checkValidity(input, true, apply); 164 165 // When min is set to a valid date, there is a step base. 166 input.min = '2008-02-28'; 167 input.step = '2'; 168 input.value = '2008-03-01'; 169 checkValidity(input, true, apply); 170 171 input.value = '2008-02-29'; 172 checkValidity(input, false, apply, { low: "2008-02-28", high: "2008-03-01" }); 173 174 input.min = '2008-02-27'; 175 input.value = '2008-02-28'; 176 checkValidity(input, false, apply, { low: "2008-02-27", high: "2008-02-29" }); 177 178 input.min = '2009-02-27'; 179 input.value = '2009-02-28'; 180 checkValidity(input, false, apply, { low: "2009-02-27", high: "2009-03-01" }); 181 182 input.min = '2009-02-01'; 183 input.step = '1.1'; 184 input.value = '2009-02-02'; 185 checkValidity(input, true, apply); 186 187 // Without any step attribute the date is valid 188 input.removeAttribute('step'); 189 checkValidity(input, true, apply); 190 191 input.min = '1950-01-01'; 192 input.step = '366'; 193 input.value = '1951-01-01'; 194 checkValidity(input, false, apply, { low: "1950-01-01", high: "1951-01-02" }); 195 196 input.min = '1951-01-01'; 197 input.step = '365'; 198 input.value = '1952-01-01'; 199 checkValidity(input, true, apply); 200 201 input.step = '0.9'; 202 input.value = '1951-01-02'; 203 is(input.step, '0.9', "check that step value is unchanged"); 204 checkValidity(input, true, apply); 205 206 input.step = '0.4'; 207 input.value = '1951-01-02'; 208 is(input.step, '0.4', "check that step value is unchanged"); 209 checkValidity(input, true, apply); 210 211 input.step = '1.5'; 212 input.value = '1951-01-02'; 213 is(input.step, '1.5', "check that step value is unchanged"); 214 checkValidity(input, false, apply, { low: "1951-01-01", high: "1951-01-03" }); 215 216 input.value = '1951-01-08'; 217 checkValidity(input, false, apply, { low: "1951-01-07", high: "1951-01-09" }); 218 219 input.step = '3000'; 220 input.min= '1968-01-01'; 221 input.value = '1968-05-12'; 222 checkValidity(input, false, apply, { low: "1968-01-01", high: "1976-03-19" }); 223 224 input.value = '1971-01-01'; 225 checkValidity(input, false, apply, { low: "1968-01-01", high: "1976-03-19" }); 226 227 input.value = '1991-01-01'; 228 checkValidity(input, false, apply, { low: "1984-06-05", high: "1992-08-22" }); 229 230 input.value = '1984-06-05'; 231 checkValidity(input, true, apply); 232 233 input.value = '1992-08-22'; 234 checkValidity(input, true, apply); 235 236 input.step = '2.1'; 237 input.min = '1991-01-01'; 238 input.value = '1991-01-01'; 239 checkValidity(input, true, apply); 240 241 input.value = '1991-01-02'; 242 checkValidity(input, false, apply, { low: "1991-01-01", high: "1991-01-03" }); 243 244 input.value = '1991-01-03'; 245 checkValidity(input, true, apply); 246 247 input.step = '2.1'; 248 input.min = '1969-12-20'; 249 input.value = '1969-12-20'; 250 checkValidity(input, true, apply); 251 252 input.value = '1969-12-21'; 253 checkValidity(input, false, apply, { low: "1969-12-20", high: "1969-12-22" }); 254 255 input.value = '1969-12-22'; 256 checkValidity(input, true, apply); 257 258 break; 259 case 'number': 260 // When step=0, the allowed step is 1. 261 input.step = '0'; 262 input.value = '1.2'; 263 checkValidity(input, false, apply, { low: 1, high: 2 }); 264 265 input.value = '1'; 266 checkValidity(input, true, apply); 267 268 input.value = '0'; 269 checkValidity(input, true, apply); 270 271 // When step is NaN, the allowed step value is 1. 272 input.step = 'foo'; 273 input.value = '1'; 274 checkValidity(input, true, apply); 275 276 input.value = '1.5'; 277 checkValidity(input, false, apply, { low: 1, high: 2 }); 278 279 // When step is negative, the allowed step value is 1. 280 input.step = '-0.1'; 281 checkValidity(input, false, apply, { low: 1, high: 2 }); 282 283 input.value = '1'; 284 checkValidity(input, true, apply); 285 286 // When step is missing, the allowed step value is 1. 287 input.removeAttribute('step'); 288 input.value = '1.5'; 289 checkValidity(input, false, apply, { low: 1, high: 2 }); 290 291 input.value = '1'; 292 checkValidity(input, true, apply); 293 294 // When step is 'any', all values are fine wrt to step. 295 input.step = 'any'; 296 checkValidity(input, true, apply); 297 298 input.step = 'aNy'; 299 input.value = '1337'; 300 checkValidity(input, true, apply); 301 302 input.step = 'AnY'; 303 input.value = '0.1'; 304 checkValidity(input, true, apply); 305 306 input.step = 'ANY'; 307 input.value = '-13.37'; 308 checkValidity(input, true, apply); 309 310 // When min is set to a valid float, there is a step base. 311 input.min = '1'; 312 input.step = '2'; 313 input.value = '3'; 314 checkValidity(input, true, apply); 315 316 input.value = '2'; 317 checkValidity(input, false, apply, { low: 1, high: 3 }); 318 319 input.removeAttribute('step'); // step = 1 320 input.min = '0.5'; 321 input.value = '5.5'; 322 checkValidity(input, true, apply); 323 324 input.value = '1'; 325 checkValidity(input, false, apply, { low: 0.5, high: 1.5 }); 326 327 input.min = '-0.1'; 328 input.step = '1'; 329 input.value = '0.9'; 330 checkValidity(input, true, apply); 331 332 input.value = '0.1'; 333 checkValidity(input, false, apply, { low: -0.1, high: 0.9 }); 334 335 // When min is set to NaN, there is no step base (step base=0 actually). 336 input.min = 'foo'; 337 input.step = '1'; 338 input.value = '1'; 339 checkValidity(input, true, apply); 340 341 input.value = '0.5'; 342 checkValidity(input, false, apply, { low: 0, high: 1 }); 343 344 input.min = ''; 345 input.value = '1'; 346 checkValidity(input, true, apply); 347 348 input.value = '0.5'; 349 checkValidity(input, false, apply, { low: 0, high: 1 }); 350 351 input.removeAttribute('min'); 352 353 // If value isn't a number, the element isn't invalid. 354 input.value = ''; 355 checkValidity(input, true, apply); 356 357 // Regular situations. 358 input.step = '2'; 359 input.value = '1.5'; 360 checkValidity(input, false, apply, { low: 0, high: 2 }); 361 362 input.value = '42.0'; 363 checkValidity(input, true, apply); 364 365 input.step = '0.1'; 366 input.value = '-0.1'; 367 checkValidity(input, true, apply); 368 369 input.step = '2'; 370 input.removeAttribute('min'); 371 input.max = '10'; 372 input.value = '-9'; 373 checkValidity(input, false, apply, {low: -10, high: -8}); 374 375 // If there is a value defined but no min, the step base is the value. 376 input = getFreshElement(test.type); 377 input.setAttribute('value', '1'); 378 input.step = 2; 379 checkValidity(input, true, apply); 380 381 input.value = 3; 382 checkValidity(input, true, apply); 383 384 input.value = 2; 385 checkValidity(input, false, apply, {low: 1, high: 3}); 386 387 // Should also work with defaultValue. 388 input = getFreshElement(test.type); 389 input.defaultValue = 1; 390 input.step = 2; 391 checkValidity(input, true, apply); 392 393 input.value = 3; 394 checkValidity(input, true, apply); 395 396 input.value = 2; 397 checkValidity(input, false, apply, {low: 1, high: 3}); 398 399 // Rounding issues. 400 input = getFreshElement(test.type); 401 input.min = 0.1; 402 input.step = 0.2; 403 input.value = 0.3; 404 checkValidity(input, true, apply); 405 406 // Check that when the higher value is higher than max, we don't show it. 407 input = getFreshElement(test.type); 408 input.step = '2'; 409 input.min = '1'; 410 input.max = '10.9'; 411 input.value = '10'; 412 413 is(input.validationMessage, "Please select a valid value. " + 414 "The nearest valid value is 9.", 415 "The validation message should not include the higher value."); 416 break; 417 case 'range': 418 // Range is special in that it clamps to valid values, so it is much 419 // rarer for it to be invalid. 420 421 // When step=0, the allowed value step is 1. 422 input.step = '0'; 423 input.value = '1.2'; 424 is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 425 checkValidity(input, true, apply); 426 427 input.value = '1'; 428 is(input.value, '1', "check that the value coincides with a step"); 429 checkValidity(input, true, apply); 430 431 input.value = '0'; 432 is(input.value, '0', "check that the value coincides with a step"); 433 checkValidity(input, true, apply); 434 435 // When step is NaN, the allowed step value is 1. 436 input.step = 'foo'; 437 input.value = '1'; 438 is(input.value, '1', "check that the value coincides with a step"); 439 checkValidity(input, true, apply); 440 441 input.value = '1.5'; 442 is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 443 checkValidity(input, true, apply); 444 445 // When step is negative, the allowed step value is 1. 446 input.step = '-0.1'; 447 is(input.value, '2', "check that the value still coincides with a step"); 448 checkValidity(input, true, apply); 449 450 input.value = '1'; 451 is(input.value, '1', "check that the value coincides with a step"); 452 checkValidity(input, true, apply); 453 454 // When step is missing, the allowed step value is 1. 455 input.removeAttribute('step'); 456 input.value = '1.5'; 457 is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 458 checkValidity(input, true, apply); 459 460 input.value = '1'; 461 is(input.value, '1', "check that the value coincides with a step"); 462 checkValidity(input, true, apply); 463 464 // When step is 'any', all values are fine wrt to step. 465 input.step = 'any'; 466 checkValidity(input, true, apply); 467 468 input.step = 'aNy'; 469 input.value = '97'; 470 is(input.value, '97', "check that the value for step=aNy is unchanged"); 471 checkValidity(input, true, apply); 472 473 input.step = 'AnY'; 474 input.value = '0.1'; 475 is(input.value, '0.1', "check that a positive fractional value with step=AnY is unchanged"); 476 checkValidity(input, true, apply); 477 478 input.step = 'ANY'; 479 input.min = -100; 480 input.value = '-13.37'; 481 is(input.value, '-13.37', "check that a negative fractional value with step=ANY is unchanged"); 482 checkValidity(input, true, apply); 483 484 // When min is set to a valid float, there is a step base. 485 input.min = '1'; // the step base 486 input.step = '2'; 487 input.value = '3'; 488 is(input.value, '3', "check that the value coincides with a step"); 489 checkValidity(input, true, apply); 490 491 input.value = '2'; 492 is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 493 checkValidity(input, true, apply); 494 495 input.value = '1.99'; 496 is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 497 checkValidity(input, true, apply); 498 499 input.removeAttribute('step'); // step = 1 500 input.min = '0.5'; // step base 501 input.value = '5.5'; 502 is(input.value, '5.5', "check that the value coincides with a step"); 503 checkValidity(input, true, apply); 504 505 input.value = '1'; 506 is(input.value, '1.5', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 507 checkValidity(input, true, apply); 508 509 input.min = '-0.1'; // step base 510 input.step = '1'; 511 input.value = '0.9'; 512 is(input.value, '0.9', "the value should be a valid step"); 513 checkValidity(input, true, apply); 514 515 input.value = '0.1'; 516 is(input.value, '-0.1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 517 checkValidity(input, true, apply); 518 519 // When min is set to NaN, the step base is the value. 520 input.min = 'foo'; 521 input.step = '1'; 522 input.value = '1'; 523 is(input.value, '1', "check that the value coincides with a step"); 524 checkValidity(input, true, apply); 525 526 input.value = '0.5'; 527 is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 528 checkValidity(input, true, apply); 529 530 input.min = ''; 531 input.value = '1'; 532 is(input.value, '1', "check that the value coincides with a step"); 533 checkValidity(input, true, apply); 534 535 input.value = '0.5'; 536 is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 537 checkValidity(input, true, apply); 538 539 input.removeAttribute('min'); 540 541 // Test when the value isn't a number 542 input.value = ''; 543 is(input.value, '50', "value be should default to the value midway between the minimum (0) and the maximum (100)"); 544 checkValidity(input, true, apply); 545 546 // Regular situations. 547 input.step = '2'; 548 input.value = '1.5'; 549 is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 550 checkValidity(input, true, apply); 551 552 input.value = '42.0'; 553 is(input.value, '42.0', "check that the value coincides with a step"); 554 checkValidity(input, true, apply); 555 556 input.step = '0.1'; 557 input.value = '-0.1'; 558 is(input.value, '0', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 559 checkValidity(input, true, apply); 560 561 input.step = '2'; 562 input.removeAttribute('min'); 563 input.max = '10'; 564 input.value = '-9'; 565 is(input.value, '0', "check the value is clamped to the minimum's default of zero"); 566 checkValidity(input, true, apply); 567 568 // If @value is defined but not @min, the step base is @value. 569 input = getFreshElement(test.type); 570 input.setAttribute('value', '1'); 571 input.step = 2; 572 is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 573 checkValidity(input, true, apply); 574 575 input.value = 3; 576 is(input.value, '3', "check that the value coincides with a step"); 577 checkValidity(input, true, apply); 578 579 input.value = 2; 580 is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 581 checkValidity(input, true, apply); 582 583 // Should also work with defaultValue. 584 input = getFreshElement(test.type); 585 input.defaultValue = 1; 586 input.step = 2; 587 is(input.value, '1', "check that the value coincides with a step"); 588 checkValidity(input, true, apply); 589 590 input.value = 3; 591 is(input.value, '3', "check that the value coincides with a step"); 592 checkValidity(input, true, apply); 593 594 input.value = 2; 595 is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); 596 checkValidity(input, true, apply); 597 598 // Check contrived error case where there are no valid steps in range: 599 // No @min, so the step base is the default minimum, zero, the valid 600 // range is 0-1, -1 gets clamped to zero. 601 input = getFreshElement(test.type); 602 input.step = '3'; 603 input.max = '1'; 604 input.defaultValue = '-1'; 605 is(input.value, '0', "the value should have been clamped to the default minimum, zero"); 606 checkValidity(input, false, apply, {low: -1, high: -1}); 607 608 // Check that when the closest of the two steps that the value is between 609 // is greater than the maximum we sanitize to the lower step. 610 input = getFreshElement(test.type); 611 input.step = '2'; 612 input.min = '1'; 613 input.max = '10.9'; 614 input.value = '10.8'; // closest step in 11, but 11 > maximum 615 is(input.value, '9', "check that the value coincides with a step"); 616 617 // The way that step base is defined, the converse (the value not being 618 // on a step, and the nearest step being a value that would be underflow) 619 // is not possible, so nothing to test there. 620 621 is(input.validationMessage, "", 622 "The validation message should be empty."); 623 break; 624 case 'time': 625 // Tests invalid step values. That defaults to step = 1 minute (60). 626 var values = [ '0', '-1', 'foo', 'any', 'ANY', 'aNy' ]; 627 for (var value of values) { 628 input.step = value; 629 input.value = '19:06:00'; 630 checkValidity(input, true, apply); 631 input.value = '19:06:51'; 632 if (value.toLowerCase() != 'any') { 633 checkValidity(input, false, apply, {low: '19:06', high: '19:07'}); 634 } else { 635 checkValidity(input, true, apply); 636 } 637 } 638 639 // No step means that we use the default step value. 640 input.removeAttribute('step'); 641 input.value = '19:06:00'; 642 checkValidity(input, true, apply); 643 input.value = '19:06:51'; 644 checkValidity(input, false, apply, {low: '19:06', high: '19:07'}); 645 646 var tests = [ 647 // With step=1, we allow values by the second. 648 { step: '1', value: '19:11:01', min: '00:00', result: true }, 649 { step: '1', value: '19:11:01.001', min: '00:00', result: false, 650 low: '19:11:01', high: '19:11:02' }, 651 { step: '1', value: '19:11:01.1', min: '00:00', result: false, 652 low: '19:11:01', high: '19:11:02' }, 653 // When step >= 86400000, only the minimum value is valid. 654 // This is actually @value if there is no @min. 655 { step: '86400000', value: '00:00', result: true }, 656 { step: '86400000', value: '00:01', result: true }, 657 { step: '86400000', value: '00:00', min: '00:01', result: false }, 658 { step: '86400000', value: '00:01', min: '00:00', result: false, 659 low: '00:00', high: '00:00' }, 660 // When step < 1, it should just work. 661 { step: '0.1', value: '15:05:05.1', min: '00:00', result: true }, 662 { step: '0.1', value: '15:05:05.101', min: '00:00', result: false, 663 low: '15:05:05.100', high: '15:05:05.200' }, 664 { step: '0.2', value: '15:05:05.2', min: '00:00', result: true }, 665 { step: '0.2', value: '15:05:05.1', min: '00:00', result: false, 666 low: '15:05:05', high: '15:05:05.200' }, 667 { step: '0.01', value: '15:05:05.01', min: '00:00', result: true }, 668 { step: '0.01', value: '15:05:05.011', min: '00:00', result: false, 669 low: '15:05:05.010', high: '15:05:05.020' }, 670 { step: '0.02', value: '15:05:05.02', min: '00:00', result: true }, 671 { step: '0.02', value: '15:05:05.01', min: '00:00', result: false, 672 low: '15:05:05', high: '15:05:05.020' }, 673 { step: '0.002', value: '15:05:05.002', min: '00:00', result: true }, 674 { step: '0.002', value: '15:05:05.001', min: '00:00', result: false, 675 low: '15:05:05', high: '15:05:05.002' }, 676 // When step<=0.001, any value is allowed. 677 { step: '0.001', value: '15:05:05.001', min: '00:00', result: true }, 678 { step: '0.001', value: '15:05:05', min: '00:00', result: true }, 679 { step: '0.000001', value: '15:05:05', min: '00:00', result: true }, 680 // This value has conversion to double issues. 681 { step: '0.0000001', value: '15:05:05', min: '00:00', result: true }, 682 // Some random values. 683 { step: '100', value: '15:06:40', min: '00:00', result: true }, 684 { step: '100', value: '15:05:05.010', min: '00:00', result: false, 685 low: '15:05', high: '15:06:40' }, 686 { step: '3600', value: '15:00', min: '00:00', result: true }, 687 { step: '3600', value: '15:14', min: '00:00', result: false, 688 low: '15:00', high: '16:00' }, 689 { step: '7200', value: '14:00', min: '00:00', result: true }, 690 { step: '7200', value: '15:14', min: '00:00', result: false, 691 low: '14:00', high: '16:00' }, 692 { step: '7260', value: '14:07', min: '00:00', result: true }, 693 { step: '7260', value: '15:14', min: '00:00', result: false, 694 low: '14:07', high: '16:08' }, 695 ]; 696 697 var type = test.type; 698 for (var test of tests) { 699 var input = getFreshElement(type); 700 input.step = test.step; 701 input.setAttribute('value', test.value); 702 if (test.min !== undefined) { 703 input.min = test.min; 704 } 705 706 if (test.todo) { 707 todo(input.validity.valid, test.result, 708 "This test should fail for the moment because of precission issues"); 709 continue; 710 } 711 712 if (test.result) { 713 checkValidity(input, true, apply); 714 } else { 715 checkValidity(input, false, apply, 716 { low: test.low, high: test.high }); 717 } 718 } 719 720 break; 721 case 'month': 722 // When step is invalid, every date is valid 723 input.step = 0; 724 input.value = '2016-07'; 725 checkValidity(input, true, apply); 726 727 input.step = 'foo'; 728 input.value = '1970-01'; 729 checkValidity(input, true, apply); 730 731 input.step = '-1'; 732 input.value = '1970-01'; 733 checkValidity(input, true, apply); 734 735 input.removeAttribute('step'); 736 input.value = '1500-01'; 737 checkValidity(input, true, apply); 738 739 input.step = 'any'; 740 input.value = '1966-12'; 741 checkValidity(input, true, apply); 742 743 input.step = 'ANY'; 744 input.value = '2013-02'; 745 checkValidity(input, true, apply); 746 747 // When min is set to a valid month, there is a step base. 748 input.min = '2000-01'; 749 input.step = '2'; 750 input.value = '2000-03'; 751 checkValidity(input, true, apply); 752 753 input.value = '2000-02'; 754 checkValidity(input, false, apply, { low: "2000-01", high: "2000-03" }); 755 756 input.min = '2012-12'; 757 input.value = '2013-01'; 758 checkValidity(input, false, apply, { low: "2012-12", high: "2013-02" }); 759 760 input.min = '2010-10'; 761 input.value = '2010-11'; 762 checkValidity(input, false, apply, { low: "2010-10", high: "2010-12" }); 763 764 input.min = '2010-01'; 765 input.step = '1.1'; 766 input.value = '2010-02'; 767 checkValidity(input, true, apply); 768 769 input.min = '2010-05'; 770 input.step = '1.9'; 771 input.value = '2010-06'; 772 checkValidity(input, false, apply, { low: "2010-05", high: "2010-07" }); 773 774 // Without any step attribute the date is valid 775 input.removeAttribute('step'); 776 checkValidity(input, true, apply); 777 778 input.min = '1950-01'; 779 input.step = '13'; 780 input.value = '1951-01'; 781 checkValidity(input, false, apply, { low: "1950-01", high: "1951-02" }); 782 783 input.min = '1951-01'; 784 input.step = '12'; 785 input.value = '1952-01'; 786 checkValidity(input, true, apply); 787 788 input.step = '0.9'; 789 input.value = '1951-02'; 790 checkValidity(input, true, apply); 791 792 input.step = '1.5'; 793 input.value = '1951-04'; 794 checkValidity(input, false, apply, { low: "1951-03", high: "1951-05" }); 795 796 input.value = '1951-08'; 797 checkValidity(input, false, apply, { low: "1951-07", high: "1951-09" }); 798 799 input.step = '300'; 800 input.min= '1968-01'; 801 input.value = '1968-05'; 802 checkValidity(input, false, apply, { low: "1968-01", high: "1993-01" }); 803 804 input.value = '1971-01'; 805 checkValidity(input, false, apply, { low: "1968-01", high: "1993-01" }); 806 807 input.value = '1994-01'; 808 checkValidity(input, false, apply, { low: "1993-01", high: "2018-01" }); 809 810 input.value = '2018-01'; 811 checkValidity(input, true, apply); 812 813 input.value = '2043-01'; 814 checkValidity(input, true, apply); 815 816 input.step = '2.1'; 817 input.min = '1991-01'; 818 input.value = '1991-01'; 819 checkValidity(input, true, apply); 820 821 input.value = '1991-02'; 822 checkValidity(input, false, apply, { low: "1991-01", high: "1991-03" }); 823 824 input.value = '1991-03'; 825 checkValidity(input, true, apply); 826 827 input.step = '2.1'; 828 input.min = '1969-12'; 829 input.value = '1969-12'; 830 checkValidity(input, true, apply); 831 832 input.value = '1970-01'; 833 checkValidity(input, false, apply, { low: "1969-12", high: "1970-02" }); 834 835 input.value = '1970-02'; 836 checkValidity(input, true, apply); 837 838 break; 839 case 'week': 840 // When step is invalid, every week is valid 841 input.step = 0; 842 input.value = '2016-W30'; 843 checkValidity(input, true, apply); 844 845 input.step = 'foo'; 846 input.value = '1970-W01'; 847 checkValidity(input, true, apply); 848 849 input.step = '-1'; 850 input.value = '1970-W01'; 851 checkValidity(input, true, apply); 852 853 input.removeAttribute('step'); 854 input.value = '1500-W01'; 855 checkValidity(input, true, apply); 856 857 input.step = 'any'; 858 input.value = '1966-W52'; 859 checkValidity(input, true, apply); 860 861 input.step = 'ANY'; 862 input.value = '2013-W10'; 863 checkValidity(input, true, apply); 864 865 // When min is set to a valid week, there is a step base. 866 input.min = '2000-W01'; 867 input.step = '2'; 868 input.value = '2000-W03'; 869 checkValidity(input, true, apply); 870 871 input.value = '2000-W02'; 872 checkValidity(input, false, apply, { low: "2000-W01", high: "2000-W03" }); 873 874 input.min = '2012-W52'; 875 input.value = '2013-W01'; 876 checkValidity(input, false, apply, { low: "2012-W52", high: "2013-W02" }); 877 878 input.min = '2010-W01'; 879 input.step = '1.1'; 880 input.value = '2010-W02'; 881 checkValidity(input, true, apply); 882 883 input.min = '2010-W05'; 884 input.step = '1.9'; 885 input.value = '2010-W06'; 886 checkValidity(input, false, apply, { low: "2010-W05", high: "2010-W07" }); 887 888 // Without any step attribute the week is valid 889 input.removeAttribute('step'); 890 checkValidity(input, true, apply); 891 892 input.min = '1950-W01'; 893 input.step = '53'; 894 input.value = '1951-W01'; 895 checkValidity(input, false, apply, { low: "1950-W01", high: "1951-W02" }); 896 897 input.min = '1951-W01'; 898 input.step = '52'; 899 input.value = '1952-W01'; 900 checkValidity(input, true, apply); 901 902 input.step = '0.9'; 903 input.value = '1951-W02'; 904 checkValidity(input, true, apply); 905 906 input.step = '1.5'; 907 input.value = '1951-W04'; 908 checkValidity(input, false, apply, { low: "1951-W03", high: "1951-W05" }); 909 910 input.value = '1951-W20'; 911 checkValidity(input, false, apply, { low: "1951-W19", high: "1951-W21" }); 912 913 input.step = '300'; 914 input.min= '1968-W01'; 915 input.value = '1968-W05'; 916 checkValidity(input, false, apply, { low: "1968-W01", high: "1973-W40" }); 917 918 input.value = '1971-W01'; 919 checkValidity(input, false, apply, { low: "1968-W01", high: "1973-W40" }); 920 921 input.value = '1975-W01'; 922 checkValidity(input, false, apply, { low: "1973-W40", high: "1979-W27" }); 923 924 input.value = '1985-W14'; 925 checkValidity(input, true, apply); 926 927 input.step = '2.1'; 928 input.min = '1991-W01'; 929 input.value = '1991-W01'; 930 checkValidity(input, true, apply); 931 932 input.value = '1991-W02'; 933 checkValidity(input, false, apply, { low: "1991-W01", high: "1991-W03" }); 934 935 input.value = '1991-W03'; 936 checkValidity(input, true, apply); 937 938 input.step = '2.1'; 939 input.min = '1969-W52'; 940 input.value = '1969-W52'; 941 checkValidity(input, true, apply); 942 943 input.value = '1970-W01'; 944 checkValidity(input, false, apply, { low: "1969-W52", high: "1970-W02" }); 945 946 input.value = '1970-W02'; 947 checkValidity(input, true, apply); 948 949 break; 950 case 'datetime-local': 951 // When step is invalid, every datetime is valid 952 input.step = 0; 953 input.value = '2017-02-06T12:00'; 954 checkValidity(input, true, apply); 955 956 input.step = 'foo'; 957 input.value = '1970-01-01T00:00'; 958 checkValidity(input, true, apply); 959 960 input.step = '-1'; 961 input.value = '1969-12-12 00:10'; 962 checkValidity(input, true, apply); 963 964 input.removeAttribute('step'); 965 input.value = '1500-01-01T12:00'; 966 checkValidity(input, true, apply); 967 968 input.step = 'any'; 969 input.value = '1966-12-12T12:00'; 970 checkValidity(input, true, apply); 971 972 input.step = 'ANY'; 973 input.value = '2017-01-01 12:00'; 974 checkValidity(input, true, apply); 975 976 // When min is set to a valid datetime, there is a step base. 977 input.min = '2017-01-01T00:00:00'; 978 input.step = '2'; 979 input.value = '2017-01-01T00:00:02'; 980 checkValidity(input, true, apply); 981 982 input.value = '2017-01-01T00:00:03'; 983 checkValidity(input, false, apply, 984 { low: "2017-01-01T00:00:02", high: "2017-01-01T00:00:04" }); 985 986 input.min = '2017-01-01T00:00:05'; 987 input.value = '2017-01-01T00:00:08'; 988 checkValidity(input, false, apply, 989 { low: "2017-01-01T00:00:07", high: "2017-01-01T00:00:09" }); 990 991 input.min = '2000-01-01T00:00'; 992 input.step = '120'; 993 input.value = '2000-01-01T00:02'; 994 checkValidity(input, true, apply); 995 996 // Without any step attribute the datetime is valid 997 input.removeAttribute('step'); 998 checkValidity(input, true, apply); 999 1000 input.min = '1950-01-01T00:00'; 1001 input.step = '129600'; // 1.5 day 1002 input.value = '1950-01-02T00:00'; 1003 checkValidity(input, false, apply, 1004 { low: "1950-01-01T00:00", high: "1950-01-02T12:00" }); 1005 1006 input.step = '259200'; // 3 days 1007 input.value = '1950-01-04T12:00'; 1008 checkValidity(input, false, apply, 1009 { low: "1950-01-04T00:00", high: "1950-01-07T00:00" }); 1010 1011 input.value = '1950-01-10T00:00'; 1012 checkValidity(input, true, apply); 1013 1014 input.step = '0.5'; // half a second 1015 input.value = '1950-01-01T00:00:00.123'; 1016 checkValidity(input, false, apply, 1017 { low: "1950-01-01T00:00", high: "1950-01-01T00:00:00.500" }); 1018 1019 input.value = '2000-01-01T12:30:30.600'; 1020 checkValidity(input, false, apply, 1021 { low: "2000-01-01T12:30:30.500", high: "2000-01-01T12:30:31" }); 1022 1023 input.value = '1950-01-05T00:00:00.500'; 1024 checkValidity(input, true, apply); 1025 1026 input.step = '2.1'; 1027 input.min = '1991-01-01T12:00'; 1028 input.value = '1991-01-01T12:00'; 1029 checkValidity(input, true, apply); 1030 1031 input.value = '1991-01-01T12:00:03'; 1032 checkValidity(input, false, apply, 1033 { low: "1991-01-01T12:00:02.100", high: "1991-01-01T12:00:04.200" }); 1034 1035 input.value = '1991-01-01T12:00:06.3'; 1036 checkValidity(input, true, apply); 1037 1038 input.step = '2.1'; 1039 input.min = '1969-12-20T10:00:05'; 1040 input.value = '1969-12-20T10:00:05'; 1041 checkValidity(input, true, apply); 1042 1043 input.value = '1969-12-20T10:00:08'; 1044 checkValidity(input, false, apply, 1045 { low: "1969-12-20T10:00:07.100", high: "1969-12-20T10:00:09.200" }); 1046 1047 input.value = '1969-12-20T10:00:09.200'; 1048 checkValidity(input, true, apply); 1049 1050 break; 1051 default: 1052 ok(false, "Implement the tests for <input type='" + test.type + " >"); 1053 break; 1054 } 1055 } 1056 1057 </script> 1058 </pre> 1059 </body> 1060 </html>