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