gecko/browser/metro/base/tests/mochitest/browser_topsites.js
Sam Foster 7b566e39d2 Bug 865170 - Fix TopSite's methods to handle multiple sites as input. r=mbrubeck
--HG--
extra : rebase_source : 02850083782a245c6046dc070760bf3083a1b144
2013-04-26 17:38:19 +01:00

437 lines
14 KiB
JavaScript

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
//////////////////////////////////////////////////////////////////////////
// Test helpers
function mockLinks(aLinks) {
// create link objects where index. corresponds to grid position
// falsy values are set to null
let links = (typeof aLinks == "string") ?
aLinks.split(/\s*,\s*/) : aLinks;
links = links.map(function (id) {
return (id) ? {url: "http://example.com/#" + id, title: id} : null;
});
return links;
}
function siteFromNode(aNode) {
return {
url: aNode.getAttribute("value"),
title: aNode.getAttribute("label")
};
}
function clearHistory() {
PlacesUtils.history.removeAllPages();
}
function fillHistory(aLinks) {
return Task.spawn(function(){
let numLinks = aLinks.length;
let transitionLink = Ci.nsINavHistoryService.TRANSITION_LINK;
let updateDeferred = Promise.defer();
for (let link of aLinks.reverse()) {
let place = {
uri: Util.makeURI(link.url),
title: link.title,
visits: [{visitDate: Date.now() * 1000, transitionType: transitionLink}]
};
try {
PlacesUtils.asyncHistory.updatePlaces(place, {
handleError: function (aError) {
ok(false, "couldn't add visit to history");
throw new Task.Result(aError);
},
handleResult: function () {},
handleCompletion: function () {
if(--numLinks <= 0) {
updateDeferred.resolve(true);
}
}
});
} catch(e) {
ok(false, "because: " + e);
}
}
return updateDeferred.promise;
});
}
/**
* Allows to specify the list of pinned links (that have a fixed position in
* the grid.
* @param aLinksPattern the pattern (see below)
*
* Example: setPinnedLinks("foo,,bar")
* Result: 'http://example.com/#foo' is pinned in the first cell. 'http://example.com/#bar' is
* pinned in the third cell.
*/
function setPinnedLinks(aLinks) {
let links = mockLinks(aLinks);
// (we trust that NewTabUtils works, and test our consumption of it)
// clear all existing pins
Array.forEach(NewTabUtils.pinnedLinks.links, function(aLink){
if(aLink)
NewTabUtils.pinnedLinks.unpin(aLink);
});
links.forEach(function(aLink, aIndex){
if(aLink) {
NewTabUtils.pinnedLinks.pin(aLink, aIndex);
}
});
NewTabUtils.pinnedLinks.save();
}
/**
* Allows to provide a list of links that is used to construct the grid.
* @param aLinksPattern the pattern (see below)
* @param aPinnedLinksPattern the pattern (see below)
*
* Example: setLinks("dougal,florence,zebedee")
* Result: [{url: "http://example.com/#dougal", title: "dougal"},
* {url: "http://example.com/#florence", title: "florence"}
* {url: "http://example.com/#zebedee", title: "zebedee"}]
* Example: setLinks("dougal,florence,zebedee","dougal,,zebedee")
* Result: http://example.com/#dougal is pinned at index 0, http://example.com/#florence at index 2
*/
function setLinks(aLinks, aPinnedLinks) {
let links = mockLinks(aLinks);
if (links.filter(function(aLink){
return !aLink;
}).length) {
throw new Error("null link objects in setLinks");
}
return Task.spawn(function() {
clearHistory();
yield Task.spawn(fillHistory(links));
if(aPinnedLinks) {
setPinnedLinks(aPinnedLinks);
}
// reset the TopSites state, have it update its cache with the new data fillHistory put there
yield TopSites.prepareCache(true);
});
}
function updatePagesAndWait() {
let deferredUpdate = Promise.defer();
let updater = {
update: function() {
NewTabUtils.allPages.unregister(updater);
deferredUpdate.resolve(true);
}
};
NewTabUtils.allPages.register(updater);
setTimeout(function() {
NewTabUtils.allPages.update();
}, 0);
return deferredUpdate.promise;
}
//////////////////////////////////////////////////////////////////////////
function test() {
runTests();
}
gTests.push({
desc: "TopSites dependencies",
run: function() {
ok(NewTabUtils, "NewTabUtils is truthy");
ok(TopSites, "TopSites is truthy");
}
});
gTests.push({
desc: "load and display top sites",
setUp: function() {
// setup - set history to known state
yield setLinks("brian,dougal,dylan,ermintrude,florence,moose,sgtsam,train,zebedee,zeebad");
let grid = document.getElementById("start-topsites-grid");
yield updatePagesAndWait();
// pause until the update has fired and the view is finishd updating
yield waitForCondition(function(){
return !grid.controller.isUpdating;
});
},
run: function() {
let grid = document.getElementById("start-topsites-grid");
let items = grid.children;
is(items.length, 8, "should be 8 topsites"); // i.e. not 10
if(items.length) {
let firstitem = items[0];
is(
firstitem.getAttribute("label"),
"brian",
"first item label should be 'brian': " + firstitem.getAttribute("label")
);
is(
firstitem.getAttribute("value"),
"http://example.com/#brian",
"first item url should be 'http://example.com/#brian': " + firstitem.getAttribute("url")
);
}
}
});
gTests.push({
desc: "pinned sites",
pins: "dangermouse,zebedee,,,dougal",
setUp: function() {
// setup - set history to known state
yield setLinks(
"brian,dougal,dylan,ermintrude,florence,moose,sgtsam,train,zebedee,zeebad",
this.pins
);
yield updatePagesAndWait();
// pause until the update has fired and the view is finished updating
yield waitForCondition(function(){
let grid = document.getElementById("start-topsites-grid");
return !grid.controller.isUpdating;
});
},
run: function() {
// test that pinned state of each site as rendered matches our expectations
let pins = this.pins.split(",");
let items = document.getElementById("start-topsites-grid").children;
is(items.length, 8, "should be 8 topsites in the grid");
is(document.querySelectorAll("#start-topsites-grid > [pinned]").length, 3, "should be 3 children with 'pinned' attribute");
try {
Array.forEach(items, function(aItem, aIndex){
// pinned state should agree with the pins array
is(
aItem.hasAttribute("pinned"), !!pins[aIndex],
"site at index " + aIndex + " was " +aItem.hasAttribute("pinned")
+", should agree with " + !!pins[aIndex]
);
if (pins[aIndex]) {
is(
aItem.getAttribute("label"),
pins[aIndex],
"pinned site has correct label: " + pins[aIndex] +"=="+ aItem.getAttribute("label")
);
}
}, this);
} catch(e) {
ok(false, this.desc + ": Test of pinned state on items failed");
info("because: " + e.message + "\n" + e.stack);
}
}
});
gTests.push({
desc: "pin site",
setUp: function() {
// setup - set history to known state
yield setLinks("sgtsam,train,zebedee,zeebad", []); // nothing initially pinned
yield updatePagesAndWait();
// pause until the update has fired and the view is finished updating
yield waitForCondition(function(){
let grid = document.getElementById("start-topsites-grid");
return !grid.controller.isUpdating;
});
},
run: function() {
// pin a site
// test that site is pinned as expected
// and that sites fill positions around it
let grid = document.getElementById("start-topsites-grid"),
items = grid.children;
is(items.length, 4, this.desc + ": should be 4 topsites");
let tile = grid.children[2],
url = tile.getAttribute("value"),
title = tile.getAttribute("label");
info(this.desc + ": pinning site at index 2");
TopSites.pinSites([{
url: url,
title: title
}], [2]);
yield waitForCondition(function(){
return !grid.controller.isUpdating;
});
let thirdTile = grid.children[2];
ok( thirdTile.hasAttribute("pinned"), thirdTile.getAttribute("value")+ " should look pinned" );
// visit some more sites
yield fillHistory( mockLinks("brian,dougal,dylan,ermintrude,florence,moose") );
// force flush and repopulation of links cache
yield TopSites.prepareCache(true);
yield updatePagesAndWait();
// pause until the update has fired and the view is finishd updating
yield waitForCondition(function(){
return !grid.controller.isUpdating;
});
// check zebedee is still pinned at index 2
is( items[2].getAttribute("label"), "zebedee", "Pinned site remained at its index" );
ok( items[2].hasAttribute("pinned"), "3rd site should still look pinned" );
}
});
gTests.push({
desc: "unpin site",
pins: ",zebedee",
setUp: function() {
try {
// setup - set history to known state
yield setLinks(
"brian,dougal,dylan,ermintrude,florence,moose,sgtsam,train,zebedee,zeebad",
this.pins
);
yield updatePagesAndWait();
// pause until the update has fired and the view is finished updating
yield waitForCondition(function(){
let grid = document.getElementById("start-topsites-grid");
return !grid.controller.isUpdating;
});
} catch(e) {
info("caught error in setUp: " + e);
info("trace: " + e.stack);
}
},
run: function() {
// unpin a pinned site
// test that sites are unpinned as expected
let grid = document.getElementById("start-topsites-grid"),
items = grid.children;
is(items.length, 8, this.desc + ": should be 8 topsites");
let site = {
url: items[1].getAttribute("value"),
title: items[1].getAttribute("label")
};
// verify assumptions before unpinning this site
ok( NewTabUtils.pinnedLinks.isPinned(site), "2nd item is pinned" );
ok( items[1].hasAttribute("pinned"), "2nd item has pinned attribute" );
TopSites.unpinSites([site]);
yield waitForCondition(function(){
return !grid.controller.isUpdating;
});
let secondTile = grid.children[1];
ok( !secondTile.hasAttribute("pinned"), "2nd item should no longer be marked as pinned" );
ok( !NewTabUtils.pinnedLinks.isPinned(site), "2nd item should no longer be pinned" );
}
});
gTests.push({
desc: "block/unblock sites",
setUp: function() {
// setup - set topsites to known state
yield setLinks(
"brian,dougal,dylan,ermintrude,florence,moose,sgtsam,train,zebedee,zeebad,basic,coral",
",dougal"
);
yield updatePagesAndWait();
// pause until the update has fired and the view is finished updating
yield waitForCondition(function(){
let grid = document.getElementById("start-topsites-grid");
return !grid.controller.isUpdating;
});
},
run: function() {
try {
// block a site
// test that sites are removed from the grid as expected
let grid = document.getElementById("start-topsites-grid"),
items = grid.children;
is(items.length, 8, this.desc + ": should be 8 topsites");
let brianSite = siteFromNode(items[0]);
let dougalSite = siteFromNode(items[1]);
let dylanSite = siteFromNode(items[2]);
// we'll block brian (he's not pinned)
TopSites.hideSites([brianSite]);
// pause until the update has fired and the view is finished updating
yield waitForCondition(function(){
return !grid.controller.isUpdating;
});
// verify brian is blocked and removed from the grid
ok( (new Site(brianSite)).blocked, "Site has truthy blocked property" );
ok( NewTabUtils.blockedLinks.isBlocked(brianSite), "Site was blocked" );
is( grid.querySelectorAll("[value='"+brianSite.url+"']").length, 0, "Blocked site was removed from grid");
// make sure the empty slot was backfilled
is(items.length, 8, this.desc + ": should be 8 topsites");
// block dougal,dylan. dougal is currently pinned at index 1
TopSites.hideSites([dougalSite, dylanSite]);
// pause until the update has fired and the view is finished updating
yield waitForCondition(function(){
return !grid.controller.isUpdating;
});
// verify dougal is blocked and removed from the grid
ok( (new Site(dougalSite)).blocked, "Site has truthy blocked property" );
ok( NewTabUtils.blockedLinks.isBlocked(dougalSite), "Site was blocked" );
ok( !NewTabUtils.pinnedLinks.isPinned(dougalSite), "Blocked Site is no longer pinned" );
is( grid.querySelectorAll("[value='"+dougalSite.url+"']").length, 0, "Blocked site was removed from grid");
// verify dylan is blocked and removed from the grid
ok( (new Site(dylanSite)).blocked, "Site has truthy blocked property" );
ok( NewTabUtils.blockedLinks.isBlocked(dylanSite), "Site was blocked" );
ok( !NewTabUtils.pinnedLinks.isPinned(dylanSite), "Blocked Site is no longer pinned" );
is( grid.querySelectorAll("[value='"+dylanSite.url+"']").length, 0, "Blocked site was removed from grid");
// make sure the empty slots were backfilled
is(items.length, 8, this.desc + ": should be 8 topsites");
TopSites.restoreSites([brianSite, dougalSite, dylanSite]);
yield waitForCondition(function(){
return !grid.controller.isUpdating;
});
// verify brian, dougal and dyland are unblocked and back in the grid
ok( !NewTabUtils.blockedLinks.isBlocked(brianSite), "site was unblocked" );
is( grid.querySelectorAll("[value='"+brianSite.url+"']").length, 1, "Unblocked site is back in the grid");
ok( !NewTabUtils.blockedLinks.isBlocked(dougalSite), "site was unblocked" );
is( grid.querySelectorAll("[value='"+dougalSite.url+"']").length, 1, "Unblocked site is back in the grid");
// ..and that a previously pinned site is re-pinned after being blocked, then restored
ok( NewTabUtils.pinnedLinks.isPinned(dougalSite), "Restoring previously pinned site makes it pinned again" );
is( grid.children[1].getAttribute("value"), dougalSite.url, "Blocked Site restored to pinned index" );
ok( !NewTabUtils.blockedLinks.isBlocked(dylanSite), "site was unblocked" );
is( grid.querySelectorAll("[value='"+dylanSite.url+"']").length, 1, "Unblocked site is back in the grid");
} catch(ex) {
ok(false, this.desc+": Caught exception in test: " + ex);
info("trace: " + ex.stack);
}
}
});