tor-browser

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

test_observablearray.html (17847B)


      1 <!-- Any copyright is dedicated to the Public Domain.
      2 - http://creativecommons.org/publicdomain/zero/1.0/ -->
      3 <!DOCTYPE HTML>
      4 <html>
      5 <head>
      6 <title>Test Observable Array Type</title>
      7 <script src="/tests/SimpleTest/SimpleTest.js"></script>
      8 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      9 </head>
     10 <body>
     11 <script>
     12 /* global TestInterfaceObservableArray */
     13 
     14 add_task(async function init() {
     15  await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]});
     16 });
     17 
     18 add_task(function testObservableArray_length() {
     19  let setCallbackCount = 0;
     20  let deleteCallbackCount = 0;
     21  let deleteCallbackTests = null;
     22 
     23  let m = new TestInterfaceObservableArray({
     24    setBooleanCallback() {
     25      setCallbackCount++;
     26    },
     27    deleteBooleanCallback(value, index) {
     28      deleteCallbackCount++;
     29      if (typeof deleteCallbackTests === 'function') {
     30        deleteCallbackTests(value, index);
     31      }
     32    },
     33  });
     34  m.observableArrayBoolean = [true, true, true, true, true];
     35 
     36  let b = m.observableArrayBoolean;
     37  ok(Array.isArray(b), "observable array should be an array type");
     38  is(b.length, 5, "length of observable array should be 5");
     39 
     40  [
     41    // [length, shouldThrow, expectedResult]
     42    ["invalid", true, false],
     43    [b.length + 1, false, false],
     44    [b.length, false, true],
     45    [b.length - 1, false, true],
     46    [0, false, true],
     47  ].forEach(function([length, shouldThrow, expectedResult]) {
     48    // Initialize
     49    let oldValues = b.slice();
     50    let oldLen = b.length;
     51    let shouldSuccess = !shouldThrow && expectedResult;
     52    setCallbackCount = 0;
     53    deleteCallbackCount = 0;
     54    deleteCallbackTests = null;
     55    if (shouldSuccess) {
     56      let deleteCallbackIndex = b.length - 1;
     57      deleteCallbackTests = function(_value, _index) {
     58        info(`delete callback for ${_index}`);
     59        is(_value, oldValues[deleteCallbackIndex], "deleteCallbackTests: test value argument");
     60        is(_index, deleteCallbackIndex, "deleteCallbackTests: test index argument");
     61        deleteCallbackIndex--;
     62      };
     63    }
     64 
     65    // Test
     66    info(`setting length to ${length}`);
     67    try {
     68      b.length = length;
     69      ok(!shouldThrow, `setting length should throw`);
     70    } catch(e) {
     71      ok(shouldThrow, `setting length throws ${e}`);
     72    }
     73    is(setCallbackCount, 0, "setCallback should not be called");
     74    is(deleteCallbackCount, shouldSuccess ? (oldLen - length) : 0, "deleteCallback count");
     75    isDeeply(b, shouldSuccess ? oldValues.slice(0, length) : oldValues, "property values");
     76    is(b.length, shouldSuccess ? length : oldLen, `length of observable array`);
     77  });
     78 });
     79 
     80 add_task(function testObservableArray_length_callback_throw() {
     81  let setCallbackCount = 0;
     82  let deleteCallbackCount = 0;
     83 
     84  let m = new TestInterfaceObservableArray({
     85    setBooleanCallback() {
     86      setCallbackCount++;
     87    },
     88    deleteBooleanCallback(value) {
     89      deleteCallbackCount++;
     90      if (value) {
     91        throw new Error("deleteBooleanCallback");
     92      }
     93    },
     94  });
     95  m.observableArrayBoolean = [true, true, false, false, false];
     96 
     97  let b = m.observableArrayBoolean;
     98  ok(Array.isArray(b), "observable array should be an array type");
     99  is(b.length, 5, "length of observable array should be 5");
    100 
    101  // Initialize
    102  setCallbackCount = 0;
    103  deleteCallbackCount = 0;
    104 
    105  // Test
    106  info(`setting length to 0`);
    107  try {
    108    b.length = 0;
    109    ok(false, `setting length should throw`);
    110  } catch(e) {
    111    ok(true, `setting length throws ${e}`);
    112  }
    113  is(setCallbackCount, 0, "setCallback should not be called");
    114  is(deleteCallbackCount, 4, "deleteCallback should be called");
    115  isDeeply(b, [true, true], "property values");
    116  is(b.length, 2, `length of observable array`);
    117 });
    118 
    119 add_task(function testObservableArray_setter() {
    120  let setCallbackCount = 0;
    121  let deleteCallbackCount = 0;
    122  let setCallbackTests = null;
    123  let deleteCallbackTests = null;
    124 
    125  let m = new TestInterfaceObservableArray({
    126    setBooleanCallback(value, index) {
    127      setCallbackCount++;
    128      if (typeof setCallbackTests === 'function') {
    129        setCallbackTests(value, index);
    130      }
    131    },
    132    deleteBooleanCallback(value, index) {
    133      deleteCallbackCount++;
    134      if (typeof deleteCallbackTests === 'function') {
    135        deleteCallbackTests(value, index);
    136      }
    137    },
    138  });
    139 
    140  let b = m.observableArrayBoolean;
    141  ok(Array.isArray(b), "observable array should be an array type");
    142  is(b.length, 0, "length of observable array should be 0");
    143 
    144  [
    145    // [values, shouldThrow]
    146    ["invalid", true],
    147    [[1,[],{},"invalid"], false],
    148    [[0,NaN,null,undefined,""], false],
    149    [[true,true], false],
    150    [[false,false,false], false],
    151  ].forEach(function([values, shouldThrow]) {
    152    // Initialize
    153    let oldValues = b.slice();
    154    let oldLen = b.length;
    155    setCallbackCount = 0;
    156    deleteCallbackCount = 0;
    157    setCallbackTests = null;
    158    deleteCallbackTests = null;
    159    if (!shouldThrow) {
    160      let setCallbackIndex = 0;
    161      setCallbackTests = function(_value, _index) {
    162        info(`set callback for ${_index}`);
    163        is(_value, !!values[setCallbackIndex], "setCallbackTests: test value argument");
    164        is(_index, setCallbackIndex, "setCallbackTests: test index argument");
    165        setCallbackIndex++;
    166      };
    167 
    168      let deleteCallbackIndex = b.length - 1;
    169      deleteCallbackTests = function(_value, _index) {
    170        info(`delete callback for ${_index}`);
    171        is(_value, oldValues[deleteCallbackIndex], "deleteCallbackTests: test value argument");
    172        is(_index, deleteCallbackIndex, "deleteCallbackTests: test index argument");
    173        deleteCallbackIndex--;
    174      };
    175    }
    176 
    177    // Test
    178    info(`setting value to ${JSON.stringify(values)}`);
    179    try {
    180      m.observableArrayBoolean = values;
    181      ok(!shouldThrow, `setting value should not throw`);
    182    } catch(e) {
    183      ok(shouldThrow, `setting value throws ${e}`);
    184    }
    185    is(setCallbackCount, shouldThrow ? 0 : values.length, "setCallback count");
    186    is(deleteCallbackCount, oldLen, "deleteCallback should be called");
    187    isDeeply(b, shouldThrow ? [] : values.map(v => !!v), "property values");
    188    is(b.length, shouldThrow ? 0 : values.length, `length of observable array`);
    189  });
    190 });
    191 
    192 add_task(function testObservableArray_setter_invalid_item() {
    193  let setCallbackCount = 0;
    194  let deleteCallbackCount = 0;
    195  let setCallbackTests = null;
    196  let deleteCallbackTests = null;
    197 
    198  let m = new TestInterfaceObservableArray({
    199    setInterfaceCallback(value, index) {
    200      setCallbackCount++;
    201      if (typeof setCallbackTests === 'function') {
    202        setCallbackTests(value, index);
    203      }
    204    },
    205    deleteInterfaceCallback(value, index) {
    206      deleteCallbackCount++;
    207      if (typeof deleteCallbackTests === 'function') {
    208        deleteCallbackTests(value, index);
    209      }
    210    },
    211  });
    212 
    213  let b = m.observableArrayInterface;
    214  ok(Array.isArray(b), "observable array should be an array type");
    215  is(b.length, 0, "length of observable array should be 0");
    216 
    217  [
    218    // [values, shouldThrow]
    219    [[m,m,m,m], false],
    220    [["invalid"], true],
    221    [[m,m], false],
    222    [[m,"invalid"], true],
    223    [[m,m,m], false],
    224  ].forEach(function([values, shouldThrow]) {
    225    // Initialize
    226    let oldValues = b.slice();
    227    let oldLen = b.length;
    228    let setCallbackIndex = 0;
    229    setCallbackTests = function(_value, _index) {
    230      info(`set callback for ${_index}`);
    231      is(_value, values[setCallbackIndex], "setCallbackTests: test value argument");
    232      is(_index, setCallbackIndex, "setCallbackTests: test index argument");
    233      setCallbackIndex++;
    234    };
    235    let deleteCallbackIndex = b.length - 1;
    236    deleteCallbackTests = function(_value, _index) {
    237      info(`delete callback for ${_index}`);
    238      is(_value, oldValues[deleteCallbackIndex], "deleteCallbackTests: test value argument");
    239      is(_index, deleteCallbackIndex, "deleteCallbackTests: test index argument");
    240      deleteCallbackIndex--;
    241    };
    242    setCallbackCount = 0;
    243    deleteCallbackCount = 0;
    244 
    245    // Test
    246    info(`setting value to ${values}`);
    247    try {
    248      m.observableArrayInterface = values;
    249      ok(!shouldThrow, `setting value should not throw`);
    250    } catch(e) {
    251      ok(shouldThrow, `setting value throws ${e}`);
    252    }
    253    is(setCallbackCount, shouldThrow ? 0 : values.length, "setCallback count");
    254    is(deleteCallbackCount, shouldThrow ? 0 : oldLen, "deleteCallback should be called");
    255    isDeeply(b, shouldThrow ? oldValues : values, "property values");
    256    is(b.length, shouldThrow ? oldLen : values.length, `length of observable array`);
    257  });
    258 });
    259 
    260 add_task(function testObservableArray_setter_callback_throw() {
    261  let setCallbackCount = 0;
    262  let deleteCallbackCount = 0;
    263 
    264  let m = new TestInterfaceObservableArray({
    265    setBooleanCallback(value, index) {
    266      setCallbackCount++;
    267      if (index >= 3) {
    268        throw new Error("setBooleanCallback");
    269      }
    270    },
    271    deleteBooleanCallback(value) {
    272      deleteCallbackCount++;
    273      if (value) {
    274        throw new Error("deleteBooleanCallback");
    275      }
    276    },
    277  });
    278  m.observableArrayBoolean = [false, false, false];
    279 
    280  let b = m.observableArrayBoolean;
    281  ok(Array.isArray(b), "observable array should be an array type");
    282  is(b.length, 3, "length of observable array should be 3");
    283 
    284  [
    285    // [values, shouldThrow, expectedLength, expectedSetCbCount, expectedDeleteCbCount]
    286    [[false,false], false, 2, 2, 3],
    287    [[false,true,false,false], true, 3, 4, 2],
    288    [[false,false,true], true, 2, 0, 2],
    289  ].forEach(function([values, shouldThrow, expectedLength, expectedSetCbCount,
    290                      expectedDeleteCbCount]) {
    291    // Initialize
    292    setCallbackCount = 0;
    293    deleteCallbackCount = 0;
    294 
    295    // Test
    296    info(`setting value to ${values}`);
    297    try {
    298      m.observableArrayBoolean = values;
    299      ok(!shouldThrow, `setting value should not throw`);
    300    } catch(e) {
    301      ok(shouldThrow, `setting length throws ${e}`);
    302    }
    303    is(setCallbackCount, expectedSetCbCount, "setCallback should be called");
    304    is(deleteCallbackCount, expectedDeleteCbCount, "deleteCallback should be called");
    305    is(b.length, expectedLength, `length of observable array`);
    306  });
    307 });
    308 
    309 add_task(function testObservableArray_indexed_setter() {
    310  let setCallbackCount = 0;
    311  let deleteCallbackCount = 0;
    312  let setCallbackTests = null;
    313  let deleteCallbackTests = null;
    314 
    315  let m = new TestInterfaceObservableArray({
    316    setBooleanCallback(value, index) {
    317      setCallbackCount++;
    318      if (typeof setCallbackTests === 'function') {
    319        setCallbackTests(value, index);
    320      }
    321    },
    322    deleteBooleanCallback(value, index) {
    323      deleteCallbackCount++;
    324      if (typeof deleteCallbackTests === 'function') {
    325        deleteCallbackTests(value, index);
    326      }
    327    },
    328  });
    329 
    330  let b = m.observableArrayBoolean;
    331  ok(Array.isArray(b), "observable array should be an array type");
    332  is(b.length, 0, "length of observable array should be 0");
    333 
    334  [
    335    // [index, value, expectedResult]
    336    [b.length + 1, false, false],
    337    [b.length, false, true],
    338    [b.length + 1, false, true],
    339    [b.length + 1, true, true],
    340  ].forEach(function([index, value, expectedResult]) {
    341    // Initialize
    342    let oldValue = b[index];
    343    let oldLen = b.length;
    344    setCallbackCount = 0;
    345    deleteCallbackCount = 0;
    346    setCallbackTests = function(_value, _index) {
    347      info(`set callback for ${_index}`);
    348      is(_value, value, "setCallbackTests: test value argument");
    349      is(_index, index, "setCallbackTests: test index argument");
    350    };
    351    deleteCallbackTests = function(_value, _index) {
    352      info(`delete callback for ${_index}`);
    353      is(_value, oldValue, "deleteCallbackTests: test value argument");
    354      is(_index, index, "deleteCallbackTests: test index argument");
    355    };
    356 
    357    // Test
    358    info(`setting value of property ${index} to ${value}`);
    359    try {
    360      b[index] = value;
    361      ok(true, `setting value should not throw`);
    362    } catch(e) {
    363      ok(false, `setting value throws ${e}`);
    364    }
    365    is(setCallbackCount, expectedResult ? 1 : 0, "setCallback should be called");
    366    is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback should be called");
    367    is(b[index], expectedResult ? value : oldValue, `property value`);
    368    is(b.length, expectedResult ? Math.max(oldLen, index + 1) : oldLen, `length of observable array`);
    369  });
    370 });
    371 
    372 add_task(function testObservableArray_indexed_setter_invalid() {
    373  let setCallbackCount = 0;
    374  let deleteCallbackCount = 0;
    375  let setCallbackTests = null;
    376  let deleteCallbackTests = null;
    377 
    378  let m = new TestInterfaceObservableArray({
    379    setInterfaceCallback(value, index) {
    380      setCallbackCount++;
    381      if (typeof setCallbackTests === 'function') {
    382        setCallbackTests(value, index);
    383      }
    384    },
    385    deleteInterfaceCallback(value, index) {
    386      deleteCallbackCount++;
    387      if (typeof deleteCallbackTests === 'function') {
    388        deleteCallbackTests(value, index);
    389      }
    390    },
    391  });
    392 
    393  let b = m.observableArrayInterface;
    394  ok(Array.isArray(b), "observable array should be an array type");
    395  is(b.length, 0, "length of observable array should be 0");
    396 
    397  [
    398    // [index, value, shouldThrow]
    399    [b.length, "invalid", true],
    400    [b.length, m, false],
    401    [b.length + 1, m, false],
    402    [b.length + 1, "invalid", true],
    403  ].forEach(function([index, value, shouldThrow]) {
    404    // Initialize
    405    let oldValue = b[index];
    406    let oldLen = b.length;
    407    setCallbackCount = 0;
    408    deleteCallbackCount = 0;
    409    setCallbackTests = function(_value, _index) {
    410      info(`set callback for ${_index}`);
    411      is(_value, value, "setCallbackTests: test value argument");
    412      is(_index, index, "setCallbackTests: test index argument");
    413    };
    414    deleteCallbackTests = function(_value, _index) {
    415      info(`delete callback for ${_index}`);
    416      is(_value, oldValue, "deleteCallbackTests: test value argument");
    417      is(_index, index, "deleteCallbackTests: test index argument");
    418    };
    419 
    420    // Test
    421    info(`setting value of property ${index} to ${value}`);
    422    try {
    423      b[index] = value;
    424      ok(!shouldThrow, `setting value should not throw`);
    425    } catch(e) {
    426      ok(shouldThrow, `setting value throws ${e}`);
    427    }
    428    is(setCallbackCount, shouldThrow ? 0 : 1, "setCallback count");
    429    is(deleteCallbackCount, ((oldLen > index) && !shouldThrow) ? 1 : 0, "deleteCallback count");
    430    is(b[index], shouldThrow ? oldValue : value, `property value`);
    431    is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), `length of observable array`);
    432  });
    433 });
    434 
    435 add_task(function testObservableArray_indexed_setter_callback_throw() {
    436  let setCallbackCount = 0;
    437  let deleteCallbackCount = 0;
    438 
    439  let m = new TestInterfaceObservableArray({
    440    setBooleanCallback(value) {
    441      setCallbackCount++;
    442      if (value) {
    443        throw new Error("setBooleanCallback");
    444      }
    445    },
    446    deleteBooleanCallback(value, index) {
    447      deleteCallbackCount++;
    448      if (index < 2) {
    449        throw new Error("deleteBooleanCallback");
    450      }
    451    },
    452  });
    453  m.observableArrayBoolean = [false, false, false];
    454 
    455  let b = m.observableArrayBoolean;
    456  ok(Array.isArray(b), "observable array should be an array type");
    457  is(b.length, 3, "length of observable array should be 3");
    458 
    459  [
    460    // [index, value, shouldThrow]
    461    [b.length, true, true],
    462    [b.length, false, false],
    463    [b.length, true, true],
    464    [0, false, true],
    465    [0, true, true]
    466  ].forEach(function([index, value, shouldThrow]) {
    467    // Initialize
    468    let oldValue = b[index];
    469    let oldLen = b.length;
    470    setCallbackCount = 0;
    471    deleteCallbackCount = 0;
    472 
    473    // Test
    474    info(`setting value of property ${index} to ${value}`);
    475    try {
    476      b[index] = value;
    477      ok(!shouldThrow, `setting value should not throw`);
    478    } catch(e) {
    479      ok(shouldThrow, `setting value throws ${e}`);
    480    }
    481    is(setCallbackCount, (shouldThrow && index < 2) ? 0 : 1, "setCallback should be called");
    482    is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback should be called");
    483    is(b[index], shouldThrow ? oldValue : value, "property value");
    484    is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), `length of observable array`);
    485  });
    486 });
    487 
    488 add_task(function testObservableArray_object() {
    489  let setCallbackCount = 0;
    490  let deleteCallbackCount = 0;
    491  let callbackIndex = 0;
    492 
    493  let values = [
    494    {property1: false, property2: "property2"},
    495    {property1: [], property2: 2},
    496  ];
    497 
    498  let m = new TestInterfaceObservableArray({
    499    setObjectCallback(value, index) {
    500      setCallbackCount++;
    501      is(index, callbackIndex++, "setCallbackTests: test index argument");
    502      isDeeply(values[index], value, "setCallbackTests: test value argument");
    503    },
    504    deleteObjectCallback() {
    505      deleteCallbackCount++;
    506    },
    507  });
    508 
    509  m.observableArrayObject = values;
    510 
    511  let b = m.observableArrayObject;
    512  ok(Array.isArray(b), "observable array should be an array type");
    513  is(b.length, 2, "length of observable array should be 2");
    514  is(setCallbackCount, values.length, "setCallback should be called");
    515  is(deleteCallbackCount, 0, "deleteCallback should not be called");
    516 
    517  for(let i = 0; i < values.length; i++) {
    518    isDeeply(values[i], b[i], `check index ${i}`);
    519  }
    520 });
    521 
    522 add_task(function testObservableArray_xrays() {
    523  let m = new TestInterfaceObservableArray({
    524    setObjectCallback() {
    525      ok(false, "Shouldn't reach setObjectCallback");
    526    },
    527    deleteObjectCallback() {
    528      ok(false, "Shouldn't reach deleteObjectCallback");
    529    },
    530  });
    531 
    532  let wrapper = SpecialPowers.wrap(m);
    533  ok(SpecialPowers.Cu.isXrayWrapper(wrapper), "Should be a wrapper");
    534  let observableArray = wrapper.observableArrayBoolean;
    535  ok(!!observableArray, "Should not throw");
    536  is("length" in observableArray, false, "Should be opaque");
    537 
    538  try {
    539    wrapper.observableArrayBoolean = [true, false, false];
    540    ok(false, "Expected to throw, for now");
    541  } catch (ex) {}
    542 });
    543 
    544 </script>
    545 </body>
    546 </html>