Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / test / data / extensions / api_test / bookmarks / test.js
blob88d1f26b244248144b1bd0cc48747ff818f36ad6
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // bookmarks api test
6 // browser_tests.exe --gtest_filter=ExtensionApiTest.Bookmarks
8 // This is global state that is maintained across tests as a reference
9 // to compare against what's fetched from the browser (using compareTrees).
10 // TODO(erikkay) It would be better if each test was self-contained and
11 // didn't depend on global state.
12 var expected = [
13   {"children": [
14       {children:[], id:"1", parentId:"0", index:0, title:"Bookmarks bar"},
15       {children:[], id:"2", parentId:"0", index:1, title:"Other bookmarks"},
16       {id:"4", parentId:"0", index:3, title:"Managed bookmarks",
17        unmodifiable:"managed", children:[
18           {id:"6", parentId:"4", index:0, title:"Managed Bookmark",
19            url:"http://www.chromium.org/", unmodifiable:"managed"},
20           {id:"7", parentId:"4", index:1, title:"Managed Folder",
21            children:[], unmodifiable:"managed"}
22         ]
23       },
24       {id:"5", parentId:"0", index:4, title:"Parent suggestions",
25        unmodifiable:"managed", children:[
26           {id:"8", parentId:"4", index:0, title:"Supervised Bookmark",
27            url:"http://www.pbskids.org/", unmodifiable:"managed"},
28           {id:"9", parentId:"4", index:1, title:"Supervised Folder",
29            children:[], unmodifiable:"managed"}
30         ]
31       }
32     ],
33    id:"0", title:""
34   }
37 function bookmarksBar() { return expected[0].children[0]; }
38 function otherBookmarks() { return expected[0].children[1]; }
40 // Some variables that are used across multiple tests.
41 var node1 = {parentId:"1", title:"bar baz",
42              url:"http://www.example.com/hello"};
43 var node2 = {parentId:"1", title:"foo quux",
44              url:"http://www.example.com/bar"};
45 var node3 = {parentId:"1", title:"Foo bar baz",
46              url:"http://www.google.com/hello/quux"};
48 var pass = chrome.test.callbackPass;
49 var fail = chrome.test.callbackFail;
51 function compareNode(left, right) {
52   //chrome.test.log("compareNode()");
53   //chrome.test.log(JSON.stringify(left, null, 2));
54   //chrome.test.log(JSON.stringify(right, null, 2));
55   // TODO(erikkay): do some comparison of dateAdded
56   if (left.id != right.id)
57     return "id mismatch: " + left.id + " != " + right.id;
58   if (left.title != right.title) {
59     // TODO(erikkay): This resource dependency still isn't working reliably.
60     // See bug 19866.
61     // return "title mismatch: " + left.title + " != " + right.title;
62     chrome.test.log("title mismatch: " + left.title + " != " + right.title);
63   }
64   if (left.url != right.url)
65     return "url mismatch: " + left.url + " != " + right.url;
66   if (left.index != right.index)
67     return "index mismatch: " + left.index + " != " + right.index;
68   if (left.unmodifiable != right.unmodifiable) {
69     return "unmodifiable mismatch: " + left.unmodifiable +
70            " != " + right.unmodifiable;
71   }
72   return true;
75 function compareTrees(left, right, verbose) {
76   if (verbose) {
77     chrome.test.log(JSON.stringify(left) || "<null>");
78     chrome.test.log(JSON.stringify(right) || "<null>");
79   }
80   if (left == null && right == null) {
81     return true;
82   }
83   if (left == null || right == null)
84     return left + " != " + right;
85   if (left.length != right.length)
86     return "count mismatch: " + left.length + " != " + right.length;
87   for (var i = 0; i < left.length; i++) {
88     var result = compareNode(left[i], right[i]);
89     if (result !== true) {
90       chrome.test.log(result);
91       chrome.test.log(JSON.stringify(left, null, 2));
92       chrome.test.log(JSON.stringify(right, null, 2));
93       return result;
94     }
95     result = compareTrees(left[i].children, right[i].children);
96     if (result !== true)
97       return result;
98   }
99   return true;
102 // |expectedParent| is a child within the global |expected| that each node in
103 // the array|nodes| should be added to.  |callback| will be called when all of
104 // the nodes have been successfully created.
105 function createNodes(expectedParent, nodes, callback) {
106   function createNext() {
107     if (nodes.length) {
108       var node = nodes.shift();
109       chrome.bookmarks.create(node, function(results) {
110         node.id = results.id;
111         node.index = results.index;
112         expectedParent.children.push(node);
114         // Create each node a minimum of 1ms apart.  This ensures that each
115         // node will have a unique timestamp.
116         setTimeout(createNext, 1);
117       });
118     } else {
119       callback();
120     }
121   }
122   createNext();
125 // Calls getTree and verifies that the results match the global |expected|
126 // state.  Assigns over expected in the end since getTree has more data
127 // (e.g. createdDate) which tests may want to depend on.
128 function verifyTreeIsExpected(callback) {
129   chrome.bookmarks.getTree(pass(function(results) {
130     chrome.test.assertTrue(compareTrees(expected, results),
131                            "getTree() result != expected");
132     expected = results;
133     callback();
134   }));
137 function run() {
138 chrome.test.runTests([
139   function getTree() {
140     verifyTreeIsExpected(pass());
141   },
143   function get() {
144     chrome.bookmarks.get("1", pass(function(results) {
145       chrome.test.assertTrue(compareNode(results[0], expected[0].children[0]));
146     }));
147     chrome.bookmarks.get("6", pass(function(results) {
148       chrome.test.assertTrue(compareNode(
149           results[0], expected[0].children[2].children[0]));
150     }));
151     chrome.bookmarks.get("42", fail("Can't find bookmark for id."));
152   },
154   function getArray() {
155     chrome.bookmarks.get(["1", "2"], pass(function(results) {
156       chrome.test.assertTrue(compareNode(results[0], expected[0].children[0]),
157                              "get() result != expected");
158       chrome.test.assertTrue(compareNode(results[1], expected[0].children[1]),
159                              "get() result != expected");
160     }));
161   },
163   function getChildren() {
164     chrome.bookmarks.getChildren("0", pass(function(results) {
165       chrome.test.assertTrue(compareNode(results[0], expected[0].children[0]),
166                              "getChildren() result != expected");
167       chrome.test.assertTrue(compareNode(results[1], expected[0].children[1]),
168                              "getChildren() result != expected");
169     }));
170   },
172   function create() {
173     var node = {parentId:"1", title:"google", url:"http://www.google.com/"};
174     chrome.test.listenOnce(chrome.bookmarks.onCreated, function(id, created) {
175       node.id = created.id;
176       node.index = 0;
177       chrome.test.assertEq(id, node.id);
178       chrome.test.assertTrue(compareNode(node, created));
179     });
180     chrome.bookmarks.create(node, pass(function(results) {
181       node.id = results.id;  // since we couldn't know this going in
182       node.index = 0;
183       chrome.test.assertTrue(compareNode(node, results),
184                              "created node != source");
185       expected[0].children[0].children.push(node);
186     }));
187   },
189   function createNoParentId() {
190     var node = {title:"google", url:"http://www.google.com/"};
191     chrome.test.listenOnce(chrome.bookmarks.onCreated, function(id, created) {
192       node.id = created.id;
193       node.index = 0;
194       chrome.test.assertEq(id, node.id);
195       // Make sure the parentId defaults to the Other Bookmarks folder.
196       chrome.test.assertEq(expected[0].children[1].id, created.parentId);
197       chrome.test.assertTrue(compareNode(node, created));
198       expected[0].children[1].children.push(node);
199     });
200     chrome.bookmarks.create(node, pass(function(results) {
201       node.id = results.id;  // since we couldn't know this going in
202       node.index = 0;
203       chrome.test.assertTrue(compareNode(node, results),
204                              "created node != source");
205     }));
206   },
208   function createInRoot() {
209     const error = "Can't modify the root bookmark folders.";
210     var node = {parentId:"0", title:"g404", url:"http://www.google.com/404"};
211     chrome.bookmarks.create(node, fail(error));
212   },
214   function createInManaged() {
215     const error = "Can't modify managed bookmarks.";
216     var node = {parentId:"4", title:"g404", url:"http://www.google.com/404"};
217     chrome.bookmarks.create(node, fail(error));
218   },
220   function createFolder() {
221     var node = {parentId:"1", title:"foo bar"};  // folder
222     chrome.test.listenOnce(chrome.bookmarks.onCreated, function(id, created) {
223       node.id = created.id;
224       node.index = 1;
225       node.children = [];
226       chrome.test.assertTrue(compareNode(node, created));
227     });
228     chrome.bookmarks.create(node, pass(function(results) {
229       node.id = results.id;  // since we couldn't know this going in
230       node.index = 1;
231       node.children = [];
232       chrome.test.assertTrue(compareNode(node, results),
233                              "created node != source");
234       expected[0].children[0].children.push(node);
235     }));
236   },
238   function getSubTree() {
239     chrome.bookmarks.getSubTree(expected[0].children[0].id,
240         pass(function(results) {
241           chrome.test.assertTrue(compareTrees([expected[0].children[0]],
242               results), "getTree() result != expected");
243         }));
244   },
246   function moveSetup() {
247     createNodes(bookmarksBar(), [node1, node2, node3], pass(function() {
248       verifyTreeIsExpected(pass());
249     }));
250   },
252   function move() {
253     // Move node1, node2, and node3 from their current location (the bookmark
254     // bar) to be under the "foo bar" folder (created in createFolder()).
255     // Then move that folder to be under the "other bookmarks" folder.
256     var folder = expected[0].children[0].children[1];
257     var old_node1 = expected[0].children[0].children[2];
258     chrome.test.listenOnce(chrome.bookmarks.onMoved, function(id, moveInfo) {
259       chrome.test.assertEq(node1.id, id);
260       chrome.test.assertEq(moveInfo.parentId, folder.id);
261       chrome.test.assertEq(moveInfo.index, 0);
262       chrome.test.assertEq(moveInfo.oldParentId, old_node1.parentId);
263       chrome.test.assertEq(moveInfo.oldIndex, old_node1.index);
264     });
265     chrome.bookmarks.move(node1.id, {parentId:folder.id},
266                           pass(function(results) {
267       chrome.test.assertEq(results.parentId, folder.id);
268       node1.parentId = results.parentId;
269       node1.index = 0;
270     }));
271     chrome.bookmarks.move(node2.id, {parentId:folder.id},
272                           pass(function(results) {
273       chrome.test.assertEq(results.parentId, folder.id);
274       node2.parentId = results.parentId;
275       node2.index = 1;
276     }));
277     // Insert node3 at index 1 rather than at the end.  This should result in
278     // an order of node1, node3, node2.
279     chrome.bookmarks.move(node3.id, {parentId:folder.id, index:1},
280                           pass(function(results) {
281       chrome.test.assertEq(results.parentId, folder.id);
282       chrome.test.assertEq(results.index, 1);
283       node3.parentId = results.parentId;
284       node3.index = 1;
285       node2.index = 2;
287       // update expected to match
288       expected[0].children[0].children.pop();
289       expected[0].children[0].children.pop();
290       expected[0].children[0].children.pop();
291       folder.children.push(node1);
292       folder.children.push(node3);
293       folder.children.push(node2);
295       verifyTreeIsExpected(pass());
296     }));
298     // Move folder (and its children) to be a child of Other Bookmarks.
299     var other = expected[0].children[1];
300     chrome.bookmarks.move(folder.id, {parentId:other.id},
301                           pass(function(results) {
302       chrome.test.assertEq(results.parentId, other.id);
303       folder.parentId = results.parentId;
304       folder.index = results.index;
306       var folder2 = expected[0].children[0].children.pop();
307       chrome.test.assertEq(folder2.id, folder.id);
308       expected[0].children[1].children.push(folder2);
309       verifyTreeIsExpected(pass());
310     }));
311   },
313   function moveToManaged() {
314     var managed_node = expected[0].children[2];
315     chrome.test.assertEq("4", managed_node.id);
316     const error = "Can't modify managed bookmarks.";
317     chrome.bookmarks.move(node1.id, {parentId:managed_node.id}, fail(error));
318     verifyTreeIsExpected(pass());
319   },
321   function moveFromManaged() {
322     var managed_node = expected[0].children[2];
323     var moving_node = managed_node.children[0];
324     var other = expected[0].children[1];
325     const error = "Can't modify managed bookmarks.";
326     chrome.bookmarks.move(moving_node.id, {parentId:other.id}, fail(error));
327     verifyTreeIsExpected(pass());
328   },
330   function search() {
331     chrome.bookmarks.search("baz bar", pass(function(results) {
332       // matches node1 & node3
333       chrome.test.assertEq(2, results.length);
334     }));
335     chrome.bookmarks.search("www hello", pass(function(results) {
336       // matches node1 & node3
337       chrome.test.assertEq(2, results.length);
338     }));
339     chrome.bookmarks.search("bar example",
340                             pass(function(results) {
341       // matches node2
342       chrome.test.assertEq(1, results.length);
343     }));
344     chrome.bookmarks.search("foo bar", pass(function(results) {
345       // matches node3 & folder "foo bar" from createFolder
346       chrome.test.assertEq(2, results.length);
347     }));
348     chrome.bookmarks.search("quux", pass(function(results) {
349       // matches node2 & node1
350       chrome.test.assertEq(2, results.length);
351     }));
352     chrome.bookmarks.search("Bookmark Bar", pass(function(results) {
353       // Does not match any node since permanent nodes are stripped from search
354       chrome.test.assertEq(0, results.length);
355     }));
356     chrome.bookmarks.search("Managed", pass(function(results) {
357       // Matches the Managed Bookmark and the Managed Folder but not the
358       // managed_node.
359       chrome.test.assertEq(2, results.length);
360     }));
361   },
363   function update() {
364     var title = "hello world";
365     chrome.test.listenOnce(chrome.bookmarks.onChanged, function(id, changes) {
366       chrome.test.assertEq(title, changes.title);
367     });
368     chrome.bookmarks.update(node1.id, {"title": title}, pass(function(results) {
369       chrome.test.assertEq(title, results.title);
370     }));
372     var url = "http://example.com/hello";
373     chrome.bookmarks.update(node1.id, {"url": url}, pass(function(results) {
374       // Make sure that leaving out the title does not set the title to empty.
375       chrome.test.assertEq(title, results.title);
376       chrome.test.assertEq(url, results.url);
378       // Empty or invalid URLs should not change the URL.
379       var bad_url = "";
380       chrome.bookmarks.update(node1.id, {"url": bad_url},
381         pass(function(results) {
382           chrome.bookmarks.get(node1.id, pass(function(results) {
383             chrome.test.assertEq(url, results[0].url);
384             chrome.test.log("URL UNCHANGED");
385           }));
386         })
387       );
389       // Invalid URLs also generate an error.
390       bad_url = "I am not an URL";
391       chrome.bookmarks.update(node1.id, {"url": bad_url}, fail("Invalid URL.",
392         function(results) {
393           chrome.bookmarks.get(node1.id, pass(function(results) {
394             chrome.test.assertEq(url, results[0].url);
395             chrome.test.log("URL UNCHANGED");
396           }));
397         })
398       );
399     }));
400   },
402   function updateManaged() {
403     var managed_node = expected[0].children[2];
404     var updating_node = managed_node.children[0];
405     const error = "Can't modify managed bookmarks.";
406     chrome.bookmarks.update(updating_node.id, {"title": "New"}, fail(error));
407   },
409   function remove() {
410     var parentId = node1.parentId;
411     chrome.test.listenOnce(chrome.bookmarks.onRemoved,
412                            function(id, removeInfo) {
413       chrome.test.assertEq(id, node1.id);
414       chrome.test.assertEq(removeInfo.parentId, parentId);
415       chrome.test.assertEq(removeInfo.index, node1.index);
416     });
417     chrome.bookmarks.remove(node1.id, pass(function() {
418       // Update expected to match.
419       // We removed node1, which means that the index of the other two nodes
420       // changes as well.
421       expected[0].children[1].children[1].children.shift();
422       expected[0].children[1].children[1].children[0].index = 0;
423       expected[0].children[1].children[1].children[1].index = 1;
424       verifyTreeIsExpected(pass());
425     }));
426   },
428   function removeManaged() {
429     var managed_node = expected[0].children[2];
430     var removing_node = managed_node.children[0];
431     const error = "Can't modify managed bookmarks.";
432     chrome.bookmarks.remove(removing_node.id, fail(error));
433   },
435   function searchRemoved() {
436       // Search for deleted node
437       chrome.bookmarks.search("baz bar", pass(function(results) {
438         // matches only node3 since node1 was removed
439         chrome.test.assertEq(1, results.length);
440       }));
441   },
443   function removeTree() {
444     var parentId = node2.parentId;
445     var folder = expected[0].children[1].children[1];
446     chrome.test.listenOnce(chrome.bookmarks.onRemoved,
447                            function(id, removeInfo) {
448       chrome.test.assertEq(id, folder.id);
449       chrome.test.assertEq(removeInfo.parentId, folder.parentId);
450       chrome.test.assertEq(removeInfo.index, folder.index);
451     });
452     chrome.bookmarks.removeTree(parentId, pass(function(){
453       // Update expected to match.
454       expected[0].children[1].children.pop();
455       verifyTreeIsExpected(pass());
456     }));
457   },
459   function removeManagedTree() {
460     var managed_node = expected[0].children[2];
461     var managed_folder = managed_node.children[1];
462     const error = "Can't modify managed bookmarks.";
463     chrome.bookmarks.removeTree(managed_folder.id, fail(error));
464   },
466   function searchRemovedTree() {
467     // Search for deleted folder and enclosed node3
468     chrome.bookmarks.search("foo bar", pass(function(results) {
469       // Does not match anything since folder was removed with node3 in it
470       chrome.test.assertEq(0, results.length);
471     }));
472   },
474   function getRecentSetup() {
475     // Clean up tree
476     ["1", "2"].forEach(function(id) {
477       chrome.bookmarks.getChildren(id, pass(function(children) {
478         children.forEach(function(child, i) {
479           chrome.bookmarks.removeTree(child.id, pass(function() {}));
480           // When we have removed the last child we can continue.
481           if (id == "2" && i == children.length - 1)
482             afterRemove();
483         });
484       }));
485     });
487     function afterRemove() {
488       // Once done add 3 nodes
489       chrome.bookmarks.getTree(pass(function(results) {
490         chrome.test.assertEq(0, results[0].children[0].children.length);
491         chrome.test.assertEq(0, results[0].children[1].children.length);
492         expected = results;
494         // Reset the nodes
495         node1 = {parentId:"1", title:"bar baz",
496                  url:"http://www.example.com/hello"};
497         node2 = {parentId:"1", title:"foo quux",
498                  url:"http://www.example.com/bar"};
499         node3 = {parentId:"1", title:"Foo bar baz",
500                   url:"http://www.google.com/hello/quux"};
501         createNodes(bookmarksBar(), [node1, node2, node3], pass(function() {
502           verifyTreeIsExpected(pass());
503         }));
504       }));
505     }
506   },
508   function getRecent() {
509     var failed = false;
510     try {
511       chrome.bookmarks.getRecent(0, function() {});
512     } catch (ex) {
513       failed = true;
514     }
515     chrome.test.assertTrue(failed, "Calling with 0 should fail");
517     chrome.bookmarks.getRecent(10000, pass(function(results) {
518       // Should include the "Managed Bookmark" and "Supervised Bookmark".
519       chrome.test.assertEq(5, results.length,
520                            "Should have gotten all recent bookmarks");
521     }));
523     chrome.bookmarks.getRecent(2, pass(function(results) {
524       chrome.test.assertEq(2, results.length,
525                            "Should only get the last 2 bookmarks");
527       chrome.test.assertTrue(compareNode(node3, results[0]));
528       chrome.test.assertTrue(compareNode(node2, results[1]));
529     }));
530   },
532   function updateFolder() {
533     chrome.bookmarks.create({title: 'folder'}, function(folder) {
534       var newTitle = 'changedFolder';
535       chrome.test.listenOnce(chrome.bookmarks.onChanged, pass(
536           function(id, changes) {
537         chrome.test.assertEq(folder.id, id);
538         chrome.test.assertEq(newTitle, changes.title);
539         chrome.test.assertFalse('url' in changes);
540       }));
542       chrome.bookmarks.update(folder.id, {title: newTitle}, pass(
543           function(result) {
544         chrome.test.assertEq(newTitle, result.title);
545         chrome.test.assertFalse('url' in result)
546       }));
547     });
548   }
552 run();