- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / bookmarks / bookmark_editor_gtk_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/gtk/bookmarks/bookmark_editor_gtk.h"
6
7 #include <gtk/gtk.h>
8
9 #include <string>
10
11 #include "base/compiler_specific.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/bookmarks/bookmark_model.h"
16 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
17 #include "chrome/browser/bookmarks/bookmark_test_helpers.h"
18 #include "chrome/browser/ui/gtk/bookmarks/bookmark_tree_model.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "content/public/test/test_browser_thread.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 using base::Time;
24 using base::TimeDelta;
25 using content::BrowserThread;
26
27 // Base class for bookmark editor tests. This class is a copy from
28 // bookmark_editor_view_unittest.cc, and all the tests in this file are
29 // GTK-ifications of the corresponding views tests. Testing here is really
30 // important because on Linux, we make round trip copies from chrome's
31 // BookmarkModel class to GTK's native GtkTreeStore.
32 class BookmarkEditorGtkTest : public testing::Test {
33  public:
34   BookmarkEditorGtkTest()
35       : model_(NULL),
36         ui_thread_(BrowserThread::UI, &message_loop_),
37         file_thread_(BrowserThread::FILE, &message_loop_) {
38   }
39
40   virtual void SetUp() OVERRIDE {
41     profile_.reset(new TestingProfile());
42     profile_->CreateBookmarkModel(true);
43
44     model_ = BookmarkModelFactory::GetForProfile(profile_.get());
45     test::WaitForBookmarkModelToLoad(model_);
46
47     AddTestData();
48   }
49
50   virtual void TearDown() OVERRIDE {
51   }
52
53  protected:
54   std::string base_path() const { return "file:///c:/tmp/"; }
55
56   const BookmarkNode* GetNode(const std::string& name) {
57     return model_->GetMostRecentlyAddedNodeForURL(GURL(base_path() + name));
58   }
59
60   BookmarkModel* model_;
61   scoped_ptr<TestingProfile> profile_;
62
63  private:
64   // Creates the following structure:
65   // bookmark bar node
66   //   a
67   //   F1
68   //    f1a
69   //    F11
70   //     f11a
71   //   F2
72   // other node
73   //   oa
74   //   OF1
75   //     of1a
76   // mobile node
77   //   sa
78   void AddTestData() {
79     std::string test_base = base_path();
80
81     model_->AddURL(model_->bookmark_bar_node(), 0, ASCIIToUTF16("a"),
82                    GURL(test_base + "a"));
83     const BookmarkNode* f1 =
84         model_->AddFolder(model_->bookmark_bar_node(), 1, ASCIIToUTF16("F1"));
85     model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
86     const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
87     model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
88     model_->AddFolder(model_->bookmark_bar_node(), 2, ASCIIToUTF16("F2"));
89
90     // Children of the other node.
91     model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
92                    GURL(test_base + "oa"));
93     const BookmarkNode* of1 =
94         model_->AddFolder(model_->other_node(), 1, ASCIIToUTF16("OF1"));
95     model_->AddURL(of1, 0, ASCIIToUTF16("of1a"), GURL(test_base + "of1a"));
96
97     // Children of the mobile node.
98     model_->AddURL(model_->mobile_node(), 0, ASCIIToUTF16("sa"),
99                    GURL(test_base + "sa"));
100   }
101
102   base::MessageLoopForUI message_loop_;
103   content::TestBrowserThread ui_thread_;
104   content::TestBrowserThread file_thread_;
105 };
106
107 // Makes sure the tree model matches that of the bookmark bar model.
108 TEST_F(BookmarkEditorGtkTest, ModelsMatch) {
109   BookmarkEditorGtk editor(
110       NULL,
111       profile_.get(),
112       NULL,
113       BookmarkEditor::EditDetails::AddNodeInFolder(
114           NULL, -1, GURL(), string16()),
115       BookmarkEditor::SHOW_TREE);
116
117   // The root should have two or three children, one for the bookmark bar node,
118   // another for the 'other bookmarks' folder, and depending on the visib
119   GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
120   GtkTreeIter toplevel;
121   ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &toplevel));
122   GtkTreeIter bookmark_bar_node = toplevel;
123   ASSERT_TRUE(gtk_tree_model_iter_next(store, &toplevel));
124   GtkTreeIter other_node = toplevel;
125   if (model_->mobile_node()->IsVisible()) {
126     // If we have a mobile node, then the iterator should find one element after
127     // "other bookmarks"
128     ASSERT_TRUE(gtk_tree_model_iter_next(store, &toplevel));
129     ASSERT_FALSE(gtk_tree_model_iter_next(store, &toplevel));
130   } else {
131     ASSERT_FALSE(gtk_tree_model_iter_next(store, &toplevel));
132   }
133
134   // The bookmark bar should have 2 nodes: folder F1 and F2.
135   GtkTreeIter f1_iter;
136   GtkTreeIter child;
137   ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
138   ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &bookmark_bar_node));
139   f1_iter = child;
140   ASSERT_EQ("F1", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
141   ASSERT_TRUE(gtk_tree_model_iter_next(store, &child));
142   ASSERT_EQ("F2", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
143   ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
144
145   // F1 should have one child, F11
146   ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f1_iter));
147   ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &f1_iter));
148   ASSERT_EQ("F11", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
149   ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
150
151   // Other node should have one child (OF1).
152   ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &other_node));
153   ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &other_node));
154   ASSERT_EQ("OF1", UTF16ToUTF8(GetTitleFromTreeIter(store, &child)));
155   ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
156 }
157
158 // Changes the title and makes sure parent/visual order doesn't change.
159 TEST_F(BookmarkEditorGtkTest, EditTitleKeepsPosition) {
160   BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
161                            BookmarkEditor::EditDetails::EditNode(GetNode("a")),
162                            BookmarkEditor::SHOW_TREE);
163   gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
164
165   GtkTreeIter bookmark_bar_node;
166   GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
167   ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
168   editor.ApplyEdits(&bookmark_bar_node);
169
170   const BookmarkNode* bb_node = model_->bookmark_bar_node();
171   ASSERT_EQ(ASCIIToUTF16("new_a"), bb_node->GetChild(0)->GetTitle());
172   // The URL shouldn't have changed.
173   ASSERT_TRUE(GURL(base_path() + "a") == bb_node->GetChild(0)->url());
174 }
175
176 // Changes the url and makes sure parent/visual order doesn't change.
177 TEST_F(BookmarkEditorGtkTest, EditURLKeepsPosition) {
178   Time node_time = GetNode("a")->date_added();
179   BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
180                            BookmarkEditor::EditDetails::EditNode(GetNode("a")),
181                            BookmarkEditor::SHOW_TREE);
182   gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
183                      GURL(base_path() + "new_a").spec().c_str());
184
185   GtkTreeIter bookmark_bar_node;
186   GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
187   ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
188   editor.ApplyEdits(&bookmark_bar_node);
189
190   const BookmarkNode* bb_node = model_->bookmark_bar_node();
191   ASSERT_EQ(ASCIIToUTF16("a"), bb_node->GetChild(0)->GetTitle());
192   // The URL should have changed.
193   ASSERT_TRUE(GURL(base_path() + "new_a") == bb_node->GetChild(0)->url());
194   ASSERT_TRUE(node_time == bb_node->GetChild(0)->date_added());
195 }
196
197 // Moves 'a' to be a child of the other node.
198 TEST_F(BookmarkEditorGtkTest, ChangeParent) {
199   BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
200                            BookmarkEditor::EditDetails::EditNode(GetNode("a")),
201                            BookmarkEditor::SHOW_TREE);
202
203   GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
204   GtkTreeIter gtk_other_node;
205   ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
206   ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
207   editor.ApplyEdits(&gtk_other_node);
208
209   const BookmarkNode* other_node = model_->other_node();
210   ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
211   ASSERT_TRUE(GURL(base_path() + "a") == other_node->GetChild(2)->url());
212 }
213
214 // Moves 'a' to be a child of the other node.
215 // Moves 'a' to be a child of the other node and changes its url to new_a.
216 TEST_F(BookmarkEditorGtkTest, ChangeParentAndURL) {
217   Time node_time = GetNode("a")->date_added();
218   BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
219                            BookmarkEditor::EditDetails::EditNode(GetNode("a")),
220                            BookmarkEditor::SHOW_TREE);
221
222   gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
223                      GURL(base_path() + "new_a").spec().c_str());
224
225   GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
226   GtkTreeIter gtk_other_node;
227   ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
228   ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
229   editor.ApplyEdits(&gtk_other_node);
230
231   const BookmarkNode* other_node = model_->other_node();
232   ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
233   ASSERT_TRUE(GURL(base_path() + "new_a") == other_node->GetChild(2)->url());
234   ASSERT_TRUE(node_time == other_node->GetChild(2)->date_added());
235 }
236
237 // Creates a new folder and moves a node to it.
238 TEST_F(BookmarkEditorGtkTest, MoveToNewParent) {
239   BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
240                            BookmarkEditor::EditDetails::EditNode(GetNode("a")),
241                            BookmarkEditor::SHOW_TREE);
242
243   GtkTreeIter bookmark_bar_node;
244   GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
245   ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
246
247   // The bookmark bar should have 2 nodes: folder F1 and F2.
248   GtkTreeIter f2_iter;
249   ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
250   ASSERT_TRUE(gtk_tree_model_iter_children(store, &f2_iter,
251                                            &bookmark_bar_node));
252   ASSERT_TRUE(gtk_tree_model_iter_next(store, &f2_iter));
253
254   // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21".
255   GtkTreeIter f21_iter;
256   editor.AddNewFolder(&f2_iter, &f21_iter);
257   gtk_tree_store_set(editor.tree_store_, &f21_iter, FOLDER_NAME, "F21", -1);
258   GtkTreeIter f211_iter;
259   editor.AddNewFolder(&f21_iter, &f211_iter);
260   gtk_tree_store_set(editor.tree_store_, &f211_iter, FOLDER_NAME, "F211", -1);
261
262   ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f2_iter));
263
264   editor.ApplyEdits(&f2_iter);
265
266   const BookmarkNode* bb_node = model_->bookmark_bar_node();
267   const BookmarkNode* mf2 = bb_node->GetChild(1);
268
269   // F2 in the model should have two children now: F21 and the node edited.
270   ASSERT_EQ(2, mf2->child_count());
271   // F21 should be first.
272   ASSERT_EQ(ASCIIToUTF16("F21"), mf2->GetChild(0)->GetTitle());
273   // Then a.
274   ASSERT_EQ(ASCIIToUTF16("a"), mf2->GetChild(1)->GetTitle());
275
276   // F21 should have one child, F211.
277   const BookmarkNode* mf21 = mf2->GetChild(0);
278   ASSERT_EQ(1, mf21->child_count());
279   ASSERT_EQ(ASCIIToUTF16("F211"), mf21->GetChild(0)->GetTitle());
280 }
281
282 // Brings up the editor, creating a new URL on the bookmark bar.
283 TEST_F(BookmarkEditorGtkTest, NewURL) {
284   BookmarkEditorGtk editor(
285       NULL,
286       profile_.get(),
287       NULL,
288       BookmarkEditor::EditDetails::AddNodeInFolder(
289           NULL, -1, GURL(), string16()),
290       BookmarkEditor::SHOW_TREE);
291
292   gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
293                      GURL(base_path() + "a").spec().c_str());
294   gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
295
296   GtkTreeIter bookmark_bar_node;
297   GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
298   ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
299   editor.ApplyEdits(&bookmark_bar_node);
300
301   const BookmarkNode* bb_node = model_->bookmark_bar_node();
302   ASSERT_EQ(4, bb_node->child_count());
303
304   const BookmarkNode* new_node = bb_node->GetChild(3);
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(BookmarkEditorGtkTest, ChangeURLNoTree) {
311   BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
312                            BookmarkEditor::EditDetails::EditNode(
313                                model_->other_node()->GetChild(0)),
314                            BookmarkEditor::NO_TREE);
315
316   gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
317                      GURL(base_path() + "a").spec().c_str());
318   gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
319
320   editor.ApplyEdits(NULL);
321
322   const BookmarkNode* other_node = model_->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(BookmarkEditorGtkTest, ChangeTitleNoTree) {
333   BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
334                            BookmarkEditor::EditDetails::EditNode(
335                                model_->other_node()->GetChild(0)),
336                            BookmarkEditor::NO_TREE);
337   gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");
338
339   editor.ApplyEdits();
340
341   const BookmarkNode* other_node = model_->other_node();
342   ASSERT_EQ(2, other_node->child_count());
343
344   const BookmarkNode* new_node = other_node->GetChild(0);
345   EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
346 }