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