blob: 4098467fc081af1263246bbe49d32fbea47d7ae9 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <Cocoa/Cocoa.h>
#include "base/strings/string16.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h"
#include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
#include "chrome/test/base/testing_profile.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#include "testing/platform_test.h"
using base::ASCIIToUTF16;
using bookmarks::BookmarkModel;
using bookmarks::BookmarkNode;
class BookmarkEditorControllerTest : public CocoaProfileTest {
public:
const BookmarkNode* default_node_;
const BookmarkNode* default_parent_;
const char* default_name_;
base::string16 default_title_;
BookmarkEditorController* controller_;
void SetUp() override {
CocoaProfileTest::SetUp();
ASSERT_TRUE(profile());
BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(profile());
default_parent_ = model->bookmark_bar_node();
default_name_ = "http://www.zim-bop-a-dee.com/";
default_title_ = ASCIIToUTF16("ooh title");
const BookmarkNode* default_node = model->AddURL(default_parent_, 0,
default_title_,
GURL(default_name_));
controller_ = [[BookmarkEditorController alloc]
initWithParentWindow:test_window()
profile:profile()
parent:default_parent_
node:default_node
url:GURL()
title:base::string16()
configuration:BookmarkEditor::NO_TREE];
[controller_ runAsModalSheet];
}
void TearDown() override {
controller_ = NULL;
CocoaProfileTest::TearDown();
}
};
TEST_F(BookmarkEditorControllerTest, NoEdit) {
[controller_ cancel:nil];
ASSERT_EQ(default_parent_->child_count(), 1);
const BookmarkNode* child = default_parent_->GetChild(0);
EXPECT_EQ(child->GetTitle(), default_title_);
EXPECT_EQ(child->url(), GURL(default_name_));
}
TEST_F(BookmarkEditorControllerTest, EditTitle) {
[controller_ setDisplayName:@"whamma jamma bamma"];
[controller_ ok:nil];
ASSERT_EQ(default_parent_->child_count(), 1);
const BookmarkNode* child = default_parent_->GetChild(0);
EXPECT_EQ(child->GetTitle(), ASCIIToUTF16("whamma jamma bamma"));
EXPECT_EQ(child->url(), GURL(default_name_));
}
TEST_F(BookmarkEditorControllerTest, EditURL) {
EXPECT_TRUE([controller_ okButtonEnabled]);
[controller_ setDisplayURL:@"http://yellow-sneakers.com/"];
EXPECT_TRUE([controller_ okButtonEnabled]);
[controller_ ok:nil];
ASSERT_EQ(default_parent_->child_count(), 1);
const BookmarkNode* child = default_parent_->GetChild(0);
EXPECT_EQ(child->GetTitle(), default_title_);
EXPECT_EQ(child->url(), GURL("http://yellow-sneakers.com/"));
}
TEST_F(BookmarkEditorControllerTest, EditAndFixPrefix) {
[controller_ setDisplayURL:@"x"];
[controller_ ok:nil];
ASSERT_EQ(default_parent_->child_count(), 1);
const BookmarkNode* child = default_parent_->GetChild(0);
EXPECT_TRUE(child->url().is_valid());
}
TEST_F(BookmarkEditorControllerTest, NodeDeleted) {
// Delete the bookmark being edited and verify the sheet cancels itself:
ASSERT_TRUE([test_window() attachedSheet]);
BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile());
model->Remove(default_parent_->GetChild(0));
ASSERT_FALSE([test_window() attachedSheet]);
}
TEST_F(BookmarkEditorControllerTest, EditAndConfirmOKButton) {
// Confirm OK button enabled/disabled as appropriate:
// First test the URL.
EXPECT_TRUE([controller_ okButtonEnabled]);
[controller_ setDisplayURL:@""];
EXPECT_FALSE([controller_ okButtonEnabled]);
[controller_ setDisplayURL:@"http://www.cnn.com"];
EXPECT_TRUE([controller_ okButtonEnabled]);
// Then test the name.
[controller_ setDisplayName:@""];
EXPECT_TRUE([controller_ okButtonEnabled]);
[controller_ setDisplayName:@" "];
EXPECT_TRUE([controller_ okButtonEnabled]);
// Then little mix of both.
[controller_ setDisplayName:@"name"];
EXPECT_TRUE([controller_ okButtonEnabled]);
[controller_ setDisplayURL:@""];
EXPECT_FALSE([controller_ okButtonEnabled]);
[controller_ cancel:nil];
}
TEST_F(BookmarkEditorControllerTest, GoodAndBadURLsChangeColor) {
// Confirm that the background color of the URL edit field changes
// based on whether it contains a valid or invalid URL.
[controller_ setDisplayURL:@"http://www.cnn.com"];
NSColor *urlColorA = [controller_ urlFieldColor];
EXPECT_TRUE(urlColorA);
[controller_ setDisplayURL:@""];
NSColor *urlColorB = [controller_ urlFieldColor];
EXPECT_TRUE(urlColorB);
EXPECT_NSNE(urlColorA, urlColorB);
[controller_ setDisplayURL:@"http://www.google.com"];
[controller_ cancel:nil];
urlColorB = [controller_ urlFieldColor];
EXPECT_TRUE(urlColorB);
EXPECT_NSEQ(urlColorA, urlColorB);
}
class BookmarkEditorControllerNoNodeTest : public CocoaProfileTest {
public:
BookmarkEditorController* controller_;
void SetUp() override {
CocoaProfileTest::SetUp();
ASSERT_TRUE(profile());
BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(profile());
const BookmarkNode* parent = model->bookmark_bar_node();
controller_ = [[BookmarkEditorController alloc]
initWithParentWindow:test_window()
profile:profile()
parent:parent
node:NULL
url:GURL()
title:base::string16()
configuration:BookmarkEditor::NO_TREE];
[controller_ runAsModalSheet];
}
void TearDown() override {
controller_ = NULL;
CocoaProfileTest::TearDown();
}
};
TEST_F(BookmarkEditorControllerNoNodeTest, NoNodeNoTree) {
EXPECT_NSEQ(@"", [controller_ displayName]);
EXPECT_EQ(nil, [controller_ displayURL]);
EXPECT_FALSE([controller_ okButtonEnabled]);
[controller_ cancel:nil];
}
class BookmarkEditorControllerYesNodeTest : public CocoaProfileTest {
public:
base::string16 default_title_;
BookmarkEditorController* controller_;
void SetUp() override {
CocoaProfileTest::SetUp();
ASSERT_TRUE(profile());
BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(profile());
const BookmarkNode* parent = model->bookmark_bar_node();
default_title_ = ASCIIToUTF16("wooh title");
const BookmarkNode* node =
model->AddURL(parent, 0, default_title_,
GURL("http://www.zoom-baby-doo-da.com/"));
controller_ = [[BookmarkEditorController alloc]
initWithParentWindow:test_window()
profile:profile()
parent:parent
node:node
url:GURL()
title:base::string16()
configuration:BookmarkEditor::NO_TREE];
[controller_ runAsModalSheet];
}
void TearDown() override {
controller_ = NULL;
CocoaProfileTest::TearDown();
}
};
TEST_F(BookmarkEditorControllerYesNodeTest, YesNodeShowTree) {
EXPECT_NSEQ(base::SysUTF16ToNSString(default_title_),
[controller_ displayName]);
EXPECT_NSEQ([NSString stringWithCString:"www.zoom-baby-doo-da.com"
encoding:NSUTF8StringEncoding],
[controller_ displayURL]);
[controller_ cancel:nil];
}
class BookmarkEditorControllerUtf8NodeTest : public CocoaProfileTest {
public:
BookmarkEditorController* controller_;
void SetUp() override {
CocoaProfileTest::SetUp();
ASSERT_TRUE(profile());
BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(profile());
const BookmarkNode* parent = model->bookmark_bar_node();
base::string16 title = ASCIIToUTF16("wooh title");
const char* url_name = "http://www.foobar.com/心得寫作";
const BookmarkNode* node = model->AddURL(parent, 0, title, GURL(url_name));
controller_ = [[BookmarkEditorController alloc]
initWithParentWindow:test_window()
profile:profile()
parent:parent
node:node
url:GURL()
title:base::string16()
configuration:BookmarkEditor::NO_TREE];
[controller_ runAsModalSheet];
}
void TearDown() override {
controller_ = NULL;
CocoaProfileTest::TearDown();
}
};
TEST_F(BookmarkEditorControllerUtf8NodeTest, DisplayUtf8Name) {
// The "http://" prefix is trimmed, but the UTF-8 formatted characters remain.
EXPECT_NSEQ([NSString stringWithCString:"www.foobar.com/心得寫作"
encoding:NSUTF8StringEncoding],
[controller_ displayURL]);
[controller_ cancel:nil];
}
using BookmarkEditorControllerEditKeepsSchemeTest = CocoaProfileTest;
TEST_F(BookmarkEditorControllerEditKeepsSchemeTest, EditKeepsScheme) {
// Edits the bookmark and ensures resulting URL keeps the same scheme, even
// when userinfo is present in the URL
ASSERT_TRUE(profile());
BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile());
const BookmarkNode* kParent = model->bookmark_bar_node();
const base::string16 kTitle = ASCIIToUTF16("EditingKeepsScheme");
const GURL kUrl = GURL("http://javascript:scripttext@example.com/");
const BookmarkNode* kNode = model->AddURL(kParent, 0, base::string16(), kUrl);
BookmarkEditorController* controller = [[BookmarkEditorController alloc]
initWithParentWindow:test_window()
profile:profile()
parent:kParent
node:kNode
url:GURL()
title:base::string16()
configuration:BookmarkEditor::SHOW_TREE];
[controller runAsModalSheet];
// We expect only the trailing / to be trimmed when userinfo is present
EXPECT_NSEQ(base::SysUTF8ToNSString(kUrl.spec()),
[[controller displayURL] stringByAppendingString:@"/"]);
[controller setDisplayName:base::SysUTF16ToNSString(kTitle)];
EXPECT_TRUE([controller okButtonEnabled]);
[controller ok:nil];
ASSERT_EQ(1, kParent->child_count());
const BookmarkNode* kChild = kParent->GetChild(0);
EXPECT_EQ(kTitle, kChild->GetTitle());
EXPECT_EQ(kUrl, kChild->url());
}
class BookmarkEditorControllerTreeTest : public CocoaProfileTest {
public:
BookmarkEditorController* controller_;
const BookmarkNode* folder_a_;
const BookmarkNode* folder_b_;
const BookmarkNode* folder_bb_;
const BookmarkNode* folder_c_;
const BookmarkNode* bookmark_bb_3_;
GURL bb3_url_1_;
GURL bb3_url_2_;
void CreateModel() {
// Set up a small bookmark hierarchy, which will look as follows:
// a b c d
// a-0 b-0 c-0
// a-1 bb-0 c-1
// a-2 bb-1 c-2
// bb-2
// bb-3
// bb-4
// b-1
// b-2
BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(profile());
const BookmarkNode* root = model->bookmark_bar_node();
folder_a_ = model->AddFolder(root, 0, ASCIIToUTF16("a"));
model->AddURL(folder_a_, 0, ASCIIToUTF16("a-0"), GURL("http://a-0.com"));
model->AddURL(folder_a_, 1, ASCIIToUTF16("a-1"), GURL("http://a-1.com"));
model->AddURL(folder_a_, 2, ASCIIToUTF16("a-2"), GURL("http://a-2.com"));
folder_b_ = model->AddFolder(root, 1, ASCIIToUTF16("b"));
model->AddURL(folder_b_, 0, ASCIIToUTF16("b-0"), GURL("http://b-0.com"));
folder_bb_ = model->AddFolder(folder_b_, 1, ASCIIToUTF16("bb"));
model->AddURL(folder_bb_, 0, ASCIIToUTF16("bb-0"), GURL("http://bb-0.com"));
model->AddURL(folder_bb_, 1, ASCIIToUTF16("bb-1"), GURL("http://bb-1.com"));
model->AddURL(folder_bb_, 2, ASCIIToUTF16("bb-2"), GURL("http://bb-2.com"));
// To find it later, this bookmark name must always have a URL
// of http://bb-3.com or https://bb-3.com
bb3_url_1_ = GURL("http://bb-3.com");
bb3_url_2_ = GURL("https://bb-3.com");
bookmark_bb_3_ = model->AddURL(folder_bb_, 3, ASCIIToUTF16("bb-3"),
bb3_url_1_);
model->AddURL(folder_bb_, 4, ASCIIToUTF16("bb-4"), GURL("http://bb-4.com"));
model->AddURL(folder_b_, 2, ASCIIToUTF16("b-1"), GURL("http://b-2.com"));
model->AddURL(folder_b_, 3, ASCIIToUTF16("b-2"), GURL("http://b-3.com"));
folder_c_ = model->AddFolder(root, 2, ASCIIToUTF16("c"));
model->AddURL(folder_c_, 0, ASCIIToUTF16("c-0"), GURL("http://c-0.com"));
model->AddURL(folder_c_, 1, ASCIIToUTF16("c-1"), GURL("http://c-1.com"));
model->AddURL(folder_c_, 2, ASCIIToUTF16("c-2"), GURL("http://c-2.com"));
model->AddURL(folder_c_, 3, ASCIIToUTF16("c-3"), GURL("http://c-3.com"));
model->AddURL(root, 3, ASCIIToUTF16("d"), GURL("http://d-0.com"));
}
virtual BookmarkEditorController* CreateController() {
return [[BookmarkEditorController alloc]
initWithParentWindow:test_window()
profile:profile()
parent:folder_bb_
node:bookmark_bb_3_
url:GURL()
title:base::string16()
configuration:BookmarkEditor::SHOW_TREE];
}
void SetUp() override {
CocoaProfileTest::SetUp();
ASSERT_TRUE(profile());
CreateModel();
controller_ = CreateController();
[controller_ runAsModalSheet];
}
void TearDown() override {
controller_ = NULL;
CocoaProfileTest::TearDown();
}
// After changing a node, pointers to the node may be invalid. This
// is because the node itself may not be updated; it may removed and
// a new one is added in that location. (Implementation detail of
// BookmarkEditorController). This method updates the class's
// bookmark_bb_3_ so that it points to the new node for testing.
void UpdateBB3() {
std::vector<const BookmarkNode*> nodes;
BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(profile());
model->GetNodesByURL(bb3_url_1_, &nodes);
if (nodes.empty())
model->GetNodesByURL(bb3_url_2_, &nodes);
DCHECK(nodes.size());
bookmark_bb_3_ = nodes[0];
}
};
TEST_F(BookmarkEditorControllerTreeTest, VerifyBookmarkTestModel) {
BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile());
model->root_node();
const BookmarkNode* root = model->bookmark_bar_node();
EXPECT_EQ(4, root->child_count());
const BookmarkNode* child = root->GetChild(0);
EXPECT_EQ(3, child->child_count());
const BookmarkNode* subchild = child->GetChild(0);
EXPECT_EQ(0, subchild->child_count());
subchild = child->GetChild(1);
EXPECT_EQ(0, subchild->child_count());
subchild = child->GetChild(2);
EXPECT_EQ(0, subchild->child_count());
child = root->GetChild(1);
EXPECT_EQ(4, child->child_count());
subchild = child->GetChild(0);
EXPECT_EQ(0, subchild->child_count());
subchild = child->GetChild(1);
EXPECT_EQ(5, subchild->child_count());
const BookmarkNode* subsubchild = subchild->GetChild(0);
EXPECT_EQ(0, subsubchild->child_count());
subsubchild = subchild->GetChild(1);
EXPECT_EQ(0, subsubchild->child_count());
subsubchild = subchild->GetChild(2);
EXPECT_EQ(0, subsubchild->child_count());
subsubchild = subchild->GetChild(3);
EXPECT_EQ(0, subsubchild->child_count());
subsubchild = subchild->GetChild(4);
EXPECT_EQ(0, subsubchild->child_count());
subchild = child->GetChild(2);
EXPECT_EQ(0, subchild->child_count());
subchild = child->GetChild(3);
EXPECT_EQ(0, subchild->child_count());
child = root->GetChild(2);
EXPECT_EQ(4, child->child_count());
subchild = child->GetChild(0);
EXPECT_EQ(0, subchild->child_count());
subchild = child->GetChild(1);
EXPECT_EQ(0, subchild->child_count());
subchild = child->GetChild(2);
EXPECT_EQ(0, subchild->child_count());
subchild = child->GetChild(3);
EXPECT_EQ(0, subchild->child_count());
child = root->GetChild(3);
EXPECT_EQ(0, child->child_count());
[controller_ cancel:nil];
}
TEST_F(BookmarkEditorControllerTreeTest, RenameBookmarkInPlace) {
const BookmarkNode* oldParent = bookmark_bb_3_->parent();
[controller_ setDisplayName:@"NEW NAME"];
[controller_ ok:nil];
UpdateBB3();
const BookmarkNode* newParent = bookmark_bb_3_->parent();
ASSERT_EQ(newParent, oldParent);
int childIndex = newParent->GetIndexOf(bookmark_bb_3_);
ASSERT_EQ(3, childIndex);
}
TEST_F(BookmarkEditorControllerTreeTest, ChangeBookmarkURLInPlace) {
const BookmarkNode* oldParent = bookmark_bb_3_->parent();
[controller_ setDisplayURL:@"https://bb-3.com"];
[controller_ ok:nil];
UpdateBB3();
const BookmarkNode* newParent = bookmark_bb_3_->parent();
ASSERT_EQ(newParent, oldParent);
int childIndex = newParent->GetIndexOf(bookmark_bb_3_);
ASSERT_EQ(3, childIndex);
}
TEST_F(BookmarkEditorControllerTreeTest, ChangeBookmarkFolder) {
[controller_ selectTestNodeInBrowser:folder_c_];
[controller_ ok:nil];
UpdateBB3();
const BookmarkNode* parent = bookmark_bb_3_->parent();
ASSERT_EQ(parent, folder_c_);
int childIndex = parent->GetIndexOf(bookmark_bb_3_);
ASSERT_EQ(4, childIndex);
}
TEST_F(BookmarkEditorControllerTreeTest, ChangeNameAndBookmarkFolder) {
[controller_ setDisplayName:@"NEW NAME"];
[controller_ selectTestNodeInBrowser:folder_c_];
[controller_ ok:nil];
UpdateBB3();
const BookmarkNode* parent = bookmark_bb_3_->parent();
ASSERT_EQ(parent, folder_c_);
int childIndex = parent->GetIndexOf(bookmark_bb_3_);
ASSERT_EQ(4, childIndex);
EXPECT_EQ(bookmark_bb_3_->GetTitle(), ASCIIToUTF16("NEW NAME"));
}
TEST_F(BookmarkEditorControllerTreeTest, AddFolderWithFolderSelected) {
// Folders are NOT added unless the OK button is pressed.
[controller_ newFolder:nil];
[controller_ cancel:nil];
EXPECT_EQ(5, folder_bb_->child_count());
}
class BookmarkEditorControllerTreeNoNodeTest :
public BookmarkEditorControllerTreeTest {
public:
BookmarkEditorController* CreateController() override {
return [[BookmarkEditorController alloc]
initWithParentWindow:test_window()
profile:profile()
parent:folder_bb_
node:nil
url:GURL()
title:base::string16()
configuration:BookmarkEditor::SHOW_TREE];
}
};
TEST_F(BookmarkEditorControllerTreeNoNodeTest, NewBookmarkNoNode) {
[controller_ setDisplayName:@"NEW BOOKMARK"];
[controller_ setDisplayURL:@"http://NEWURL.com"];
[controller_ ok:nil];
const BookmarkNode* new_node = folder_bb_->GetChild(5);
ASSERT_EQ(0, new_node->child_count());
EXPECT_EQ(new_node->GetTitle(), ASCIIToUTF16("NEW BOOKMARK"));
EXPECT_EQ(new_node->url(), GURL("http://NEWURL.com"));
}