test_observablearray_helper.html (12157B)
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 Helpers of 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_helper_elementAt() { 19 let m = new TestInterfaceObservableArray(); 20 21 [ 22 // [values, property, helper] 23 [[true, false], "observableArrayBoolean", m.booleanElementAtInternal.bind(m)], 24 [[new TestInterfaceObservableArray(), new TestInterfaceObservableArray()], 25 "observableArrayInterface", m.interfaceElementAtInternal.bind(m)], 26 [[{property: "test"}, {property: 2}], "observableArrayObject", 27 m.objectElementAtInternal.bind(m)], 28 ].forEach(function([values, property, helper]) { 29 m[property] = values; 30 31 let t = m[property]; 32 ok(Array.isArray(t), "observable array should be an array type"); 33 is(t.length, values.length, "length of observable array"); 34 35 for (let i = 0; i < values.length; i++) { 36 isDeeply(values[i], helper(i), `check index ${i}`); 37 } 38 39 SimpleTest.doesThrow(() => { 40 helper(values.length); 41 }, `getting element outside the range should throw`); 42 }); 43 }); 44 45 add_task(function testObservableArray_helper_replaceElementAt() { 46 let setCallbackCount = 0; 47 let deleteCallbackCount = 0; 48 let setCallbackTests = null; 49 let deleteCallbackTests = null; 50 51 let m = new TestInterfaceObservableArray({ 52 setBooleanCallback(value, index) { 53 setCallbackCount++; 54 if (typeof setCallbackTests === 'function') { 55 setCallbackTests(value, index); 56 } 57 }, 58 deleteBooleanCallback(value, index) { 59 deleteCallbackCount++; 60 if (typeof deleteCallbackTests === 'function') { 61 deleteCallbackTests(value, index); 62 } 63 }, 64 }); 65 66 let b = m.observableArrayBoolean; 67 ok(Array.isArray(b), "observable array should be an array type"); 68 is(b.length, 0, "length of observable array should be 0"); 69 70 [ 71 // [index, value, shouldThrow] 72 [b.length + 1, false, true], 73 [b.length, false, false], 74 [b.length + 1, false, false], 75 [b.length + 1, true, false], 76 ].forEach(function([index, value, shouldThrow]) { 77 // Initialize 78 let oldValue = b[index]; 79 let oldLen = b.length; 80 setCallbackCount = 0; 81 deleteCallbackCount = 0; 82 setCallbackTests = function(_value, _index) { 83 info(`set callback for ${_index}`); 84 is(_value, value, "setCallbackTests: test value argument"); 85 is(_index, index, "setCallbackTests: test index argument"); 86 }; 87 deleteCallbackTests = function(_value, _index) { 88 info(`delete callback for ${_index}`); 89 is(_value, oldValue, "deleteCallbackTests: test value argument"); 90 is(_index, index, "deleteCallbackTests: test index argument"); 91 }; 92 93 // Test 94 info(`setting value of property ${index} to ${value}`); 95 try { 96 m.booleanReplaceElementAtInternal(index, value); 97 ok(!shouldThrow, `setting value should not throw`); 98 } catch(e) { 99 ok(shouldThrow, `setting value throws ${e}`); 100 } 101 is(setCallbackCount, shouldThrow ? 0 : 1, "setCallback count"); 102 is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback count"); 103 is(b[index], shouldThrow ? oldValue : value, `property value`); 104 is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), `length of observable array`); 105 }); 106 }); 107 108 add_task(function testObservableArray_helper_replaceElementAt_callback_throw() { 109 let setCallbackCount = 0; 110 let deleteCallbackCount = 0; 111 112 let m = new TestInterfaceObservableArray({ 113 setBooleanCallback(value) { 114 setCallbackCount++; 115 if (value) { 116 throw new Error("setBooleanCallback"); 117 } 118 }, 119 deleteBooleanCallback(value, index) { 120 deleteCallbackCount++; 121 if (index < 2) { 122 throw new Error("deleteBooleanCallback"); 123 } 124 }, 125 }); 126 m.observableArrayBoolean = [false, false, false]; 127 128 let b = m.observableArrayBoolean; 129 ok(Array.isArray(b), "observable array should be an array type"); 130 is(b.length, 3, "length of observable array should be 3"); 131 132 [ 133 // [index, value, shouldThrow] 134 [b.length, true, true], 135 [b.length, false, false], 136 [b.length, true, true], 137 [0, false, true], 138 [0, true, true] 139 ].forEach(function([index, value, shouldThrow]) { 140 // Initialize 141 let oldValue = b[index]; 142 let oldLen = b.length; 143 setCallbackCount = 0; 144 deleteCallbackCount = 0; 145 146 // Test 147 info(`setting value of property ${index} to ${value}`); 148 try { 149 m.booleanReplaceElementAtInternal(index, value); 150 ok(!shouldThrow, `setting value should not throw`); 151 } catch(e) { 152 ok(shouldThrow, `setting value throws ${e}`); 153 } 154 is(setCallbackCount, (shouldThrow && index < 2) ? 0 : 1, "setCallback count"); 155 is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback count"); 156 is(b[index], shouldThrow ? oldValue : value, "property value"); 157 is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), `length of observable array`); 158 }); 159 }); 160 161 add_task(function testObservableArray_helper_appendElement() { 162 let setCallbackCount = 0; 163 let deleteCallbackCount = 0; 164 let setCallbackTests = null; 165 166 let m = new TestInterfaceObservableArray({ 167 setBooleanCallback(value, index) { 168 setCallbackCount++; 169 if (typeof setCallbackTests === 'function') { 170 setCallbackTests(value, index); 171 } 172 }, 173 deleteBooleanCallback() { 174 deleteCallbackCount++; 175 }, 176 }); 177 178 let b = m.observableArrayBoolean; 179 ok(Array.isArray(b), "observable array should be an array type"); 180 is(b.length, 0, "length of observable array should be 0"); 181 182 [true, false, true, false].forEach(function(value) { 183 // Initialize 184 let oldLen = b.length; 185 let index = oldLen; 186 setCallbackCount = 0; 187 deleteCallbackCount = 0; 188 setCallbackTests = function(_value, _index) { 189 info(`set callback for ${_index}`); 190 is(_value, value, "setCallbackTests: test value argument"); 191 is(_index, index, "setCallbackTests: test index argument"); 192 }; 193 194 // Test 195 info(`append ${value}`); 196 try { 197 m.booleanAppendElementInternal(value); 198 ok(true, `appending value should not throw`); 199 } catch(e) { 200 ok(false, `appending value throws ${e}`); 201 } 202 is(setCallbackCount, 1, "setCallback should be called"); 203 is(deleteCallbackCount, 0, "deleteCallback should not be called"); 204 is(b[index], value, `property value`); 205 is(b.length, oldLen + 1, `length of observable array`); 206 }); 207 }); 208 209 add_task(function testObservableArray_helper_appendElement_callback_throw() { 210 let setCallbackCount = 0; 211 let deleteCallbackCount = 0; 212 213 let m = new TestInterfaceObservableArray({ 214 setBooleanCallback(value) { 215 setCallbackCount++; 216 if (value) { 217 throw new Error("setBooleanCallback"); 218 } 219 }, 220 deleteBooleanCallback() { 221 deleteCallbackCount++; 222 }, 223 }); 224 m.observableArrayBoolean = [false, false, false]; 225 226 let b = m.observableArrayBoolean; 227 ok(Array.isArray(b), "observable array should be an array type"); 228 is(b.length, 3, "length of observable array should be 3"); 229 230 [true, false, true, false].forEach(function(value) { 231 // Initialize 232 let oldLen = b.length; 233 let index = oldLen; 234 let oldValue = b[index]; 235 let shouldThrow = value; 236 setCallbackCount = 0; 237 deleteCallbackCount = 0; 238 239 // Test 240 info(`append ${value}`); 241 try { 242 m.booleanAppendElementInternal(value); 243 ok(!shouldThrow, `appending value should not throw`); 244 } catch(e) { 245 ok(shouldThrow, `appending value throws ${e}`); 246 } 247 is(setCallbackCount, 1, "setCallback should be called"); 248 is(deleteCallbackCount, 0, "deleteCallback should not be called"); 249 is(b[index], shouldThrow ? oldValue : value, "property value"); 250 is(b.length, shouldThrow ? oldLen : oldLen + 1, `length of observable array`); 251 }); 252 }); 253 254 add_task(function testObservableArray_helper_removeLastElement() { 255 let setCallbackCount = 0; 256 let deleteCallbackCount = 0; 257 let deleteCallbackTests = null; 258 259 let m = new TestInterfaceObservableArray({ 260 setBooleanCallback() { 261 setCallbackCount++; 262 }, 263 deleteBooleanCallback(value, index) { 264 deleteCallbackCount++; 265 if (typeof deleteCallbackTests === 'function') { 266 deleteCallbackTests(value, index); 267 } 268 }, 269 }); 270 m.observableArrayBoolean = [true, false, true, false]; 271 272 let b = m.observableArrayBoolean; 273 ok(Array.isArray(b), "observable array should be an array type"); 274 is(b.length, 4, "length of observable array should be 4"); 275 276 let oldValues = b.slice(); 277 while (oldValues.length) { 278 // Initialize 279 let oldValue = oldValues.pop(); 280 let index = oldValues.length; 281 setCallbackCount = 0; 282 deleteCallbackCount = 0; 283 deleteCallbackTests = function(_value, _index) { 284 info(`delete callback for ${_index}`); 285 is(_value, oldValue, "deleteCallbackTests: test value argument"); 286 is(_index, index, "deleteCallbackTests: test index argument"); 287 }; 288 289 // Test 290 info(`remove last element`); 291 try { 292 m.booleanRemoveLastElementInternal(); 293 ok(true, `removing last element should not throw`); 294 } catch(e) { 295 ok(false, `removing last element throws ${e}`); 296 } 297 is(setCallbackCount, 0, "setCallback should not be called"); 298 is(deleteCallbackCount, 1, "deleteCallback should be called"); 299 isDeeply(b, oldValues, `property value`); 300 is(b.length, oldValues.length, `length of observable array`); 301 } 302 303 // test when array is empty 304 setCallbackCount = 0; 305 deleteCallbackCount = 0; 306 SimpleTest.doesThrow(() => { 307 m.booleanRemoveLastElementInternal(); 308 }, `removing last element should throw when array is empty`); 309 is(setCallbackCount, 0, "setCallback should not be called"); 310 is(deleteCallbackCount, 0, "deleteCallback should not be called"); 311 is(b.length, 0, `length of observable array`); 312 }); 313 314 add_task(function testObservableArray_helper_removeLastElement_callback_throw() { 315 let setCallbackCount = 0; 316 let deleteCallbackCount = 0; 317 318 let m = new TestInterfaceObservableArray({ 319 setBooleanCallback() { 320 setCallbackCount++; 321 }, 322 deleteBooleanCallback(value) { 323 deleteCallbackCount++; 324 if (value) { 325 throw new Error("deleteBooleanCallback"); 326 } 327 }, 328 }); 329 m.observableArrayBoolean = [false, true, false, false]; 330 331 let b = m.observableArrayBoolean; 332 ok(Array.isArray(b), "observable array should be an array type"); 333 is(b.length, 4, "length of observable array should be 4"); 334 335 let shouldThrow = false; 336 while (!shouldThrow && b.length) { 337 // Initialize 338 let oldValues = b.slice(); 339 let oldLen = b.length; 340 shouldThrow = oldValues[oldLen - 1]; 341 setCallbackCount = 0; 342 deleteCallbackCount = 0; 343 344 // Test 345 info(`remove last element`); 346 try { 347 m.booleanRemoveLastElementInternal(); 348 ok(!shouldThrow, `removing last element should not throw`); 349 } catch(e) { 350 ok(shouldThrow, `removing last element throws ${e}`); 351 } 352 is(setCallbackCount, 0, "setCallback should not be called"); 353 is(deleteCallbackCount, 1, "deleteCallback should be called"); 354 isDeeply(b, shouldThrow ? oldValues : oldValues.slice(0, oldLen - 1), `property value`); 355 is(b.length, shouldThrow ? oldLen : oldLen - 1, `length of observable array`); 356 } 357 }); 358 359 add_task(function testObservableArray_helper_length() { 360 let m = new TestInterfaceObservableArray(); 361 let b = m.observableArrayBoolean; 362 ok(Array.isArray(b), "observable array should be an array type"); 363 is(b.length, 0, "length of observable array"); 364 365 [ 366 [false, true, false, true], 367 [true, false], 368 [false, true, false], 369 ].forEach(function(values) { 370 m.observableArrayBoolean = values; 371 is(b.length, m.booleanLengthInternal(), "length helper function"); 372 }); 373 }); 374 </script> 375 </body> 376 </html>