Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / bookmarks / bookmark_utils_unittest.cc
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.
4
5 #include "components/bookmarks/core/browser/bookmark_utils.h"
6
7 #include <vector>
8
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "components/bookmarks/core/browser/base_bookmark_model_observer.h"
12 #include "components/bookmarks/core/browser/bookmark_model.h"
13 #include "components/bookmarks/core/browser/bookmark_node_data.h"
14 #include "components/bookmarks/core/test/test_bookmark_client.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/base/clipboard/clipboard.h"
17 #include "ui/base/clipboard/scoped_clipboard_writer.h"
18
19 using base::ASCIIToUTF16;
20 using std::string;
21
22 namespace bookmark_utils {
23 namespace {
24
25 class BookmarkUtilsTest : public testing::Test,
26                           public BaseBookmarkModelObserver {
27  public:
28   BookmarkUtilsTest()
29       : grouped_changes_beginning_count_(0),
30         grouped_changes_ended_count_(0) {}
31   virtual ~BookmarkUtilsTest() {}
32
33 // Copy and paste is not yet supported on iOS. http://crbug.com/228147
34 #if !defined(OS_IOS)
35   virtual void TearDown() OVERRIDE {
36     ui::Clipboard::DestroyClipboardForCurrentThread();
37   }
38 #endif  // !defined(OS_IOS)
39
40   // Certain user actions require multiple changes to the bookmark model,
41   // however these modifications need to be atomic for the undo framework. The
42   // BaseBookmarkModelObserver is used to inform the boundaries of the user
43   // action. For example, when multiple bookmarks are cut to the clipboard we
44   // expect one call each to GroupedBookmarkChangesBeginning/Ended.
45   void ExpectGroupedChangeCount(int expected_beginning_count,
46                                 int expected_ended_count) {
47     // The undo framework is not used under Android.  Thus the group change
48     // events will not be fired and so should not be tested for Android.
49 #if !defined(OS_ANDROID)
50     EXPECT_EQ(grouped_changes_beginning_count_, expected_beginning_count);
51     EXPECT_EQ(grouped_changes_ended_count_, expected_ended_count);
52 #endif
53   }
54
55  private:
56   // BaseBookmarkModelObserver:
57   virtual void BookmarkModelChanged() OVERRIDE {}
58
59   virtual void GroupedBookmarkChangesBeginning(BookmarkModel* model) OVERRIDE {
60     ++grouped_changes_beginning_count_;
61   }
62
63   virtual void GroupedBookmarkChangesEnded(BookmarkModel* model) OVERRIDE {
64     ++grouped_changes_ended_count_;
65   }
66
67   int grouped_changes_beginning_count_;
68   int grouped_changes_ended_count_;
69
70   // Clipboard requires a message loop.
71   base::MessageLoopForUI loop_;
72
73   DISALLOW_COPY_AND_ASSIGN(BookmarkUtilsTest);
74 };
75
76 TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesWordPhraseQuery) {
77   test::TestBookmarkClient client;
78   scoped_ptr<BookmarkModel> model(client.CreateModel(false));
79   const BookmarkNode* node1 = model->AddURL(model->other_node(),
80                                             0,
81                                             ASCIIToUTF16("foo bar"),
82                                             GURL("http://www.google.com"));
83   const BookmarkNode* node2 = model->AddURL(model->other_node(),
84                                             0,
85                                             ASCIIToUTF16("baz buz"),
86                                             GURL("http://www.cnn.com"));
87   const BookmarkNode* folder1 =
88       model->AddFolder(model->other_node(), 0, ASCIIToUTF16("foo"));
89   std::vector<const BookmarkNode*> nodes;
90   QueryFields query;
91   query.word_phrase_query.reset(new base::string16);
92   // No nodes are returned for empty string.
93   *query.word_phrase_query = ASCIIToUTF16("");
94   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
95   EXPECT_TRUE(nodes.empty());
96   nodes.clear();
97
98   // No nodes are returned for space-only string.
99   *query.word_phrase_query = ASCIIToUTF16("   ");
100   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
101   EXPECT_TRUE(nodes.empty());
102   nodes.clear();
103
104   // Node "foo bar" and folder "foo" are returned in search results.
105   *query.word_phrase_query = ASCIIToUTF16("foo");
106   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
107   ASSERT_EQ(2U, nodes.size());
108   EXPECT_TRUE(nodes[0] == folder1);
109   EXPECT_TRUE(nodes[1] == node1);
110   nodes.clear();
111
112   // Ensure url matches return in search results.
113   *query.word_phrase_query = ASCIIToUTF16("cnn");
114   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
115   ASSERT_EQ(1U, nodes.size());
116   EXPECT_TRUE(nodes[0] == node2);
117   nodes.clear();
118
119   // Ensure folder "foo" is not returned in more specific search.
120   *query.word_phrase_query = ASCIIToUTF16("foo bar");
121   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
122   ASSERT_EQ(1U, nodes.size());
123   EXPECT_TRUE(nodes[0] == node1);
124   nodes.clear();
125
126   // Bookmark Bar and Other Bookmarks are not returned in search results.
127   *query.word_phrase_query = ASCIIToUTF16("Bookmark");
128   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
129   ASSERT_EQ(0U, nodes.size());
130   nodes.clear();
131 }
132
133 // Check exact matching against a URL query.
134 TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesUrl) {
135   test::TestBookmarkClient client;
136   scoped_ptr<BookmarkModel> model(client.CreateModel(false));
137   const BookmarkNode* node1 = model->AddURL(model->other_node(),
138                                             0,
139                                             ASCIIToUTF16("Google"),
140                                             GURL("https://www.google.com/"));
141   model->AddURL(model->other_node(),
142                 0,
143                 ASCIIToUTF16("Google Calendar"),
144                 GURL("https://www.google.com/calendar"));
145
146   model->AddFolder(model->other_node(), 0, ASCIIToUTF16("Folder"));
147
148   std::vector<const BookmarkNode*> nodes;
149   QueryFields query;
150   query.url.reset(new base::string16);
151   *query.url = ASCIIToUTF16("https://www.google.com/");
152   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
153   ASSERT_EQ(1U, nodes.size());
154   EXPECT_TRUE(nodes[0] == node1);
155   nodes.clear();
156
157   *query.url = ASCIIToUTF16("calendar");
158   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
159   ASSERT_EQ(0U, nodes.size());
160   nodes.clear();
161
162   // Empty URL should not match folders.
163   *query.url = ASCIIToUTF16("");
164   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
165   ASSERT_EQ(0U, nodes.size());
166   nodes.clear();
167 }
168
169 // Check exact matching against a title query.
170 TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesTitle) {
171   test::TestBookmarkClient client;
172   scoped_ptr<BookmarkModel> model(client.CreateModel(false));
173   const BookmarkNode* node1 = model->AddURL(model->other_node(),
174                                             0,
175                                             ASCIIToUTF16("Google"),
176                                             GURL("https://www.google.com/"));
177   model->AddURL(model->other_node(),
178                 0,
179                 ASCIIToUTF16("Google Calendar"),
180                 GURL("https://www.google.com/calendar"));
181
182   const BookmarkNode* folder1 =
183       model->AddFolder(model->other_node(), 0, ASCIIToUTF16("Folder"));
184
185   std::vector<const BookmarkNode*> nodes;
186   QueryFields query;
187   query.title.reset(new base::string16);
188   *query.title = ASCIIToUTF16("Google");
189   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
190   ASSERT_EQ(1U, nodes.size());
191   EXPECT_TRUE(nodes[0] == node1);
192   nodes.clear();
193
194   *query.title = ASCIIToUTF16("Calendar");
195   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
196   ASSERT_EQ(0U, nodes.size());
197   nodes.clear();
198
199   // Title should match folders.
200   *query.title = ASCIIToUTF16("Folder");
201   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
202   ASSERT_EQ(1U, nodes.size());
203   EXPECT_TRUE(nodes[0] == folder1);
204   nodes.clear();
205 }
206
207 // Check matching against a query with multiple predicates.
208 TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesConjunction) {
209   test::TestBookmarkClient client;
210   scoped_ptr<BookmarkModel> model(client.CreateModel(false));
211   const BookmarkNode* node1 = model->AddURL(model->other_node(),
212                                             0,
213                                             ASCIIToUTF16("Google"),
214                                             GURL("https://www.google.com/"));
215   model->AddURL(model->other_node(),
216                 0,
217                 ASCIIToUTF16("Google Calendar"),
218                 GURL("https://www.google.com/calendar"));
219
220   model->AddFolder(model->other_node(), 0, ASCIIToUTF16("Folder"));
221
222   std::vector<const BookmarkNode*> nodes;
223   QueryFields query;
224
225   // Test all fields matching.
226   query.word_phrase_query.reset(new base::string16(ASCIIToUTF16("www")));
227   query.url.reset(new base::string16(ASCIIToUTF16("https://www.google.com/")));
228   query.title.reset(new base::string16(ASCIIToUTF16("Google")));
229   GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
230   ASSERT_EQ(1U, nodes.size());
231   EXPECT_TRUE(nodes[0] == node1);
232   nodes.clear();
233
234   scoped_ptr<base::string16>* fields[] = {
235     &query.word_phrase_query, &query.url, &query.title };
236
237   // Test two fields matching.
238   for (size_t i = 0; i < arraysize(fields); i++) {
239     scoped_ptr<base::string16> original_value(fields[i]->release());
240     GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
241     ASSERT_EQ(1U, nodes.size());
242     EXPECT_TRUE(nodes[0] == node1);
243     nodes.clear();
244     fields[i]->reset(original_value.release());
245   }
246
247   // Test two fields matching with one non-matching field.
248   for (size_t i = 0; i < arraysize(fields); i++) {
249     scoped_ptr<base::string16> original_value(fields[i]->release());
250     fields[i]->reset(new base::string16(ASCIIToUTF16("fjdkslafjkldsa")));
251     GetBookmarksMatchingProperties(model.get(), query, 100, string(), &nodes);
252     ASSERT_EQ(0U, nodes.size());
253     nodes.clear();
254     fields[i]->reset(original_value.release());
255   }
256 }
257
258 // Copy and paste is not yet supported on iOS. http://crbug.com/228147
259 #if !defined(OS_IOS)
260 TEST_F(BookmarkUtilsTest, CopyPaste) {
261   test::TestBookmarkClient client;
262   scoped_ptr<BookmarkModel> model(client.CreateModel(false));
263   const BookmarkNode* node = model->AddURL(model->other_node(),
264                                            0,
265                                            ASCIIToUTF16("foo bar"),
266                                            GURL("http://www.google.com"));
267
268   // Copy a node to the clipboard.
269   std::vector<const BookmarkNode*> nodes;
270   nodes.push_back(node);
271   CopyToClipboard(model.get(), nodes, false);
272
273   // And make sure we can paste a bookmark from the clipboard.
274   EXPECT_TRUE(CanPasteFromClipboard(model->bookmark_bar_node()));
275
276   // Write some text to the clipboard.
277   {
278     ui::ScopedClipboardWriter clipboard_writer(
279         ui::Clipboard::GetForCurrentThread(),
280         ui::CLIPBOARD_TYPE_COPY_PASTE);
281     clipboard_writer.WriteText(ASCIIToUTF16("foo"));
282   }
283
284   // Now we shouldn't be able to paste from the clipboard.
285   EXPECT_FALSE(CanPasteFromClipboard(model->bookmark_bar_node()));
286 }
287
288 TEST_F(BookmarkUtilsTest, CutToClipboard) {
289   test::TestBookmarkClient client;
290   scoped_ptr<BookmarkModel> model(client.CreateModel(false));
291   model->AddObserver(this);
292
293   base::string16 title(ASCIIToUTF16("foo"));
294   GURL url("http://foo.com");
295   const BookmarkNode* n1 = model->AddURL(model->other_node(), 0, title, url);
296   const BookmarkNode* n2 = model->AddURL(model->other_node(), 1, title, url);
297
298   // Cut the nodes to the clipboard.
299   std::vector<const BookmarkNode*> nodes;
300   nodes.push_back(n1);
301   nodes.push_back(n2);
302   CopyToClipboard(model.get(), nodes, true);
303
304   // Make sure the nodes were removed.
305   EXPECT_EQ(0, model->other_node()->child_count());
306
307   // Make sure observers were notified the set of changes should be grouped.
308   ExpectGroupedChangeCount(1, 1);
309
310   // And make sure we can paste from the clipboard.
311   EXPECT_TRUE(CanPasteFromClipboard(model->other_node()));
312 }
313 #endif  // !defined(OS_IOS)
314
315 TEST_F(BookmarkUtilsTest, GetParentForNewNodes) {
316   test::TestBookmarkClient client;
317   scoped_ptr<BookmarkModel> model(client.CreateModel(false));
318   // This tests the case where selection contains one item and that item is a
319   // folder.
320   std::vector<const BookmarkNode*> nodes;
321   nodes.push_back(model->bookmark_bar_node());
322   int index = -1;
323   const BookmarkNode* real_parent =
324       GetParentForNewNodes(model->bookmark_bar_node(), nodes, &index);
325   EXPECT_EQ(real_parent, model->bookmark_bar_node());
326   EXPECT_EQ(0, index);
327
328   nodes.clear();
329
330   // This tests the case where selection contains one item and that item is an
331   // url.
332   const BookmarkNode* page1 = model->AddURL(model->bookmark_bar_node(),
333                                             0,
334                                             ASCIIToUTF16("Google"),
335                                             GURL("http://google.com"));
336   nodes.push_back(page1);
337   real_parent = GetParentForNewNodes(model->bookmark_bar_node(), nodes, &index);
338   EXPECT_EQ(real_parent, model->bookmark_bar_node());
339   EXPECT_EQ(1, index);
340
341   // This tests the case where selection has more than one item.
342   const BookmarkNode* folder1 =
343       model->AddFolder(model->bookmark_bar_node(), 1, ASCIIToUTF16("Folder 1"));
344   nodes.push_back(folder1);
345   real_parent = GetParentForNewNodes(model->bookmark_bar_node(), nodes, &index);
346   EXPECT_EQ(real_parent, model->bookmark_bar_node());
347   EXPECT_EQ(2, index);
348
349   // This tests the case where selection doesn't contain any items.
350   nodes.clear();
351   real_parent = GetParentForNewNodes(model->bookmark_bar_node(), nodes, &index);
352   EXPECT_EQ(real_parent, model->bookmark_bar_node());
353   EXPECT_EQ(2, index);
354 }
355
356 // Verifies that meta info is copied when nodes are cloned.
357 TEST_F(BookmarkUtilsTest, CloneMetaInfo) {
358   test::TestBookmarkClient client;
359   scoped_ptr<BookmarkModel> model(client.CreateModel(false));
360   // Add a node containing meta info.
361   const BookmarkNode* node = model->AddURL(model->other_node(),
362                                            0,
363                                            ASCIIToUTF16("foo bar"),
364                                            GURL("http://www.google.com"));
365   model->SetNodeMetaInfo(node, "somekey", "somevalue");
366   model->SetNodeMetaInfo(node, "someotherkey", "someothervalue");
367
368   // Clone node to a different folder.
369   const BookmarkNode* folder =
370       model->AddFolder(model->bookmark_bar_node(), 0, ASCIIToUTF16("Folder"));
371   std::vector<BookmarkNodeData::Element> elements;
372   BookmarkNodeData::Element node_data(node);
373   elements.push_back(node_data);
374   EXPECT_EQ(0, folder->child_count());
375   CloneBookmarkNode(model.get(), elements, folder, 0, false);
376   ASSERT_EQ(1, folder->child_count());
377
378   // Verify that the cloned node contains the same meta info.
379   const BookmarkNode* clone = folder->GetChild(0);
380   ASSERT_TRUE(clone->GetMetaInfoMap());
381   EXPECT_EQ(2u, clone->GetMetaInfoMap()->size());
382   std::string value;
383   EXPECT_TRUE(clone->GetMetaInfo("somekey", &value));
384   EXPECT_EQ("somevalue", value);
385   EXPECT_TRUE(clone->GetMetaInfo("someotherkey", &value));
386   EXPECT_EQ("someothervalue", value);
387 }
388
389 }  // namespace
390 }  // namespace bookmark_utils