tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_valueasnumber_attribute.html (27864B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <!--
      4 https://bugzilla.mozilla.org/show_bug.cgi?id=636737
      5 -->
      6 <head>
      7  <title>Test for Bug input.valueAsNumber</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=636737">Mozilla Bug 636737</a>
     13 <p id="display"></p>
     14 <pre id="test">
     15 <script type="application/javascript">
     16 
     17 /** Test for Bug 636737 */
     18 
     19 /**
     20 * This test is checking .valueAsNumber.
     21 */
     22 
     23 function checkAvailability()
     24 {
     25  var testData =
     26  [
     27    ["text", false],
     28    ["password", false],
     29    ["search", false],
     30    ["tel", false],
     31    ["email", false],
     32    ["url", false],
     33    ["hidden", false],
     34    ["checkbox", false],
     35    ["radio", false],
     36    ["file", false],
     37    ["submit", false],
     38    ["image", false],
     39    ["reset", false],
     40    ["button", false],
     41    ["number", true],
     42    ["range", true],
     43    ["date", true],
     44    ["time", true],
     45    ["color", false],
     46    ["month", true],
     47    ["week", true],
     48    ["datetime-local", true],
     49  ];
     50 
     51  var element = document.createElement('input');
     52 
     53  for (let data of testData) {
     54    var exceptionCatched = false;
     55    element.type = data[0];
     56    try {
     57      element.valueAsNumber;
     58    } catch (e) {
     59      exceptionCatched = true;
     60    }
     61    is(exceptionCatched, false,
     62       "valueAsNumber shouldn't throw exception on getting");
     63 
     64    exceptionCatched = false;
     65    try {
     66      element.valueAsNumber = 42;
     67    } catch (e) {
     68      exceptionCatched = true;
     69    }
     70    is(exceptionCatched, !data[1], "valueAsNumber for " + data[0] +
     71                                   " availability is not correct");
     72  }
     73 }
     74 
     75 function checkNumberGet()
     76 {
     77  var testData =
     78  [
     79    ["42", 42],
     80    ["-42", -42], // should work for negative values
     81    ["42.1234", 42.1234],
     82    ["123.123456789123", 123.123456789123], // double precision
     83    ["1e2", 100], // e should be usable
     84    ["2e1", 20],
     85    ["1e-1", 0.1], // value after e can be negative
     86    ["1E2", 100], // E can be used instead of e
     87    ["e", null],
     88    ["e2", null],
     89    ["1e0.1", null],
     90    ["", null], // the empty string is not a number
     91    ["foo", null],
     92    ["42,13", null], // comma can't be used as a decimal separator
     93  ];
     94 
     95  var element = document.createElement('input');
     96  element.type = "number";
     97  for (let data of testData) {
     98    element.value = data[0];
     99 
    100    // Given that NaN != NaN, we have to use null when the expected value is NaN.
    101    if (data[1] != null) {
    102      is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
    103         "floating point representation of the value");
    104    } else {
    105      ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN "  +
    106         "when the element value is not a number");
    107    }
    108  }
    109 }
    110 
    111 function checkNumberSet()
    112 {
    113  var testData =
    114  [
    115    [42, "42"],
    116    [-42, "-42"], // should work for negative values
    117    [42.1234, "42.1234"],
    118    [123.123456789123, "123.123456789123"], // double precision
    119    [1e2, "100"], // e should be usable
    120    [2e1, "20"],
    121    [1e-1, "0.1"], // value after e can be negative
    122    [1E2, "100"], // E can be used instead of e
    123    // Setting a string will set NaN.
    124    ["foo", ""],
    125    // "" is converted to 0.
    126    ["", "0"],
    127    [42, "42"], // Keep this here, it is used by the next test.
    128    // Setting Infinity should throw and not change the current value.
    129    [Infinity, "42", true],
    130    [-Infinity, "42", true],
    131    // Setting NaN should change the value to the empty string.
    132    [NaN, ""],
    133  ];
    134 
    135  var element = document.createElement('input');
    136  element.type = "number";
    137  for (let data of testData) {
    138    var caught = false;
    139    try {
    140      element.valueAsNumber = data[0];
    141      is(element.value, data[1],
    142         "valueAsNumber should be able to set the value");
    143    } catch (e) {
    144      caught = true;
    145    }
    146 
    147    if (data[2]) {
    148      ok(caught, "valueAsNumber should have thrown");
    149      is(element.value, data[1], "value should not have changed");
    150    } else {
    151      ok(!caught, "valueAsNumber should not have thrown");
    152    }
    153  }
    154 }
    155 
    156 function checkRangeGet()
    157 {
    158  // For type=range we should never get NaN since the user agent is required
    159  // to fix up the input's value to be something sensible.
    160 
    161  var min = -200;
    162  var max = 200;
    163  var defaultValue = min + (max - min)/2;
    164 
    165  var testData =
    166  [
    167    ["42", 42],
    168    ["-42", -42], // should work for negative values
    169    ["42.1234", 42.1234],
    170    ["123.123456789123", 123.123456789123], // double precision
    171    ["1e2", 100], // e should be usable
    172    ["2e1", 20],
    173    ["1e-1", 0.1], // value after e can be negative
    174    ["1E2", 100], // E can be used instead of e
    175    ["e", defaultValue],
    176    ["e2", defaultValue],
    177    ["1e0.1", defaultValue],
    178    ["", defaultValue],
    179    ["foo", defaultValue],
    180    ["42,13", defaultValue],
    181  ];
    182 
    183  var element = document.createElement('input');
    184  element.type = "range";
    185  element.setAttribute("min", min); // avoids out of range sanitization
    186  element.setAttribute("max", max);
    187  element.setAttribute("step", "any"); // avoids step mismatch sanitization
    188  for (let data of testData) {
    189    element.value = data[0];
    190 
    191    // Given that NaN != NaN, we have to use null when the expected value is NaN.
    192    is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
    193       "floating point representation of the value");
    194  }
    195 }
    196 
    197 function checkRangeSet()
    198 {
    199  var min = -200;
    200  var max = 200;
    201  var defaultValue = String(min + (max - min)/2);
    202 
    203  var testData =
    204  [
    205    [42, "42"],
    206    [-42, "-42"], // should work for negative values
    207    [42.1234, "42.1234"],
    208    [123.123456789123, "123.123456789123"], // double precision
    209    [1e2, "100"], // e should be usable
    210    [2e1, "20"],
    211    [1e-1, "0.1"], // value after e can be negative
    212    [1E2, "100"], // E can be used instead of e
    213    ["foo", defaultValue],
    214    ["", defaultValue],
    215    [42, "42"], // Keep this here, it is used by the next test.
    216    // Setting Infinity should throw and not change the current value.
    217    [Infinity, "42", true],
    218    [-Infinity, "42", true],
    219    // Setting NaN should change the value to the empty string.
    220    [NaN, defaultValue],
    221  ];
    222 
    223  var element = document.createElement('input');
    224  element.type = "range";
    225  element.setAttribute("min", min); // avoids out of range sanitization
    226  element.setAttribute("max", max);
    227  element.setAttribute("step", "any"); // avoids step mismatch sanitization
    228  for (let data of testData) {
    229    var caught = false;
    230    try {
    231      element.valueAsNumber = data[0];
    232      is(element.value, data[1],
    233         "valueAsNumber should be able to set the value");
    234    } catch (e) {
    235      caught = true;
    236    }
    237 
    238    if (data[2]) {
    239      ok(caught, "valueAsNumber should have thrown");
    240      is(element.value, data[1], "value should not have changed");
    241    } else {
    242      ok(!caught, "valueAsNumber should not have thrown");
    243    }
    244  }
    245 }
    246 
    247 function checkDateGet()
    248 {
    249  var validData =
    250  [
    251    [ "2012-07-12", 1342051200000 ],
    252    [ "1970-01-01", 0 ],
    253    // We are supposed to support at least until this date.
    254    // (corresponding to the date object maximal value)
    255    [ "275760-09-13", 8640000000000000 ],
    256    // Minimum valid date (limited by the input element minimum valid value)
    257    [ "0001-01-01", -62135596800000 ],
    258    [ "2012-02-29", 1330473600000 ],
    259    [ "2011-02-28", 1298851200000 ],
    260  ];
    261 
    262  var invalidData =
    263  [
    264    "invaliddate",
    265    "",
    266    "275760-09-14",
    267    "999-12-31",
    268    "-001-12-31",
    269    "0000-01-01",
    270    "2011-02-29",
    271    "1901-13-31",
    272    "1901-12-32",
    273    "1901-00-12",
    274    "1901-01-00",
    275    "1900-02-29",
    276  ];
    277 
    278  var element = document.createElement('input');
    279  element.type = "date";
    280  for (let data of validData) {
    281    element.value = data[0];
    282    is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
    283       "timestamp representing this date");
    284  }
    285 
    286  for (let data of invalidData) {
    287    element.value = data;
    288    ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN "  +
    289       "when the element value is not a valid date");
    290  }
    291 }
    292 
    293 function checkDateSet()
    294 {
    295  var testData =
    296  [
    297    [ 1342051200000,     "2012-07-12" ],
    298    [ 0,                 "1970-01-01" ],
    299    // Maximum valid date (limited by the ecma date object range).
    300    [ 8640000000000000,  "275760-09-13" ],
    301    // Minimum valid date (limited by the input element minimum valid value)
    302    [ -62135596800000,   "0001-01-01" ],
    303    [ 1330473600000,     "2012-02-29" ],
    304    [ 1298851200000,     "2011-02-28" ],
    305    // "Values must be truncated to valid dates"
    306    [ 42.1234,           "1970-01-01" ],
    307    [ 123.123456789123,  "1970-01-01" ],
    308    [ 1e2,               "1970-01-01" ],
    309    [ 1E9,               "1970-01-12" ],
    310    [ 1e-1,              "1970-01-01" ],
    311    [ 2e10,              "1970-08-20" ],
    312    [ 1298851200010,     "2011-02-28" ],
    313    [ -1,                "1969-12-31" ],
    314    [ -86400000,         "1969-12-31" ],
    315    [ 86400000,          "1970-01-02" ],
    316    // Invalid numbers.
    317    // Those are implicitly converted to numbers
    318    [ "",                "1970-01-01" ],
    319    [ true,              "1970-01-01" ],
    320    [ false,             "1970-01-01" ],
    321    [ null,              "1970-01-01" ],
    322    // Those are converted to NaN, the corresponding date string is the empty string
    323    [ "invaliddatenumber", "" ],
    324    [ NaN,               "" ],
    325    [ undefined,         "" ],
    326    // Out of range, the corresponding date string is the empty string
    327    [ -62135596800001,   "" ],
    328    // Infinity will keep the current value and throw (so we need to set a current value).
    329    [ 1298851200010, "2011-02-28" ],
    330    [ Infinity, "2011-02-28", true ],
    331    [ -Infinity, "2011-02-28", true ],
    332  ];
    333 
    334  var element = document.createElement('input');
    335  element.type = "date";
    336  for (let data of testData) {
    337    var caught = false;
    338 
    339    try {
    340      element.valueAsNumber = data[0];
    341      is(element.value, data[1], "valueAsNumber should set the value to " + data[1]);
    342    } catch(e) {
    343      caught = true;
    344    }
    345 
    346    if (data[2]) {
    347      ok(caught, "valueAsNumber should have thrown");
    348      is(element.value, data[1], "the value should not have changed");
    349    } else {
    350      ok(!caught, "valueAsNumber should not have thrown");
    351    }
    352  }
    353 
    354 }
    355 
    356 function checkTimeGet()
    357 {
    358  var tests = [
    359    // Some invalid values to begin.
    360    { value: "", result: NaN },
    361    { value: "foobar", result: NaN },
    362    { value: "00:", result: NaN },
    363    { value: "24:00", result: NaN },
    364    { value: "00:99", result: NaN },
    365    { value: "00:00:", result: NaN },
    366    { value: "00:00:99", result: NaN },
    367    { value: "00:00:00:", result: NaN },
    368    { value: "00:00:00.", result: NaN },
    369    { value: "00:00:00.0000", result: NaN },
    370    // Some simple valid values.
    371    { value: "00:00", result: 0 },
    372    { value: "00:01", result: 60000 },
    373    { value: "01:00", result: 3600000 },
    374    { value: "01:01", result: 3660000 },
    375    { value: "13:37", result: 49020000 },
    376    // Valid values including seconds.
    377    { value: "00:00:01", result: 1000 },
    378    { value: "13:37:42", result: 49062000 },
    379    // Valid values including seconds fractions.
    380    { value: "00:00:00.001", result: 1 },
    381    { value: "00:00:00.123", result: 123 },
    382    { value: "00:00:00.100", result: 100 },
    383    { value: "00:00:00.000", result: 0 },
    384    { value: "20:17:31.142", result: 73051142 },
    385    // Highest possible value.
    386    { value: "23:59:59.999", result: 86399999 },
    387    // Some values with one or two digits for the fraction of seconds.
    388    { value: "00:00:00.1", result: 100 },
    389    { value: "00:00:00.14", result: 140 },
    390    { value: "13:37:42.7", result: 49062700 },
    391    { value: "23:31:12.23", result: 84672230 },
    392  ];
    393 
    394  var element = document.createElement('input');
    395  element.type = 'time';
    396 
    397  for (let test of tests) {
    398    element.value = test.value;
    399    if (isNaN(test.result)) {
    400      ok(isNaN(element.valueAsNumber),
    401         "invalid value should have .valueAsNumber return NaN");
    402    } else {
    403      is(element.valueAsNumber, test.result,
    404         ".valueAsNumber should return " + test.result);
    405    }
    406  }
    407 }
    408 
    409 function checkTimeSet()
    410 {
    411  var tests = [
    412    // Some NaN values (should set to empty string).
    413    { value: NaN, result: "" },
    414    { value: "foobar", result: "" },
    415    { value() {}, result: "" },
    416    // Inifinity (should throw).
    417    { value: Infinity, throw: true },
    418    { value: -Infinity, throw: true },
    419    // "" converts to 0... JS is fun :)
    420    { value: "", result: "00:00" },
    421    // Simple tests.
    422    { value: 0, result: "00:00" },
    423    { value: 1, result: "00:00:00.001" },
    424    { value: 100, result: "00:00:00.100" },
    425    { value: 1000, result: "00:00:01" },
    426    { value: 60000, result: "00:01" },
    427    { value: 3600000, result: "01:00" },
    428    { value: 83622234, result: "23:13:42.234" },
    429    // Some edge cases.
    430    { value: 86400000, result: "00:00" },
    431    { value: 86400001, result: "00:00:00.001" },
    432    { value: 170022234, result: "23:13:42.234" },
    433    { value: 432000000, result: "00:00" },
    434    { value: -1, result: "23:59:59.999" },
    435    { value: -86400000, result: "00:00" },
    436    { value: -86400001, result: "23:59:59.999" },
    437    { value: -56789, result: "23:59:03.211" },
    438    { value: 0.9, result: "00:00" },
    439  ];
    440 
    441  var element = document.createElement('input');
    442  element.type = 'time';
    443 
    444  for (let test of tests) {
    445    try {
    446      var caught = false;
    447      element.valueAsNumber = test.value;
    448      is(element.value, test.result, "value should return " + test.result);
    449    } catch(e) {
    450      caught = true;
    451    }
    452 
    453    if (!test.throw) {
    454      test.throw = false;
    455    }
    456 
    457    is(caught, test.throw, "the test throwing status should be " + test.throw);
    458  }
    459 }
    460 
    461 function checkMonthGet()
    462 {
    463  var validData =
    464  [
    465    [ "2016-07", 558       ],
    466    [ "1970-01", 0         ],
    467    [ "1969-12", -1        ],
    468    [ "0001-01", -23628    ],
    469    [ "10000-12", 96371    ],
    470    [ "275760-09", 3285488 ],
    471  ];
    472 
    473  var invalidData =
    474  [
    475    "invalidmonth",
    476    "0000-01",
    477    "2000-00",
    478    "2012-13",
    479    // Out of range.
    480    "275760-10",
    481  ];
    482 
    483  var element = document.createElement('input');
    484  element.type = "month";
    485  for (let data of validData) {
    486    element.value = data[0];
    487    is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
    488       "integer value representing this month");
    489  }
    490 
    491  for (let data of invalidData) {
    492    element.value = data;
    493    ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN "  +
    494       "when the element value is not a valid month");
    495  }
    496 }
    497 
    498 function checkMonthSet()
    499 {
    500  var testData =
    501  [
    502    [ 558,               "2016-07"   ],
    503    [ 0,                 "1970-01"   ],
    504    [ -1,                "1969-12"   ],
    505    [ 96371,             "10000-12"  ],
    506    [ 12,                "1971-01"   ],
    507    [ -12,               "1969-01"   ],
    508    // Maximum valid month (limited by the ecma date object range)
    509    [ 3285488,           "275760-09" ],
    510    // Minimum valid month (limited by the input element minimum valid value)
    511    [ -23628,            "0001-01"   ],
    512    // "Values must be truncated to valid months"
    513    [ 0.3,               "1970-01"   ],
    514    [ -1.1,              "1969-11"   ],
    515    [ 1e2,               "1978-05"   ],
    516    [ 1e-1,              "1970-01"   ],
    517    // Invalid numbers.
    518    // Those are implicitly converted to numbers
    519    [ "",                "1970-01"   ],
    520    [ true,              "1970-02"   ],
    521    [ false,             "1970-01"   ],
    522    [ null,              "1970-01"   ],
    523    // Those are converted to NaN, the corresponding month string is the empty string
    524    [ "invalidmonth",    ""          ],
    525    [ NaN,               ""          ],
    526    [ undefined,         ""          ],
    527    // Out of range, the corresponding month string is the empty string
    528    [ -23629,            ""          ],
    529    [ 3285489,           ""          ],
    530    // Infinity will keep the current value and throw (so we need to set a current value)
    531    [ 558,               "2016-07"   ],
    532    [ Infinity,          "2016-07", true ],
    533    [ -Infinity,         "2016-07", true ],
    534  ];
    535 
    536  var element = document.createElement('input');
    537  element.type = "month";
    538  for (let data of testData) {
    539    var caught = false;
    540 
    541    try {
    542      element.valueAsNumber = data[0];
    543      is(element.value, data[1], "valueAsNumber should set the value to " + data[1]);
    544    } catch(e) {
    545      caught = true;
    546    }
    547 
    548    if (data[2]) {
    549      ok(caught, "valueAsNumber should have thrown");
    550      is(element.value, data[1], "the value should not have changed");
    551    } else {
    552      ok(!caught, "valueAsNumber should not have thrown");
    553    }
    554  }
    555 }
    556 
    557 function checkWeekGet()
    558 {
    559  var validData =
    560  [
    561    // Common years starting on different days of week.
    562    [ "2007-W01", Date.UTC(2007, 0, 1)   ], // Mon
    563    [ "2013-W01", Date.UTC(2012, 11, 31) ], // Tue
    564    [ "2014-W01", Date.UTC(2013, 11, 30) ], // Wed
    565    [ "2015-W01", Date.UTC(2014, 11, 29) ], // Thu
    566    [ "2010-W01", Date.UTC(2010, 0, 4)   ], // Fri
    567    [ "2011-W01", Date.UTC(2011, 0, 3)   ], // Sat
    568    [ "2017-W01", Date.UTC(2017, 0, 2)   ], // Sun
    569    // Common years ending on different days of week.
    570    [ "2007-W52", Date.UTC(2007, 11, 24) ], // Mon
    571    [ "2013-W52", Date.UTC(2013, 11, 23) ], // Tue
    572    [ "2014-W52", Date.UTC(2014, 11, 22) ], // Wed
    573    [ "2015-W53", Date.UTC(2015, 11, 28) ], // Thu
    574    [ "2010-W52", Date.UTC(2010, 11, 27) ], // Fri
    575    [ "2011-W52", Date.UTC(2011, 11, 26) ], // Sat
    576    [ "2017-W52", Date.UTC(2017, 11, 25) ], // Sun
    577    // Leap years starting on different days of week.
    578    [ "1996-W01", Date.UTC(1996, 0, 1)   ], // Mon
    579    [ "2008-W01", Date.UTC(2007, 11, 31) ], // Tue
    580    [ "2020-W01", Date.UTC(2019, 11, 30) ], // Wed
    581    [ "2004-W01", Date.UTC(2003, 11, 29) ], // Thu
    582    [ "2016-W01", Date.UTC(2016, 0, 4)   ], // Fri
    583    [ "2000-W01", Date.UTC(2000, 0, 3)   ], // Sat
    584    [ "2012-W01", Date.UTC(2012, 0, 2)   ], // Sun
    585    // Leap years ending on different days of week.
    586    [ "2012-W52", Date.UTC(2012, 11, 24) ], // Mon
    587    [ "2024-W52", Date.UTC(2024, 11, 23) ], // Tue
    588    [ "1980-W52", Date.UTC(1980, 11, 22) ], // Wed
    589    [ "1992-W53", Date.UTC(1992, 11, 28) ], // Thu
    590    [ "2004-W53", Date.UTC(2004, 11, 27) ], // Fri
    591    [ "1988-W52", Date.UTC(1988, 11, 26) ], // Sat
    592    [ "2000-W52", Date.UTC(2000, 11, 25) ], // Sun
    593    // Other normal cases.
    594    [ "2015-W53", Date.UTC(2015, 11, 28)   ],
    595    [ "2016-W36", Date.UTC(2016, 8, 5)     ],
    596    [ "1970-W01", Date.UTC(1969, 11, 29)   ],
    597    [ "275760-W37", Date.UTC(275760, 8, 8) ],
    598  ];
    599 
    600  var invalidData =
    601  [
    602    "invalidweek",
    603    "0000-W01",
    604    "2016-W00",
    605    "2016-W53",
    606    // Out of range.
    607    "275760-W38",
    608  ];
    609 
    610  var element = document.createElement('input');
    611  element.type = "week";
    612  for (let data of validData) {
    613    element.value = data[0];
    614    is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
    615       "integer value representing this week");
    616  }
    617 
    618  for (let data of invalidData) {
    619    element.value = data;
    620    ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN "  +
    621       "when the element value is not a valid week");
    622  }
    623 }
    624 
    625 function checkWeekSet()
    626 {
    627  var testData =
    628  [
    629    // Common years starting on different days of week.
    630    [ Date.UTC(2007, 0, 1), "2007-W01"   ], // Mon
    631    [ Date.UTC(2013, 0, 1), "2013-W01"   ], // Tue
    632    [ Date.UTC(2014, 0, 1), "2014-W01"   ], // Wed
    633    [ Date.UTC(2015, 0, 1), "2015-W01"   ], // Thu
    634    [ Date.UTC(2010, 0, 1), "2009-W53"   ], // Fri
    635    [ Date.UTC(2011, 0, 1), "2010-W52"   ], // Sat
    636    [ Date.UTC(2017, 0, 1), "2016-W52"   ], // Sun
    637    // Common years ending on different days of week.
    638    [ Date.UTC(2007, 11, 31), "2008-W01" ], // Mon
    639    [ Date.UTC(2013, 11, 31), "2014-W01" ], // Tue
    640    [ Date.UTC(2014, 11, 31), "2015-W01" ], // Wed
    641    [ Date.UTC(2015, 11, 31), "2015-W53" ], // Thu
    642    [ Date.UTC(2010, 11, 31), "2010-W52" ], // Fri
    643    [ Date.UTC(2011, 11, 31), "2011-W52" ], // Sat
    644    [ Date.UTC(2017, 11, 31), "2017-W52" ], // Sun
    645    // Leap years starting on different days of week.
    646    [ Date.UTC(1996, 0, 1), "1996-W01"   ], // Mon
    647    [ Date.UTC(2008, 0, 1), "2008-W01"   ], // Tue
    648    [ Date.UTC(2020, 0, 1), "2020-W01"   ], // Wed
    649    [ Date.UTC(2004, 0, 1), "2004-W01"   ], // Thu
    650    [ Date.UTC(2016, 0, 1), "2015-W53"   ], // Fri
    651    [ Date.UTC(2000, 0, 1), "1999-W52"   ], // Sat
    652    [ Date.UTC(2012, 0, 1), "2011-W52"   ], // Sun
    653    // Leap years ending on different days of week.
    654    [ Date.UTC(2012, 11, 31), "2013-W01" ], // Mon
    655    [ Date.UTC(2024, 11, 31), "2025-W01" ], // Tue
    656    [ Date.UTC(1980, 11, 31), "1981-W01" ], // Wed
    657    [ Date.UTC(1992, 11, 31), "1992-W53" ], // Thu
    658    [ Date.UTC(2004, 11, 31), "2004-W53" ], // Fri
    659    [ Date.UTC(1988, 11, 31), "1988-W52" ], // Sat
    660    [ Date.UTC(2000, 11, 31), "2000-W52" ], // Sun
    661    // Other normal cases.
    662    [ Date.UTC(2008, 8, 26),  "2008-W39" ],
    663    [ Date.UTC(2016, 0, 4),   "2016-W01" ],
    664    [ Date.UTC(2016, 0, 10),  "2016-W01" ],
    665    [ Date.UTC(2016, 0, 11),  "2016-W02" ],
    666    // Maximum valid week (limited by the ecma date object range).
    667    [ 8640000000000000,  "275760-W37" ],
    668    // Minimum valid week (limited by the input element minimum valid value)
    669    [ -62135596800000,   "0001-W01" ],
    670    // "Values must be truncated to valid weeks"
    671    [ 0.3,               "1970-W01"  ],
    672    [ 1e-1,              "1970-W01"  ],
    673    [ -1.1,              "1970-W01"  ],
    674    [ -345600000,        "1969-W52"  ],
    675    // Invalid numbers.
    676    // Those are implicitly converted to numbers
    677    [ "",                "1970-W01" ],
    678    [ true,              "1970-W01" ],
    679    [ false,             "1970-W01" ],
    680    [ null,              "1970-W01" ],
    681    // Those are converted to NaN, the corresponding week string is the empty string
    682    [ "invalidweek",     "" ],
    683    [ NaN,               "" ],
    684    [ undefined,         "" ],
    685    // Infinity will keep the current value and throw (so we need to set a current value).
    686    [ Date.UTC(2016, 8, 8), "2016-W36" ],
    687    [ Infinity,             "2016-W36", true ],
    688    [ -Infinity,            "2016-W36", true ],
    689  ];
    690 
    691  var element = document.createElement('input');
    692  element.type = "week";
    693  for (let data of testData) {
    694    var caught = false;
    695 
    696    try {
    697      element.valueAsNumber = data[0];
    698      is(element.value, data[1], "valueAsNumber should set the value to " +
    699                                 data[1]);
    700    } catch(e) {
    701      caught = true;
    702    }
    703 
    704    if (data[2]) {
    705      ok(caught, "valueAsNumber should have thrown");
    706      is(element.value, data[1], "the value should not have changed");
    707    } else {
    708      ok(!caught, "valueAsNumber should not have thrown");
    709    }
    710  }
    711 }
    712 
    713 function checkDatetimeLocalGet() {
    714  var validData =
    715  [
    716    // Simple cases.
    717    [ "2016-12-20T09:58",          Date.UTC(2016, 11, 20, 9, 58)          ],
    718    [ "2016-12-20T09:58:30",       Date.UTC(2016, 11, 20, 9, 58, 30)      ],
    719    [ "2016-12-20T09:58:30.123",   Date.UTC(2016, 11, 20, 9, 58, 30, 123) ],
    720    [ "2017-01-01T10:00",          Date.UTC(2017, 0, 1, 10, 0, 0)         ],
    721    [ "1969-12-31T12:00:00",       Date.UTC(1969, 11, 31, 12, 0, 0)       ],
    722    [ "1970-01-01T00:00",          0                                      ],
    723    // Leap years.
    724    [ "1804-02-29 12:34",          Date.UTC(1804, 1, 29, 12, 34, 0)       ],
    725    [ "2016-02-29T12:34",          Date.UTC(2016, 1, 29, 12, 34, 0)       ],
    726    [ "2016-12-31T12:34:56",       Date.UTC(2016, 11, 31, 12, 34, 56)     ],
    727    [ "2016-01-01T12:34:56.789",   Date.UTC(2016, 0, 1, 12, 34, 56, 789)  ],
    728    [ "2017-01-01 12:34:56.789",   Date.UTC(2017, 0, 1, 12, 34, 56, 789)  ],
    729    // Maximum valid datetime-local (limited by the ecma date object range).
    730    [ "275760-09-13T00:00",        8640000000000000                       ],
    731    // Minimum valid datetime-local (limited by the input element minimum valid value).
    732    [ "0001-01-01T00:00",          -62135596800000                        ],
    733  ];
    734 
    735  var invalidData =
    736  [
    737    "invaliddatetime-local",
    738    "0000-01-01T00:00",
    739    "2016-12-25T00:00Z",
    740    "2015-02-29T12:34",
    741    "1-1-1T12:00",
    742    // Out of range.
    743    "275760-09-13T12:00",
    744  ];
    745 
    746  var element = document.createElement('input');
    747  element.type = "datetime-local";
    748  for (let data of validData) {
    749    element.value = data[0];
    750    is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
    751       "integer value representing this datetime-local");
    752  }
    753 
    754  for (let data of invalidData) {
    755    element.value = data;
    756    ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN "  +
    757       "when the element value is not a valid datetime-local");
    758  }
    759 }
    760 
    761 function checkDatetimeLocalSet()
    762 {
    763  var testData =
    764  [
    765    // Simple cases.
    766    [ Date.UTC(2016, 11, 20, 9, 58, 0),       "2016-12-20T09:58",       ],
    767    [ Date.UTC(2016, 11, 20, 9, 58, 30),      "2016-12-20T09:58:30"     ],
    768    [ Date.UTC(2016, 11, 20, 9, 58, 30, 123), "2016-12-20T09:58:30.123" ],
    769    [ Date.UTC(2017, 0, 1, 10, 0, 0),         "2017-01-01T10:00"        ],
    770    [ Date.UTC(1969, 11, 31, 12, 0, 0),       "1969-12-31T12:00"        ],
    771    [ 0,                                      "1970-01-01T00:00"        ],
    772    // Maximum valid week (limited by the ecma date object range).
    773    [ 8640000000000000,  "275760-09-13T00:00"      ],
    774    // Minimum valid datetime-local (limited by the input element minimum valid value).
    775    [ -62135596800000,   "0001-01-01T00:00"        ],
    776    // Leap years.
    777    [ Date.UTC(1804, 1, 29, 12, 34, 0),       "1804-02-29T12:34"        ],
    778    [ Date.UTC(2016, 1, 29, 12, 34, 0),       "2016-02-29T12:34"        ],
    779    [ Date.UTC(2016, 11, 31, 12, 34, 56),     "2016-12-31T12:34:56"     ],
    780    [ Date.UTC(2016, 0, 1, 12, 34, 56, 789),  "2016-01-01T12:34:56.789" ],
    781    [ Date.UTC(2017, 0, 1, 12, 34, 56, 789),  "2017-01-01T12:34:56.789" ],
    782    // "Values must be truncated to valid datetime-local"
    783    [ 0.3,               "1970-01-01T00:00"        ],
    784    [ 1e-1,              "1970-01-01T00:00"        ],
    785    [ -1  ,              "1969-12-31T23:59:59.999" ],
    786    [ -345600000,        "1969-12-28T00:00"        ],
    787    // Invalid numbers.
    788    // Those are implicitly converted to numbers
    789    [ "",                "1970-01-01T00:00"        ],
    790    [ true,              "1970-01-01T00:00:00.001" ],
    791    [ false,             "1970-01-01T00:00"        ],
    792    [ null,              "1970-01-01T00:00"        ],
    793    // Those are converted to NaN, the corresponding week string is the empty string
    794    [ "invaliddatetime-local", "" ],
    795    [ NaN,                     "" ],
    796    [ undefined,               "" ],
    797    // Infinity will keep the current value and throw (so we need to set a current value).
    798    [ Date.UTC(2016, 11, 27, 15, 10, 0), "2016-12-27T15:10"       ],
    799    [ Infinity,                          "2016-12-27T15:10", true ],
    800    [ -Infinity,                         "2016-12-27T15:10", true ],
    801  ];
    802 
    803  var element = document.createElement('input');
    804  element.type = "datetime-local";
    805  for (let data of testData) {
    806    var caught = false;
    807 
    808    try {
    809      element.valueAsNumber = data[0];
    810      is(element.value, data[1], "valueAsNumber should set the value to " +
    811                                 data[1]);
    812    } catch(e) {
    813      caught = true;
    814    }
    815 
    816    if (data[2]) {
    817      ok(caught, "valueAsNumber should have thrown");
    818      is(element.value, data[1], "the value should not have changed");
    819    } else {
    820      ok(!caught, "valueAsNumber should not have thrown");
    821    }
    822  }
    823 }
    824 
    825 checkAvailability();
    826 
    827 // <input type='number'> test
    828 checkNumberGet();
    829 checkNumberSet();
    830 
    831 // <input type='range'> test
    832 checkRangeGet();
    833 checkRangeSet();
    834 
    835 // <input type='date'> test
    836 checkDateGet();
    837 checkDateSet();
    838 
    839 // <input type='time'> test
    840 checkTimeGet();
    841 checkTimeSet();
    842 
    843 // <input type='month'> test
    844 checkMonthGet();
    845 checkMonthSet();
    846 
    847 // <input type='week'> test
    848 checkWeekGet();
    849 checkWeekSet();
    850 
    851 // <input type='datetime-local'> test
    852 checkDatetimeLocalGet();
    853 checkDatetimeLocalSet();
    854 
    855 </script>
    856 </pre>
    857 </body>
    858 </html>