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.
5 #import <Cocoa/Cocoa.h>
7 #include "base/strings/string16.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
11 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h"
12 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
13 #include "chrome/test/base/testing_profile.h"
14 #include "components/bookmarks/browser/bookmark_model.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #import "testing/gtest_mac.h"
17 #include "testing/platform_test.h"
19 using base::ASCIIToUTF16;
20 using bookmarks::BookmarkModel;
21 using bookmarks::BookmarkNode;
23 class BookmarkEditorControllerTest : public CocoaProfileTest {
25 const BookmarkNode* default_node_;
26 const BookmarkNode* default_parent_;
27 const char* default_name_;
28 base::string16 default_title_;
29 BookmarkEditorController* controller_;
31 void SetUp() override {
32 CocoaProfileTest::SetUp();
33 ASSERT_TRUE(profile());
35 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
36 default_parent_ = model->bookmark_bar_node();
37 default_name_ = "http://www.zim-bop-a-dee.com/";
38 default_title_ = ASCIIToUTF16("ooh title");
39 const BookmarkNode* default_node = model->AddURL(default_parent_, 0,
42 controller_ = [[BookmarkEditorController alloc]
43 initWithParentWindow:test_window()
45 parent:default_parent_
48 title:base::string16()
49 configuration:BookmarkEditor::NO_TREE];
50 [controller_ runAsModalSheet];
53 void TearDown() override {
55 CocoaProfileTest::TearDown();
59 TEST_F(BookmarkEditorControllerTest, NoEdit) {
60 [controller_ cancel:nil];
61 ASSERT_EQ(default_parent_->child_count(), 1);
62 const BookmarkNode* child = default_parent_->GetChild(0);
63 EXPECT_EQ(child->GetTitle(), default_title_);
64 EXPECT_EQ(child->url(), GURL(default_name_));
67 TEST_F(BookmarkEditorControllerTest, EditTitle) {
68 [controller_ setDisplayName:@"whamma jamma bamma"];
70 ASSERT_EQ(default_parent_->child_count(), 1);
71 const BookmarkNode* child = default_parent_->GetChild(0);
72 EXPECT_EQ(child->GetTitle(), ASCIIToUTF16("whamma jamma bamma"));
73 EXPECT_EQ(child->url(), GURL(default_name_));
76 TEST_F(BookmarkEditorControllerTest, EditURL) {
77 EXPECT_TRUE([controller_ okButtonEnabled]);
78 [controller_ setDisplayURL:@"http://yellow-sneakers.com/"];
79 EXPECT_TRUE([controller_ okButtonEnabled]);
81 ASSERT_EQ(default_parent_->child_count(), 1);
82 const BookmarkNode* child = default_parent_->GetChild(0);
83 EXPECT_EQ(child->GetTitle(), default_title_);
84 EXPECT_EQ(child->url(), GURL("http://yellow-sneakers.com/"));
87 TEST_F(BookmarkEditorControllerTest, EditAndFixPrefix) {
88 [controller_ setDisplayURL:@"x"];
90 ASSERT_EQ(default_parent_->child_count(), 1);
91 const BookmarkNode* child = default_parent_->GetChild(0);
92 EXPECT_TRUE(child->url().is_valid());
95 TEST_F(BookmarkEditorControllerTest, NodeDeleted) {
96 // Delete the bookmark being edited and verify the sheet cancels itself:
97 ASSERT_TRUE([test_window() attachedSheet]);
98 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
99 model->Remove(default_parent_->GetChild(0));
100 ASSERT_FALSE([test_window() attachedSheet]);
103 TEST_F(BookmarkEditorControllerTest, EditAndConfirmOKButton) {
104 // Confirm OK button enabled/disabled as appropriate:
105 // First test the URL.
106 EXPECT_TRUE([controller_ okButtonEnabled]);
107 [controller_ setDisplayURL:@""];
108 EXPECT_FALSE([controller_ okButtonEnabled]);
109 [controller_ setDisplayURL:@"http://www.cnn.com"];
110 EXPECT_TRUE([controller_ okButtonEnabled]);
111 // Then test the name.
112 [controller_ setDisplayName:@""];
113 EXPECT_TRUE([controller_ okButtonEnabled]);
114 [controller_ setDisplayName:@" "];
115 EXPECT_TRUE([controller_ okButtonEnabled]);
116 // Then little mix of both.
117 [controller_ setDisplayName:@"name"];
118 EXPECT_TRUE([controller_ okButtonEnabled]);
119 [controller_ setDisplayURL:@""];
120 EXPECT_FALSE([controller_ okButtonEnabled]);
121 [controller_ cancel:nil];
124 TEST_F(BookmarkEditorControllerTest, GoodAndBadURLsChangeColor) {
125 // Confirm that the background color of the URL edit field changes
126 // based on whether it contains a valid or invalid URL.
127 [controller_ setDisplayURL:@"http://www.cnn.com"];
128 NSColor *urlColorA = [controller_ urlFieldColor];
129 EXPECT_TRUE(urlColorA);
130 [controller_ setDisplayURL:@""];
131 NSColor *urlColorB = [controller_ urlFieldColor];
132 EXPECT_TRUE(urlColorB);
133 EXPECT_NSNE(urlColorA, urlColorB);
134 [controller_ setDisplayURL:@"http://www.google.com"];
135 [controller_ cancel:nil];
136 urlColorB = [controller_ urlFieldColor];
137 EXPECT_TRUE(urlColorB);
138 EXPECT_NSEQ(urlColorA, urlColorB);
141 class BookmarkEditorControllerNoNodeTest : public CocoaProfileTest {
143 BookmarkEditorController* controller_;
145 void SetUp() override {
146 CocoaProfileTest::SetUp();
147 ASSERT_TRUE(profile());
149 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
150 const BookmarkNode* parent = model->bookmark_bar_node();
151 controller_ = [[BookmarkEditorController alloc]
152 initWithParentWindow:test_window()
157 title:base::string16()
158 configuration:BookmarkEditor::NO_TREE];
160 [controller_ runAsModalSheet];
163 void TearDown() override {
165 CocoaProfileTest::TearDown();
169 TEST_F(BookmarkEditorControllerNoNodeTest, NoNodeNoTree) {
170 EXPECT_NSEQ(@"", [controller_ displayName]);
171 EXPECT_EQ(nil, [controller_ displayURL]);
172 EXPECT_FALSE([controller_ okButtonEnabled]);
173 [controller_ cancel:nil];
176 class BookmarkEditorControllerYesNodeTest : public CocoaProfileTest {
178 base::string16 default_title_;
179 BookmarkEditorController* controller_;
181 void SetUp() override {
182 CocoaProfileTest::SetUp();
183 ASSERT_TRUE(profile());
185 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
186 const BookmarkNode* parent = model->bookmark_bar_node();
187 default_title_ = ASCIIToUTF16("wooh title");
188 const BookmarkNode* node =
189 model->AddURL(parent, 0, default_title_,
190 GURL("http://www.zoom-baby-doo-da.com/"));
191 controller_ = [[BookmarkEditorController alloc]
192 initWithParentWindow:test_window()
197 title:base::string16()
198 configuration:BookmarkEditor::NO_TREE];
200 [controller_ runAsModalSheet];
203 void TearDown() override {
205 CocoaProfileTest::TearDown();
209 TEST_F(BookmarkEditorControllerYesNodeTest, YesNodeShowTree) {
210 EXPECT_NSEQ(base::SysUTF16ToNSString(default_title_),
211 [controller_ displayName]);
212 EXPECT_NSEQ([NSString stringWithCString:"www.zoom-baby-doo-da.com"
213 encoding:NSUTF8StringEncoding],
214 [controller_ displayURL]);
215 [controller_ cancel:nil];
219 class BookmarkEditorControllerUtf8NodeTest : public CocoaProfileTest {
221 BookmarkEditorController* controller_;
223 void SetUp() override {
224 CocoaProfileTest::SetUp();
225 ASSERT_TRUE(profile());
227 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
228 const BookmarkNode* parent = model->bookmark_bar_node();
229 base::string16 title = ASCIIToUTF16("wooh title");
230 const char* url_name = "http://www.foobar.com/心得寫作";
231 const BookmarkNode* node = model->AddURL(parent, 0, title, GURL(url_name));
232 controller_ = [[BookmarkEditorController alloc]
233 initWithParentWindow:test_window()
238 title:base::string16()
239 configuration:BookmarkEditor::NO_TREE];
241 [controller_ runAsModalSheet];
244 void TearDown() override {
246 CocoaProfileTest::TearDown();
250 TEST_F(BookmarkEditorControllerUtf8NodeTest, DisplayUtf8Name) {
251 // The "http://" prefix is trimmed, but the UTF-8 formatted characters remain.
252 EXPECT_NSEQ([NSString stringWithCString:"www.foobar.com/心得寫作"
253 encoding:NSUTF8StringEncoding],
254 [controller_ displayURL]);
255 [controller_ cancel:nil];
258 class BookmarkEditorControllerTreeTest : public CocoaProfileTest {
261 BookmarkEditorController* controller_;
262 const BookmarkNode* folder_a_;
263 const BookmarkNode* folder_b_;
264 const BookmarkNode* folder_bb_;
265 const BookmarkNode* folder_c_;
266 const BookmarkNode* bookmark_bb_3_;
271 // Set up a small bookmark hierarchy, which will look as follows:
281 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
282 const BookmarkNode* root = model->bookmark_bar_node();
283 folder_a_ = model->AddFolder(root, 0, ASCIIToUTF16("a"));
284 model->AddURL(folder_a_, 0, ASCIIToUTF16("a-0"), GURL("http://a-0.com"));
285 model->AddURL(folder_a_, 1, ASCIIToUTF16("a-1"), GURL("http://a-1.com"));
286 model->AddURL(folder_a_, 2, ASCIIToUTF16("a-2"), GURL("http://a-2.com"));
288 folder_b_ = model->AddFolder(root, 1, ASCIIToUTF16("b"));
289 model->AddURL(folder_b_, 0, ASCIIToUTF16("b-0"), GURL("http://b-0.com"));
290 folder_bb_ = model->AddFolder(folder_b_, 1, ASCIIToUTF16("bb"));
291 model->AddURL(folder_bb_, 0, ASCIIToUTF16("bb-0"), GURL("http://bb-0.com"));
292 model->AddURL(folder_bb_, 1, ASCIIToUTF16("bb-1"), GURL("http://bb-1.com"));
293 model->AddURL(folder_bb_, 2, ASCIIToUTF16("bb-2"), GURL("http://bb-2.com"));
295 // To find it later, this bookmark name must always have a URL
296 // of http://bb-3.com or https://bb-3.com
297 bb3_url_1_ = GURL("http://bb-3.com");
298 bb3_url_2_ = GURL("https://bb-3.com");
299 bookmark_bb_3_ = model->AddURL(folder_bb_, 3, ASCIIToUTF16("bb-3"),
302 model->AddURL(folder_bb_, 4, ASCIIToUTF16("bb-4"), GURL("http://bb-4.com"));
303 model->AddURL(folder_b_, 2, ASCIIToUTF16("b-1"), GURL("http://b-2.com"));
304 model->AddURL(folder_b_, 3, ASCIIToUTF16("b-2"), GURL("http://b-3.com"));
306 folder_c_ = model->AddFolder(root, 2, ASCIIToUTF16("c"));
307 model->AddURL(folder_c_, 0, ASCIIToUTF16("c-0"), GURL("http://c-0.com"));
308 model->AddURL(folder_c_, 1, ASCIIToUTF16("c-1"), GURL("http://c-1.com"));
309 model->AddURL(folder_c_, 2, ASCIIToUTF16("c-2"), GURL("http://c-2.com"));
310 model->AddURL(folder_c_, 3, ASCIIToUTF16("c-3"), GURL("http://c-3.com"));
312 model->AddURL(root, 3, ASCIIToUTF16("d"), GURL("http://d-0.com"));
315 virtual BookmarkEditorController* CreateController() {
316 return [[BookmarkEditorController alloc]
317 initWithParentWindow:test_window()
322 title:base::string16()
323 configuration:BookmarkEditor::SHOW_TREE];
326 void SetUp() override {
327 CocoaProfileTest::SetUp();
328 ASSERT_TRUE(profile());
331 controller_ = CreateController();
332 [controller_ runAsModalSheet];
335 void TearDown() override {
337 CocoaProfileTest::TearDown();
340 // After changing a node, pointers to the node may be invalid. This
341 // is because the node itself may not be updated; it may removed and
342 // a new one is added in that location. (Implementation detail of
343 // BookmarkEditorController). This method updates the class's
344 // bookmark_bb_3_ so that it points to the new node for testing.
346 std::vector<const BookmarkNode*> nodes;
347 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
348 model->GetNodesByURL(bb3_url_1_, &nodes);
350 model->GetNodesByURL(bb3_url_2_, &nodes);
351 DCHECK(nodes.size());
352 bookmark_bb_3_ = nodes[0];
357 TEST_F(BookmarkEditorControllerTreeTest, VerifyBookmarkTestModel) {
358 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
360 const BookmarkNode* root = model->bookmark_bar_node();
361 EXPECT_EQ(4, root->child_count());
362 const BookmarkNode* child = root->GetChild(0);
363 EXPECT_EQ(3, child->child_count());
364 const BookmarkNode* subchild = child->GetChild(0);
365 EXPECT_EQ(0, subchild->child_count());
366 subchild = child->GetChild(1);
367 EXPECT_EQ(0, subchild->child_count());
368 subchild = child->GetChild(2);
369 EXPECT_EQ(0, subchild->child_count());
371 child = root->GetChild(1);
372 EXPECT_EQ(4, child->child_count());
373 subchild = child->GetChild(0);
374 EXPECT_EQ(0, subchild->child_count());
375 subchild = child->GetChild(1);
376 EXPECT_EQ(5, subchild->child_count());
377 const BookmarkNode* subsubchild = subchild->GetChild(0);
378 EXPECT_EQ(0, subsubchild->child_count());
379 subsubchild = subchild->GetChild(1);
380 EXPECT_EQ(0, subsubchild->child_count());
381 subsubchild = subchild->GetChild(2);
382 EXPECT_EQ(0, subsubchild->child_count());
383 subsubchild = subchild->GetChild(3);
384 EXPECT_EQ(0, subsubchild->child_count());
385 subsubchild = subchild->GetChild(4);
386 EXPECT_EQ(0, subsubchild->child_count());
387 subchild = child->GetChild(2);
388 EXPECT_EQ(0, subchild->child_count());
389 subchild = child->GetChild(3);
390 EXPECT_EQ(0, subchild->child_count());
392 child = root->GetChild(2);
393 EXPECT_EQ(4, child->child_count());
394 subchild = child->GetChild(0);
395 EXPECT_EQ(0, subchild->child_count());
396 subchild = child->GetChild(1);
397 EXPECT_EQ(0, subchild->child_count());
398 subchild = child->GetChild(2);
399 EXPECT_EQ(0, subchild->child_count());
400 subchild = child->GetChild(3);
401 EXPECT_EQ(0, subchild->child_count());
403 child = root->GetChild(3);
404 EXPECT_EQ(0, child->child_count());
405 [controller_ cancel:nil];
408 TEST_F(BookmarkEditorControllerTreeTest, RenameBookmarkInPlace) {
409 const BookmarkNode* oldParent = bookmark_bb_3_->parent();
410 [controller_ setDisplayName:@"NEW NAME"];
411 [controller_ ok:nil];
413 const BookmarkNode* newParent = bookmark_bb_3_->parent();
414 ASSERT_EQ(newParent, oldParent);
415 int childIndex = newParent->GetIndexOf(bookmark_bb_3_);
416 ASSERT_EQ(3, childIndex);
419 TEST_F(BookmarkEditorControllerTreeTest, ChangeBookmarkURLInPlace) {
420 const BookmarkNode* oldParent = bookmark_bb_3_->parent();
421 [controller_ setDisplayURL:@"https://bb-3.com"];
422 [controller_ ok:nil];
424 const BookmarkNode* newParent = bookmark_bb_3_->parent();
425 ASSERT_EQ(newParent, oldParent);
426 int childIndex = newParent->GetIndexOf(bookmark_bb_3_);
427 ASSERT_EQ(3, childIndex);
430 TEST_F(BookmarkEditorControllerTreeTest, ChangeBookmarkFolder) {
431 [controller_ selectTestNodeInBrowser:folder_c_];
432 [controller_ ok:nil];
434 const BookmarkNode* parent = bookmark_bb_3_->parent();
435 ASSERT_EQ(parent, folder_c_);
436 int childIndex = parent->GetIndexOf(bookmark_bb_3_);
437 ASSERT_EQ(4, childIndex);
440 TEST_F(BookmarkEditorControllerTreeTest, ChangeNameAndBookmarkFolder) {
441 [controller_ setDisplayName:@"NEW NAME"];
442 [controller_ selectTestNodeInBrowser:folder_c_];
443 [controller_ ok:nil];
445 const BookmarkNode* parent = bookmark_bb_3_->parent();
446 ASSERT_EQ(parent, folder_c_);
447 int childIndex = parent->GetIndexOf(bookmark_bb_3_);
448 ASSERT_EQ(4, childIndex);
449 EXPECT_EQ(bookmark_bb_3_->GetTitle(), ASCIIToUTF16("NEW NAME"));
452 TEST_F(BookmarkEditorControllerTreeTest, AddFolderWithFolderSelected) {
453 // Folders are NOT added unless the OK button is pressed.
454 [controller_ newFolder:nil];
455 [controller_ cancel:nil];
456 EXPECT_EQ(5, folder_bb_->child_count());
459 class BookmarkEditorControllerTreeNoNodeTest :
460 public BookmarkEditorControllerTreeTest {
462 BookmarkEditorController* CreateController() override {
463 return [[BookmarkEditorController alloc]
464 initWithParentWindow:test_window()
469 title:base::string16()
470 configuration:BookmarkEditor::SHOW_TREE];
475 TEST_F(BookmarkEditorControllerTreeNoNodeTest, NewBookmarkNoNode) {
476 [controller_ setDisplayName:@"NEW BOOKMARK"];
477 [controller_ setDisplayURL:@"http://NEWURL.com"];
478 [controller_ ok:nil];
479 const BookmarkNode* new_node = folder_bb_->GetChild(5);
480 ASSERT_EQ(0, new_node->child_count());
481 EXPECT_EQ(new_node->GetTitle(), ASCIIToUTF16("NEW BOOKMARK"));
482 EXPECT_EQ(new_node->url(), GURL("http://NEWURL.com"));