|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=2 et sw=2 tw=80: */ |
|
3 /* Any copyright is dedicated to the Public Domain. |
|
4 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
5 |
|
6 "use strict"; |
|
7 |
|
8 ////////////////////////////////////////////////////////////////////////// |
|
9 // Test helpers |
|
10 |
|
11 let TopSitesTestHelper = { |
|
12 get grid() { |
|
13 return Browser.selectedBrowser.contentDocument.getElementById("start-topsites-grid"); |
|
14 }, |
|
15 get document() { |
|
16 return Browser.selectedBrowser.contentDocument; |
|
17 }, |
|
18 setup: function() { |
|
19 return Task.spawn(function(){ |
|
20 if (BrowserUI.isStartTabVisible) |
|
21 return; |
|
22 |
|
23 yield addTab("about:start"); |
|
24 |
|
25 yield waitForCondition(() => BrowserUI.isStartTabVisible); |
|
26 }); |
|
27 }, |
|
28 mockLinks: function th_mockLinks(aLinks) { |
|
29 // create link objects where index. corresponds to grid position |
|
30 // falsy values are set to null |
|
31 let links = (typeof aLinks == "string") ? |
|
32 aLinks.split(/\s*,\s*/) : aLinks; |
|
33 |
|
34 links = links.map(function (id) { |
|
35 return (id) ? {url: "http://example.com/#" + id, title: id} : null; |
|
36 }); |
|
37 return links; |
|
38 }, |
|
39 siteFromNode: function th_siteFromNode(aNode) { |
|
40 return { |
|
41 url: aNode.getAttribute("value"), |
|
42 title: aNode.getAttribute("label") |
|
43 } |
|
44 }, |
|
45 clearHistory: function th_clearHistory() { |
|
46 PlacesUtils.history.removeAllPages(); |
|
47 }, |
|
48 fillHistory: function th_fillHistory(aLinks) { |
|
49 return Task.spawn(function(){ |
|
50 let numLinks = aLinks.length; |
|
51 let transitionLink = Ci.nsINavHistoryService.TRANSITION_LINK; |
|
52 |
|
53 let updateDeferred = Promise.defer(); |
|
54 |
|
55 for (let link of aLinks.reverse()) { |
|
56 let place = { |
|
57 uri: Util.makeURI(link.url), |
|
58 title: link.title, |
|
59 visits: [{visitDate: Date.now() * 1000, transitionType: transitionLink}] |
|
60 }; |
|
61 try { |
|
62 PlacesUtils.asyncHistory.updatePlaces(place, { |
|
63 handleError: function (aError) { |
|
64 ok(false, "couldn't add visit to history"); |
|
65 throw new Task.Result(aError); |
|
66 }, |
|
67 handleResult: function () {}, |
|
68 handleCompletion: function () { |
|
69 if(--numLinks <= 0) { |
|
70 updateDeferred.resolve(true); |
|
71 } |
|
72 } |
|
73 }); |
|
74 } catch(e) { |
|
75 ok(false, "because: " + e); |
|
76 } |
|
77 } |
|
78 return updateDeferred.promise; |
|
79 }); |
|
80 }, |
|
81 |
|
82 /** |
|
83 * Allows to specify the list of pinned links (that have a fixed position in |
|
84 * the grid. |
|
85 * @param aLinksPattern the pattern (see below) |
|
86 * |
|
87 * Example: setPinnedLinks("foo,,bar") |
|
88 * Result: 'http://example.com/#foo' is pinned in the first cell. 'http://example.com/#bar' is |
|
89 * pinned in the third cell. |
|
90 */ |
|
91 setPinnedLinks: function th_setPinnedLinks(aLinks) { |
|
92 let links = TopSitesTestHelper.mockLinks(aLinks); |
|
93 |
|
94 // (we trust that NewTabUtils works, and test our consumption of it) |
|
95 // clear all existing pins |
|
96 Array.forEach(NewTabUtils.pinnedLinks.links, function(aLink){ |
|
97 if(aLink) |
|
98 NewTabUtils.pinnedLinks.unpin(aLink); |
|
99 }); |
|
100 |
|
101 links.forEach(function(aLink, aIndex){ |
|
102 if(aLink) { |
|
103 NewTabUtils.pinnedLinks.pin(aLink, aIndex); |
|
104 } |
|
105 }); |
|
106 NewTabUtils.pinnedLinks.save(); |
|
107 }, |
|
108 |
|
109 /** |
|
110 * Allows to provide a list of links that is used to construct the grid. |
|
111 * @param aLinksPattern the pattern (see below) |
|
112 * @param aPinnedLinksPattern the pattern (see below) |
|
113 * |
|
114 * Example: setLinks("dougal,florence,zebedee") |
|
115 * Result: [{url: "http://example.com/#dougal", title: "dougal"}, |
|
116 * {url: "http://example.com/#florence", title: "florence"} |
|
117 * {url: "http://example.com/#zebedee", title: "zebedee"}] |
|
118 * Example: setLinks("dougal,florence,zebedee","dougal,,zebedee") |
|
119 * Result: http://example.com/#dougal is pinned at index 0, http://example.com/#florence at index 2 |
|
120 */ |
|
121 |
|
122 setLinks: function th_setLinks(aLinks, aPinnedLinks) { |
|
123 let links = TopSitesTestHelper.mockLinks(aLinks); |
|
124 if (links.filter(function(aLink){ |
|
125 return !aLink; |
|
126 }).length) { |
|
127 throw new Error("null link objects in setLinks"); |
|
128 } |
|
129 |
|
130 return Task.spawn(function() { |
|
131 TopSitesTestHelper.clearHistory(); |
|
132 |
|
133 yield Task.spawn(TopSitesTestHelper.fillHistory(links)); |
|
134 |
|
135 if(aPinnedLinks) { |
|
136 TopSitesTestHelper.setPinnedLinks(aPinnedLinks); |
|
137 } |
|
138 |
|
139 // reset the TopSites state, have it update its cache with the new data fillHistory put there |
|
140 yield TopSites.prepareCache(true); |
|
141 }); |
|
142 }, |
|
143 |
|
144 updatePagesAndWait: function th_updatePagesAndWait() { |
|
145 let deferredUpdate = Promise.defer(); |
|
146 let updater = { |
|
147 update: function() { |
|
148 NewTabUtils.allPages.unregister(updater); |
|
149 deferredUpdate.resolve(true); |
|
150 } |
|
151 }; |
|
152 NewTabUtils.allPages.register(updater); |
|
153 setTimeout(function() { |
|
154 NewTabUtils.allPages.update(); |
|
155 }, 0); |
|
156 return deferredUpdate.promise; |
|
157 }, |
|
158 |
|
159 tearDown: function th_tearDown() { |
|
160 TopSitesTestHelper.clearHistory(); |
|
161 } |
|
162 }; |
|
163 |
|
164 |
|
165 ////////////////////////////////////////////////////////////////////////// |
|
166 |
|
167 |
|
168 function test() { |
|
169 registerCleanupFunction(TopSitesTestHelper.tearDown); |
|
170 runTests(); |
|
171 } |
|
172 |
|
173 gTests.push({ |
|
174 desc: "TopSites dependencies", |
|
175 run: function() { |
|
176 ok(NewTabUtils, "NewTabUtils is truthy"); |
|
177 ok(TopSites, "TopSites is truthy"); |
|
178 } |
|
179 }); |
|
180 |
|
181 gTests.push({ |
|
182 desc: "load and display top sites", |
|
183 setUp: function() { |
|
184 yield TopSitesTestHelper.setup(); |
|
185 let grid = TopSitesTestHelper.grid; |
|
186 |
|
187 // setup - set history to known state |
|
188 yield TopSitesTestHelper.setLinks("brian,dougal,dylan,ermintrude,florence,moose,sgtsam,train,zebedee,zeebad"); |
|
189 |
|
190 let arrangedPromise = waitForEvent(grid, "arranged"); |
|
191 yield TopSitesTestHelper.updatePagesAndWait(); |
|
192 // pause until the update has fired and the view is finishd updating |
|
193 yield arrangedPromise; |
|
194 }, |
|
195 run: function() { |
|
196 let grid = TopSitesTestHelper.grid; |
|
197 let items = grid.items; |
|
198 is(items.length, 8, "should be 8 topsites"); // i.e. not 10 |
|
199 if(items.length) { |
|
200 let firstitem = items[0]; |
|
201 is( |
|
202 firstitem.getAttribute("label"), |
|
203 "brian", |
|
204 "first item label should be 'brian': " + firstitem.getAttribute("label") |
|
205 ); |
|
206 is( |
|
207 firstitem.getAttribute("value"), |
|
208 "http://example.com/#brian", |
|
209 "first item url should be 'http://example.com/#brian': " + firstitem.getAttribute("url") |
|
210 ); |
|
211 } |
|
212 } |
|
213 }); |
|
214 |
|
215 gTests.push({ |
|
216 desc: "pinned sites", |
|
217 pins: "dangermouse,zebedee,,,dougal", |
|
218 setUp: function() { |
|
219 yield TopSitesTestHelper.setup(); |
|
220 // setup - set history to known state |
|
221 yield TopSitesTestHelper.setLinks( |
|
222 "brian,dougal,dylan,ermintrude,florence,moose,sgtsam,train,zebedee,zeebad", |
|
223 this.pins |
|
224 ); |
|
225 // pause until the update has fired and the view is finishd updating |
|
226 let arrangedPromise = waitForEvent(TopSitesTestHelper.grid, "arranged"); |
|
227 yield TopSitesTestHelper.updatePagesAndWait(); |
|
228 yield arrangedPromise; |
|
229 }, |
|
230 run: function() { |
|
231 // test that pinned state of each site as rendered matches our expectations |
|
232 let pins = this.pins.split(","); |
|
233 let items = TopSitesTestHelper.grid.items; |
|
234 is(items.length, 8, "should be 8 topsites in the grid"); |
|
235 |
|
236 is(TopSitesTestHelper.document.querySelectorAll("#start-topsites-grid > [pinned]").length, 3, "should be 3 children with 'pinned' attribute"); |
|
237 try { |
|
238 Array.forEach(items, function(aItem, aIndex){ |
|
239 // pinned state should agree with the pins array |
|
240 is( |
|
241 aItem.hasAttribute("pinned"), !!pins[aIndex], |
|
242 "site at index " + aIndex + " was " +aItem.hasAttribute("pinned") |
|
243 +", should agree with " + !!pins[aIndex] |
|
244 ); |
|
245 if (pins[aIndex]) { |
|
246 is( |
|
247 aItem.getAttribute("label"), |
|
248 pins[aIndex], |
|
249 "pinned site has correct label: " + pins[aIndex] +"=="+ aItem.getAttribute("label") |
|
250 ); |
|
251 } |
|
252 }, this); |
|
253 } catch(e) { |
|
254 ok(false, this.desc + ": Test of pinned state on items failed"); |
|
255 info("because: " + e.message + "\n" + e.stack); |
|
256 } |
|
257 } |
|
258 }); |
|
259 |
|
260 gTests.push({ |
|
261 desc: "pin site", |
|
262 setUp: function() { |
|
263 yield TopSitesTestHelper.setup(); |
|
264 // setup - set history to known state |
|
265 yield TopSitesTestHelper.setLinks("sgtsam,train,zebedee,zeebad", []); // nothing initially pinned |
|
266 // pause until the update has fired and the view is finishd updating |
|
267 let arrangedPromise = waitForEvent(TopSitesTestHelper.grid, "arranged"); |
|
268 yield TopSitesTestHelper.updatePagesAndWait(); |
|
269 yield arrangedPromise; |
|
270 }, |
|
271 run: function() { |
|
272 // pin a site |
|
273 // test that site is pinned as expected |
|
274 // and that sites fill positions around it |
|
275 let grid = TopSitesTestHelper.grid, |
|
276 items = grid.items; |
|
277 is(items.length, 4, this.desc + ": should be 4 topsites"); |
|
278 |
|
279 let tile = grid.items[2], |
|
280 url = tile.getAttribute("value"), |
|
281 title = tile.getAttribute("label"); |
|
282 |
|
283 info(this.desc + ": pinning site at index 2"); |
|
284 TopSites.pinSites([{ |
|
285 url: url, |
|
286 title: title |
|
287 }], [2]); |
|
288 |
|
289 // pinning shouldn't require re-arranging - just wait for isUpdating flag to flip |
|
290 yield waitForCondition(function(){ |
|
291 return !grid.controller.isUpdating; |
|
292 }); |
|
293 |
|
294 let thirdTile = grid.items[2]; |
|
295 ok( thirdTile.hasAttribute("pinned"), thirdTile.getAttribute("value")+ " should look pinned" ); |
|
296 |
|
297 // visit some more sites |
|
298 yield TopSitesTestHelper.fillHistory( TopSitesTestHelper.mockLinks("brian,dougal,dylan,ermintrude,florence,moose") ); |
|
299 |
|
300 // force flush and repopulation of links cache |
|
301 yield TopSites.prepareCache(true); |
|
302 // pause until the update has fired and the view is finishd updating |
|
303 let arrangedPromise = waitForEvent(grid, "arranged"); |
|
304 yield TopSitesTestHelper.updatePagesAndWait(); |
|
305 yield arrangedPromise; |
|
306 |
|
307 // check zebedee is still pinned at index 2 |
|
308 is( items[2].getAttribute("label"), "zebedee", "Pinned site remained at its index" ); |
|
309 ok( items[2].hasAttribute("pinned"), "3rd site should still look pinned" ); |
|
310 } |
|
311 }); |
|
312 |
|
313 gTests.push({ |
|
314 desc: "unpin site", |
|
315 pins: ",zebedee", |
|
316 setUp: function() { |
|
317 yield TopSitesTestHelper.setup(); |
|
318 // setup - set history to known state |
|
319 yield TopSitesTestHelper.setLinks( |
|
320 "brian,dougal,dylan,ermintrude,florence,moose,sgtsam,train,zebedee,zeebad", |
|
321 this.pins |
|
322 ); |
|
323 // pause until the update has fired and the view is finishd updating |
|
324 let arrangedPromise = waitForEvent(TopSitesTestHelper.grid, "arranged"); |
|
325 yield TopSitesTestHelper.updatePagesAndWait(); |
|
326 yield arrangedPromise; |
|
327 }, |
|
328 run: function() { |
|
329 // unpin a pinned site |
|
330 // test that sites are unpinned as expected |
|
331 let grid = TopSitesTestHelper.grid, |
|
332 items = grid.items; |
|
333 is(items.length, 8, this.desc + ": should be 8 topsites"); |
|
334 let site = { |
|
335 url: items[1].getAttribute("value"), |
|
336 title: items[1].getAttribute("label") |
|
337 }; |
|
338 // verify assumptions before unpinning this site |
|
339 ok( NewTabUtils.pinnedLinks.isPinned(site), "2nd item is pinned" ); |
|
340 ok( items[1].hasAttribute("pinned"), "2nd item has pinned attribute" ); |
|
341 |
|
342 // unpinning shouldn't require re-arranging - just wait for isUpdating flag to flip |
|
343 TopSites.unpinSites([site]); |
|
344 |
|
345 yield waitForCondition(function(){ |
|
346 return !grid.controller.isUpdating; |
|
347 }); |
|
348 |
|
349 let secondTile = grid.items[1]; |
|
350 ok( !secondTile.hasAttribute("pinned"), "2nd item should no longer be marked as pinned" ); |
|
351 ok( !NewTabUtils.pinnedLinks.isPinned(site), "2nd item should no longer be pinned" ); |
|
352 } |
|
353 }); |
|
354 |
|
355 gTests.push({ |
|
356 desc: "block/unblock sites", |
|
357 setUp: function() { |
|
358 yield TopSitesTestHelper.setup(); |
|
359 // setup - set topsites to known state |
|
360 yield TopSitesTestHelper.setLinks( |
|
361 "brian,dougal,dylan,ermintrude,florence,moose,sgtsam,train,zebedee,zeebad,basic,coral", |
|
362 ",dougal" |
|
363 ); |
|
364 // pause until the update has fired and the view is finishd updating |
|
365 let arrangedPromise = waitForEvent(TopSitesTestHelper.grid, "arranged"); |
|
366 yield TopSitesTestHelper.updatePagesAndWait(); |
|
367 yield arrangedPromise; |
|
368 }, |
|
369 run: function() { |
|
370 try { |
|
371 // block a site |
|
372 // test that sites are removed from the grid as expected |
|
373 let grid = TopSitesTestHelper.grid, |
|
374 items = grid.items; |
|
375 is(items.length, 8, this.desc + ": should be 8 topsites"); |
|
376 |
|
377 let brianSite = TopSitesTestHelper.siteFromNode(items[0]); |
|
378 let dougalSite = TopSitesTestHelper.siteFromNode(items[1]); |
|
379 let dylanSite = TopSitesTestHelper.siteFromNode(items[2]); |
|
380 |
|
381 let arrangedPromise = waitForEvent(grid, "arranged"); |
|
382 // we'll block brian (he's not pinned) |
|
383 TopSites.hideSites([brianSite]); |
|
384 // pause until the update has fired and the view is finished updating |
|
385 yield arrangedPromise; |
|
386 |
|
387 // verify brian is blocked and removed from the grid |
|
388 ok( (new Site(brianSite)).blocked, "Site has truthy blocked property" ); |
|
389 ok( NewTabUtils.blockedLinks.isBlocked(brianSite), "Site was blocked" ); |
|
390 is( grid.querySelectorAll("[value='"+brianSite.url+"']").length, 0, "Blocked site was removed from grid"); |
|
391 |
|
392 // make sure the empty slot was backfilled |
|
393 is(items.length, 8, this.desc + ": should be 8 topsites"); |
|
394 |
|
395 arrangedPromise = waitForEvent(grid, "arranged"); |
|
396 // block dougal,dylan. dougal is currently pinned at index 1 |
|
397 TopSites.hideSites([dougalSite, dylanSite]); |
|
398 // pause until the update has fired and the view is finished updating |
|
399 yield arrangedPromise; |
|
400 |
|
401 // verify dougal is blocked and removed from the grid |
|
402 ok( (new Site(dougalSite)).blocked, "Site has truthy blocked property" ); |
|
403 ok( NewTabUtils.blockedLinks.isBlocked(dougalSite), "Site was blocked" ); |
|
404 ok( !NewTabUtils.pinnedLinks.isPinned(dougalSite), "Blocked Site is no longer pinned" ); |
|
405 is( grid.querySelectorAll("[value='"+dougalSite.url+"']").length, 0, "Blocked site was removed from grid"); |
|
406 |
|
407 // verify dylan is blocked and removed from the grid |
|
408 ok( (new Site(dylanSite)).blocked, "Site has truthy blocked property" ); |
|
409 ok( NewTabUtils.blockedLinks.isBlocked(dylanSite), "Site was blocked" ); |
|
410 ok( !NewTabUtils.pinnedLinks.isPinned(dylanSite), "Blocked Site is no longer pinned" ); |
|
411 is( grid.querySelectorAll("[value='"+dylanSite.url+"']").length, 0, "Blocked site was removed from grid"); |
|
412 |
|
413 // make sure the empty slots were backfilled |
|
414 is(items.length, 8, this.desc + ": should be 8 topsites"); |
|
415 |
|
416 arrangedPromise = waitForEvent(grid, "arranged"); |
|
417 TopSites.restoreSites([brianSite, dougalSite, dylanSite]); |
|
418 // pause until the update has fired and the view is finished updating |
|
419 yield arrangedPromise; |
|
420 |
|
421 // verify brian, dougal and dyland are unblocked and back in the grid |
|
422 ok( !NewTabUtils.blockedLinks.isBlocked(brianSite), "site was unblocked" ); |
|
423 is( grid.querySelectorAll("[value='"+brianSite.url+"']").length, 1, "Unblocked site is back in the grid"); |
|
424 |
|
425 ok( !NewTabUtils.blockedLinks.isBlocked(dougalSite), "site was unblocked" ); |
|
426 is( grid.querySelectorAll("[value='"+dougalSite.url+"']").length, 1, "Unblocked site is back in the grid"); |
|
427 // ..and that a previously pinned site is re-pinned after being blocked, then restored |
|
428 ok( NewTabUtils.pinnedLinks.isPinned(dougalSite), "Restoring previously pinned site makes it pinned again" ); |
|
429 is( grid.items[1].getAttribute("value"), dougalSite.url, "Blocked Site restored to pinned index" ); |
|
430 |
|
431 ok( !NewTabUtils.blockedLinks.isBlocked(dylanSite), "site was unblocked" ); |
|
432 is( grid.querySelectorAll("[value='"+dylanSite.url+"']").length, 1, "Unblocked site is back in the grid"); |
|
433 |
|
434 } catch(ex) { |
|
435 |
|
436 ok(false, this.desc+": Caught exception in test: " + ex); |
|
437 info("trace: " + ex.stack); |
|
438 } |
|
439 } |
|
440 }); |
|
441 |
|
442 gTests.push({ |
|
443 desc: "delete and restore site tiles", |
|
444 pins: "brian", |
|
445 setUp: function() { |
|
446 yield TopSitesTestHelper.setup(); |
|
447 // setup - set history to known state |
|
448 yield TopSitesTestHelper.setLinks( |
|
449 "brian,dougal,dylan,ermintrude", |
|
450 this.pins |
|
451 ); |
|
452 // pause until the update has fired and the view is finishd updating |
|
453 let arrangedPromise = waitForEvent(TopSitesTestHelper.grid, "arranged"); |
|
454 yield TopSitesTestHelper.updatePagesAndWait(); |
|
455 yield arrangedPromise; |
|
456 }, |
|
457 run: function() { |
|
458 // delete a both pinned and unpinned sites |
|
459 // test that sites are removed from the grid |
|
460 let grid = TopSitesTestHelper.grid, |
|
461 items = grid.items; |
|
462 is(items.length, 4, this.desc + ": should be 4 topsites"); |
|
463 |
|
464 let brianTile = grid.querySelector('richgriditem[value$="brian"]'); |
|
465 let dougalTile = grid.querySelector('richgriditem[value$="dougal"]') |
|
466 |
|
467 // verify assumptions before deleting sites |
|
468 ok( brianTile, "Tile for Brian was created"); |
|
469 ok( dougalTile, "Tile for Dougal was created"); |
|
470 |
|
471 let brianSite = TopSitesTestHelper.siteFromNode(brianTile); |
|
472 let dougalSite = TopSitesTestHelper.siteFromNode(dougalTile); |
|
473 ok( NewTabUtils.pinnedLinks.isPinned( brianSite ), "Brian tile is pinned" ); |
|
474 |
|
475 // select the 2 tiles |
|
476 grid.toggleItemSelection(brianTile); |
|
477 grid.toggleItemSelection(dougalTile); |
|
478 is(grid.selectedItems.length, 2, "2 tiles were selected"); |
|
479 |
|
480 // pause until the update has fired and the view is finishd updating |
|
481 let arrangedPromise = waitForEvent(grid, "arranged"); |
|
482 |
|
483 // raise a mock context-action event to trigger deletion of the selection |
|
484 let event = document.createEvent("Events"); |
|
485 event.action = "delete"; |
|
486 event.initEvent("context-action", true, true); // is cancelable |
|
487 grid.dispatchEvent(event); |
|
488 |
|
489 yield arrangedPromise; |
|
490 |
|
491 // those sites are blocked and their tiles have been removed from the grid? |
|
492 ok( !grid.querySelector('richgriditem[value="'+brianSite.value+'"]')); |
|
493 ok( !grid.querySelector('richgriditem[value="'+dougalSite.value+'"]')); |
|
494 ok( NewTabUtils.blockedLinks.isBlocked(brianSite), "Brian site was blocked" ); |
|
495 ok( NewTabUtils.blockedLinks.isBlocked(dougalSite), "Dougal site was blocked" ); |
|
496 // with the tiles deleted, selection should be empty |
|
497 is( grid.selectedItems.length, 0, "Gris selection is empty after deletion" ); |
|
498 |
|
499 // raise a mock context-action event to trigger restore |
|
500 arrangedPromise = waitForEvent(grid, "arranged"); |
|
501 event = document.createEvent("Events"); |
|
502 event.action = "restore"; |
|
503 event.initEvent("context-action", true, true); // is cancelable |
|
504 grid.dispatchEvent(event); |
|
505 |
|
506 yield arrangedPromise; |
|
507 brianTile = grid.querySelector('richgriditem[value$="brian"]'); |
|
508 dougalTile = grid.querySelector('richgriditem[value$="dougal"]'); |
|
509 |
|
510 // those tiles have been restored to the grid? |
|
511 ok( brianTile, "First tile was restored to the grid" ); |
|
512 ok( dougalTile, "2nd tile was restored to the grid" ); |
|
513 |
|
514 is(grid.selectedItems.length, 2, "2 tiles are still selected"); |
|
515 is( grid.selectedItems[0], brianTile, "Brian is still selected" ); |
|
516 is( grid.selectedItems[1], dougalTile, "Dougal is still selected" ); |
|
517 ok( NewTabUtils.pinnedLinks.isPinned( brianSite ), "Brian tile is still pinned" ); |
|
518 ok( !NewTabUtils.blockedLinks.isBlocked(brianSite), "Brian site was unblocked" ); |
|
519 ok( !NewTabUtils.blockedLinks.isBlocked(dougalSite), "Dougal site was unblocked" ); |
|
520 |
|
521 } |
|
522 }); |