Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / bookmarks / bookmark_editor_view_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 "chrome/browser/ui/views/bookmarks/bookmark_editor_view.h"
6
7 #include <string>
8
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "components/bookmarks/browser/bookmark_model.h"
16 #include "components/bookmarks/test/bookmark_test_helpers.h"
17 #include "content/public/test/test_browser_thread.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "ui/views/controls/textfield/textfield.h"
20 #include "ui/views/controls/tree/tree_view.h"
21
22 using base::ASCIIToUTF16;
23 using base::UTF8ToUTF16;
24 using base::Time;
25 using base::TimeDelta;
26 using content::BrowserThread;
27
28 // Base class for bookmark editor tests. Creates a BookmarkModel and populates
29 // it with test data.
30 class BookmarkEditorViewTest : public testing::Test {
31  public:
32   BookmarkEditorViewTest()
33       : ui_thread_(BrowserThread::UI, &message_loop_),
34         file_thread_(BrowserThread::FILE, &message_loop_),
35         model_(NULL) {
36   }
37
38   void SetUp() override {
39     profile_.reset(new TestingProfile());
40     profile_->CreateBookmarkModel(true);
41
42     model_ = BookmarkModelFactory::GetForProfile(profile_.get());
43     bookmarks::test::WaitForBookmarkModelToLoad(model_);
44
45     AddTestData();
46   }
47
48   void TearDown() override {}
49
50  protected:
51   std::string base_path() const { return "file:///c:/tmp/"; }
52
53   const BookmarkNode* GetNode(const std::string& name) {
54     return model_->GetMostRecentlyAddedUserNodeForURL(GURL(base_path() + name));
55   }
56
57   BookmarkNode* GetMutableNode(const std::string& name) {
58     return const_cast<BookmarkNode*>(GetNode(name));
59   }
60
61   BookmarkEditorView::EditorTreeModel* editor_tree_model() {
62     return editor_->tree_model_.get();
63   }
64
65   void CreateEditor(Profile* profile,
66                     const BookmarkNode* parent,
67                     const BookmarkEditor::EditDetails& details,
68                     BookmarkEditor::Configuration configuration) {
69     editor_.reset(new BookmarkEditorView(profile, parent, details,
70                                          configuration));
71   }
72
73   void SetTitleText(const base::string16& title) {
74     editor_->title_tf_->SetText(title);
75   }
76
77   void SetURLText(const base::string16& text) {
78     if (editor_->details_.type != BookmarkEditor::EditDetails::NEW_FOLDER)
79       editor_->url_tf_->SetText(text);
80   }
81
82   void ApplyEdits() {
83     editor_->ApplyEdits();
84   }
85
86   void ApplyEdits(BookmarkEditorView::EditorNode* node) {
87     editor_->ApplyEdits(node);
88   }
89
90   BookmarkEditorView::EditorNode* AddNewFolder(
91       BookmarkEditorView::EditorNode* parent) {
92     return editor_->AddNewFolder(parent);
93   }
94
95   void NewFolder() {
96     return editor_->NewFolder();
97   }
98
99   bool URLTFHasParent() {
100     if (editor_->details_.type == BookmarkEditor::EditDetails::NEW_FOLDER)
101       return false;
102     return editor_->url_tf_->parent();
103   }
104
105   void ExpandAndSelect() {
106     editor_->ExpandAndSelect();
107   }
108
109   views::TreeView* tree_view() { return editor_->tree_view_; }
110
111   base::MessageLoopForUI message_loop_;
112   content::TestBrowserThread ui_thread_;
113   content::TestBrowserThread file_thread_;
114
115   BookmarkModel* model_;
116   scoped_ptr<TestingProfile> profile_;
117
118  private:
119   // Creates the following structure:
120   // bookmark bar node
121   //   a
122   //   F1
123   //    f1a
124   //    F11
125   //     f11a
126   //   F2
127   // other node
128   //   oa
129   //   OF1
130   //     of1a
131   void AddTestData() {
132     const BookmarkNode* bb_node = model_->bookmark_bar_node();
133     std::string test_base = base_path();
134     model_->AddURL(bb_node, 0, ASCIIToUTF16("a"), GURL(test_base + "a"));
135     const BookmarkNode* f1 = model_->AddFolder(bb_node, 1, ASCIIToUTF16("F1"));
136     model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
137     const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
138     model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
139     model_->AddFolder(bb_node, 2, ASCIIToUTF16("F2"));
140
141     // Children of the other node.
142     model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
143                    GURL(test_base + "oa"));
144     const BookmarkNode* of1 =
145         model_->AddFolder(model_->other_node(), 1, ASCIIToUTF16("OF1"));
146     model_->AddURL(of1, 0, ASCIIToUTF16("of1a"), GURL(test_base + "of1a"));
147   }
148
149   scoped_ptr<BookmarkEditorView> editor_;
150 };
151
152 // Makes sure the tree model matches that of the bookmark bar model.
153 TEST_F(BookmarkEditorViewTest, ModelsMatch) {
154   CreateEditor(profile_.get(), NULL,
155                BookmarkEditor::EditDetails::AddNodeInFolder(
156                    NULL, -1, GURL(), base::string16()),
157                BookmarkEditorView::SHOW_TREE);
158   BookmarkEditorView::EditorNode* editor_root = editor_tree_model()->GetRoot();
159   // The root should have two or three children: bookmark bar, other bookmarks
160   // and conditionally mobile bookmarks.
161   if (model_->mobile_node()->IsVisible()) {
162     ASSERT_EQ(3, editor_root->child_count());
163   } else {
164     ASSERT_EQ(2, editor_root->child_count());
165   }
166
167   BookmarkEditorView::EditorNode* bb_node = editor_root->GetChild(0);
168   // The root should have 2 nodes: folder F1 and F2.
169   ASSERT_EQ(2, bb_node->child_count());
170   ASSERT_EQ(ASCIIToUTF16("F1"), bb_node->GetChild(0)->GetTitle());
171   ASSERT_EQ(ASCIIToUTF16("F2"), bb_node->GetChild(1)->GetTitle());
172
173   // F1 should have one child, F11
174   ASSERT_EQ(1, bb_node->GetChild(0)->child_count());
175   ASSERT_EQ(ASCIIToUTF16("F11"), bb_node->GetChild(0)->GetChild(0)->GetTitle());
176
177   BookmarkEditorView::EditorNode* other_node = editor_root->GetChild(1);
178   // Other node should have one child (OF1).
179   ASSERT_EQ(1, other_node->child_count());
180   ASSERT_EQ(ASCIIToUTF16("OF1"), other_node->GetChild(0)->GetTitle());
181 }
182
183 // Changes the title and makes sure parent/visual order doesn't change.
184 TEST_F(BookmarkEditorViewTest, EditTitleKeepsPosition) {
185   CreateEditor(profile_.get(), NULL,
186                BookmarkEditor::EditDetails::EditNode(GetNode("a")),
187                BookmarkEditorView::SHOW_TREE);
188   SetTitleText(ASCIIToUTF16("new_a"));
189
190   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0));
191
192   const BookmarkNode* bb_node =
193       BookmarkModelFactory::GetForProfile(profile_.get())->bookmark_bar_node();
194   ASSERT_EQ(ASCIIToUTF16("new_a"), bb_node->GetChild(0)->GetTitle());
195   // The URL shouldn't have changed.
196   ASSERT_TRUE(GURL(base_path() + "a") == bb_node->GetChild(0)->url());
197 }
198
199 // Changes the url and makes sure parent/visual order doesn't change.
200 TEST_F(BookmarkEditorViewTest, EditURLKeepsPosition) {
201   Time node_time = Time::Now() + TimeDelta::FromDays(2);
202   GetMutableNode("a")->set_date_added(node_time);
203   CreateEditor(profile_.get(), NULL,
204                BookmarkEditor::EditDetails::EditNode(GetNode("a")),
205                BookmarkEditorView::SHOW_TREE);
206
207   SetURLText(UTF8ToUTF16(GURL(base_path() + "new_a").spec()));
208
209   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0));
210
211   const BookmarkNode* bb_node =
212       BookmarkModelFactory::GetForProfile(profile_.get())->bookmark_bar_node();
213   ASSERT_EQ(ASCIIToUTF16("a"), bb_node->GetChild(0)->GetTitle());
214   // The URL should have changed.
215   ASSERT_TRUE(GURL(base_path() + "new_a") == bb_node->GetChild(0)->url());
216   ASSERT_TRUE(node_time == bb_node->GetChild(0)->date_added());
217 }
218
219 // Moves 'a' to be a child of the other node.
220 TEST_F(BookmarkEditorViewTest, ChangeParent) {
221   CreateEditor(profile_.get(), NULL,
222                BookmarkEditor::EditDetails::EditNode(GetNode("a")),
223                BookmarkEditorView::SHOW_TREE);
224
225   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1));
226
227   const BookmarkNode* other_node =
228       BookmarkModelFactory::GetForProfile(profile_.get())->other_node();
229   ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
230   ASSERT_TRUE(GURL(base_path() + "a") == other_node->GetChild(2)->url());
231 }
232
233 // Moves 'a' to be a child of the other node and changes its url to new_a.
234 TEST_F(BookmarkEditorViewTest, ChangeParentAndURL) {
235   Time node_time = Time::Now() + TimeDelta::FromDays(2);
236   GetMutableNode("a")->set_date_added(node_time);
237   CreateEditor(profile_.get(), NULL,
238                BookmarkEditor::EditDetails::EditNode(GetNode("a")),
239                BookmarkEditorView::SHOW_TREE);
240
241   SetURLText(UTF8ToUTF16(GURL(base_path() + "new_a").spec()));
242
243   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1));
244
245   const BookmarkNode* other_node =
246       BookmarkModelFactory::GetForProfile(profile_.get())->other_node();
247   ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
248   ASSERT_TRUE(GURL(base_path() + "new_a") == other_node->GetChild(2)->url());
249   ASSERT_TRUE(node_time == other_node->GetChild(2)->date_added());
250 }
251
252 // Creates a new folder and moves a node to it.
253 TEST_F(BookmarkEditorViewTest, MoveToNewParent) {
254   CreateEditor(profile_.get(), NULL,
255                BookmarkEditor::EditDetails::EditNode(GetNode("a")),
256                BookmarkEditorView::SHOW_TREE);
257
258   // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21".
259   BookmarkEditorView::EditorNode* f2 =
260       editor_tree_model()->GetRoot()->GetChild(0)->GetChild(1);
261   BookmarkEditorView::EditorNode* f21 = AddNewFolder(f2);
262   f21->SetTitle(ASCIIToUTF16("F21"));
263   BookmarkEditorView::EditorNode* f211 = AddNewFolder(f21);
264   f211->SetTitle(ASCIIToUTF16("F211"));
265
266   // Parent the node to "F21".
267   ApplyEdits(f2);
268
269   const BookmarkNode* bb_node =
270       BookmarkModelFactory::GetForProfile(profile_.get())->bookmark_bar_node();
271   const BookmarkNode* mf2 = bb_node->GetChild(1);
272
273   // F2 in the model should have two children now: F21 and the node edited.
274   ASSERT_EQ(2, mf2->child_count());
275   // F21 should be first.
276   ASSERT_EQ(ASCIIToUTF16("F21"), mf2->GetChild(0)->GetTitle());
277   // Then a.
278   ASSERT_EQ(ASCIIToUTF16("a"), mf2->GetChild(1)->GetTitle());
279
280   // F21 should have one child, F211.
281   const BookmarkNode* mf21 = mf2->GetChild(0);
282   ASSERT_EQ(1, mf21->child_count());
283   ASSERT_EQ(ASCIIToUTF16("F211"), mf21->GetChild(0)->GetTitle());
284 }
285
286 // Brings up the editor, creating a new URL on the bookmark bar.
287 TEST_F(BookmarkEditorViewTest, NewURL) {
288   const BookmarkNode* bb_node =
289       BookmarkModelFactory::GetForProfile(profile_.get())->bookmark_bar_node();
290
291   CreateEditor(profile_.get(), bb_node,
292                BookmarkEditor::EditDetails::AddNodeInFolder(
293                    bb_node, 1, GURL(), base::string16()),
294                BookmarkEditorView::SHOW_TREE);
295
296   SetURLText(UTF8ToUTF16(GURL(base_path() + "a").spec()));
297   SetTitleText(ASCIIToUTF16("new_a"));
298
299   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0));
300
301   ASSERT_EQ(4, bb_node->child_count());
302
303   const BookmarkNode* new_node = bb_node->GetChild(1);
304
305   EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
306   EXPECT_TRUE(GURL(base_path() + "a") == new_node->url());
307 }
308
309 // Brings up the editor with no tree and modifies the url.
310 TEST_F(BookmarkEditorViewTest, ChangeURLNoTree) {
311   CreateEditor(profile_.get(), NULL,
312                BookmarkEditor::EditDetails::EditNode(
313                  model_->other_node()->GetChild(0)),
314                BookmarkEditorView::NO_TREE);
315
316   SetURLText(UTF8ToUTF16(GURL(base_path() + "a").spec()));
317   SetTitleText(ASCIIToUTF16("new_a"));
318
319   ApplyEdits(NULL);
320
321   const BookmarkNode* other_node =
322       BookmarkModelFactory::GetForProfile(profile_.get())->other_node();
323   ASSERT_EQ(2, other_node->child_count());
324
325   const BookmarkNode* new_node = other_node->GetChild(0);
326
327   EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
328   EXPECT_TRUE(GURL(base_path() + "a") == new_node->url());
329 }
330
331 // Brings up the editor with no tree and modifies only the title.
332 TEST_F(BookmarkEditorViewTest, ChangeTitleNoTree) {
333   CreateEditor(profile_.get(), NULL,
334                BookmarkEditor::EditDetails::EditNode(
335                  model_->other_node()->GetChild(0)),
336                BookmarkEditorView::NO_TREE);
337
338   SetTitleText(ASCIIToUTF16("new_a"));
339
340   ApplyEdits(NULL);
341
342   const BookmarkNode* other_node =
343       BookmarkModelFactory::GetForProfile(profile_.get())->other_node();
344   ASSERT_EQ(2, other_node->child_count());
345
346   const BookmarkNode* new_node = other_node->GetChild(0);
347
348   EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
349 }
350
351 // Creates a new folder.
352 TEST_F(BookmarkEditorViewTest, NewFolder) {
353   const BookmarkNode* bb_node = model_->bookmark_bar_node();
354   BookmarkEditor::EditDetails details =
355       BookmarkEditor::EditDetails::AddFolder(bb_node, 1);
356   details.urls.push_back(std::make_pair(GURL(base_path() + "x"),
357                                         ASCIIToUTF16("z")));
358   CreateEditor(profile_.get(), bb_node, details, BookmarkEditorView::SHOW_TREE);
359
360   // The url field shouldn't be visible.
361   EXPECT_FALSE(URLTFHasParent());
362   SetTitleText(ASCIIToUTF16("new_F"));
363
364   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0));
365
366   // Make sure the folder was created.
367   ASSERT_EQ(4, bb_node->child_count());
368   const BookmarkNode* new_node = bb_node->GetChild(1);
369   EXPECT_EQ(BookmarkNode::FOLDER, new_node->type());
370   EXPECT_EQ(ASCIIToUTF16("new_F"), new_node->GetTitle());
371   // The node should have one child.
372   ASSERT_EQ(1, new_node->child_count());
373   const BookmarkNode* new_child = new_node->GetChild(0);
374   // Make sure the child url/title match.
375   EXPECT_EQ(BookmarkNode::URL, new_child->type());
376   EXPECT_EQ(details.urls[0].second, new_child->GetTitle());
377   EXPECT_EQ(details.urls[0].first, new_child->url());
378 }
379
380 // Creates a new folder and selects a different folder for the folder to appear
381 // in then the editor is initially created showing.
382 TEST_F(BookmarkEditorViewTest, MoveFolder) {
383   BookmarkEditor::EditDetails details = BookmarkEditor::EditDetails::AddFolder(
384       model_->bookmark_bar_node(), -1);
385   details.urls.push_back(std::make_pair(GURL(base_path() + "x"),
386                                         ASCIIToUTF16("z")));
387   CreateEditor(profile_.get(), model_->bookmark_bar_node(),
388                details, BookmarkEditorView::SHOW_TREE);
389
390   SetTitleText(ASCIIToUTF16("new_F"));
391
392   // Create the folder in the 'other' folder.
393   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1));
394
395   // Make sure the folder we edited is still there.
396   ASSERT_EQ(3, model_->other_node()->child_count());
397   const BookmarkNode* new_node = model_->other_node()->GetChild(2);
398   EXPECT_EQ(BookmarkNode::FOLDER, new_node->type());
399   EXPECT_EQ(ASCIIToUTF16("new_F"), new_node->GetTitle());
400   // The node should have one child.
401   ASSERT_EQ(1, new_node->child_count());
402   const BookmarkNode* new_child = new_node->GetChild(0);
403   // Make sure the child url/title match.
404   EXPECT_EQ(BookmarkNode::URL, new_child->type());
405   EXPECT_EQ(details.urls[0].second, new_child->GetTitle());
406   EXPECT_EQ(details.urls[0].first, new_child->url());
407 }
408
409 // Verifies the title of a new folder is updated correctly if ApplyEdits() is
410 // is invoked while focus is still on the text field.
411 TEST_F(BookmarkEditorViewTest, NewFolderTitleUpdatedOnCommit) {
412   const BookmarkNode* parent =
413       BookmarkModelFactory::GetForProfile(profile_.get())->
414       bookmark_bar_node() ->GetChild(2);
415
416   CreateEditor(profile_.get(), parent,
417                BookmarkEditor::EditDetails::AddNodeInFolder(
418                    parent, 1, GURL(), base::string16()),
419                BookmarkEditorView::SHOW_TREE);
420   ExpandAndSelect();
421
422   SetURLText(UTF8ToUTF16(GURL(base_path() + "a").spec()));
423   SetTitleText(ASCIIToUTF16("new_a"));
424
425   NewFolder();
426   ASSERT_TRUE(tree_view()->editor() != NULL);
427   tree_view()->editor()->SetText(ASCIIToUTF16("modified"));
428   ApplyEdits();
429
430   // Verify the new folder was added and title set appropriately.
431   ASSERT_EQ(1, parent->child_count());
432   const BookmarkNode* new_folder = parent->GetChild(0);
433   ASSERT_TRUE(new_folder->is_folder());
434   EXPECT_EQ("modified", base::UTF16ToASCII(new_folder->GetTitle()));
435 }