Home | History | Annotate | Download | only in bookmarks
      1 // Copyright (c) 2011 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 <string>
      6 
      7 #include "base/message_loop.h"
      8 #include "base/string_util.h"
      9 #include "base/utf_string_conversions.h"
     10 #include "chrome/browser/bookmarks/bookmark_model.h"
     11 #include "chrome/browser/profiles/profile.h"
     12 #include "chrome/browser/ui/views/bookmarks/bookmark_editor_view.h"
     13 #include "chrome/test/testing_profile.h"
     14 #include "content/browser/browser_thread.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 using base::Time;
     18 using base::TimeDelta;
     19 
     20 // Base class for bookmark editor tests. Creates a BookmarkModel and populates
     21 // it with test data.
     22 class BookmarkEditorViewTest : public testing::Test {
     23  public:
     24   BookmarkEditorViewTest()
     25       : ui_thread_(BrowserThread::UI, &message_loop_),
     26         file_thread_(BrowserThread::FILE, &message_loop_),
     27         model_(NULL) {
     28   }
     29 
     30   virtual void SetUp() {
     31     profile_.reset(new TestingProfile());
     32     profile_->CreateBookmarkModel(true);
     33 
     34     model_ = profile_->GetBookmarkModel();
     35     profile_->BlockUntilBookmarkModelLoaded();
     36 
     37     AddTestData();
     38   }
     39 
     40   virtual void TearDown() {
     41   }
     42 
     43  protected:
     44   std::string base_path() const { return "file:///c:/tmp/"; }
     45 
     46   const BookmarkNode* GetNode(const std::string& name) {
     47     return model_->GetMostRecentlyAddedNodeForURL(GURL(base_path() + name));
     48   }
     49 
     50   BookmarkNode* GetMutableNode(const std::string& name) {
     51     return const_cast<BookmarkNode*>(GetNode(name));
     52   }
     53 
     54   BookmarkEditorView::EditorTreeModel* editor_tree_model() {
     55     return editor_->tree_model_.get();
     56   }
     57 
     58   void CreateEditor(Profile* profile,
     59                     const BookmarkNode* parent,
     60                     const BookmarkEditor::EditDetails& details,
     61                     BookmarkEditor::Configuration configuration) {
     62     editor_.reset(new BookmarkEditorView(profile, parent, details,
     63                                          configuration));
     64   }
     65 
     66   void SetTitleText(const std::wstring& title) {
     67     editor_->title_tf_.SetText(title);
     68   }
     69 
     70   void SetURLText(const std::wstring& text) {
     71     editor_->url_tf_.SetText(text);
     72   }
     73 
     74   void ApplyEdits(BookmarkEditorView::EditorNode* node) {
     75     editor_->ApplyEdits(node);
     76   }
     77 
     78   BookmarkEditorView::EditorNode* AddNewFolder(
     79       BookmarkEditorView::EditorNode* parent) {
     80     return editor_->AddNewFolder(parent);
     81   }
     82 
     83   bool URLTFHasParent() {
     84     return editor_->url_tf_.parent();
     85   }
     86 
     87   MessageLoopForUI message_loop_;
     88   BrowserThread ui_thread_;
     89   BrowserThread file_thread_;
     90 
     91   BookmarkModel* model_;
     92   scoped_ptr<TestingProfile> profile_;
     93 
     94  private:
     95   // Creates the following structure:
     96   // bookmark bar node
     97   //   a
     98   //   F1
     99   //    f1a
    100   //    F11
    101   //     f11a
    102   //   F2
    103   // other node
    104   //   oa
    105   //   OF1
    106   //     of1a
    107   void AddTestData() {
    108     std::string test_base = base_path();
    109 
    110     model_->AddURL(model_->GetBookmarkBarNode(), 0, ASCIIToUTF16("a"),
    111                    GURL(test_base + "a"));
    112     const BookmarkNode* f1 =
    113         model_->AddFolder(model_->GetBookmarkBarNode(), 1, ASCIIToUTF16("F1"));
    114     model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
    115     const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
    116     model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
    117     model_->AddFolder(model_->GetBookmarkBarNode(), 2, ASCIIToUTF16("F2"));
    118 
    119     // Children of the other node.
    120     model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
    121                    GURL(test_base + "oa"));
    122     const BookmarkNode* of1 =
    123         model_->AddFolder(model_->other_node(), 1, ASCIIToUTF16("OF1"));
    124     model_->AddURL(of1, 0, ASCIIToUTF16("of1a"), GURL(test_base + "of1a"));
    125   }
    126 
    127   scoped_ptr<BookmarkEditorView> editor_;
    128 };
    129 
    130 // Makes sure the tree model matches that of the bookmark bar model.
    131 TEST_F(BookmarkEditorViewTest, ModelsMatch) {
    132   CreateEditor(profile_.get(), NULL, BookmarkEditor::EditDetails(),
    133                BookmarkEditorView::SHOW_TREE);
    134   BookmarkEditorView::EditorNode* editor_root = editor_tree_model()->GetRoot();
    135   // The root should have two children, one for the bookmark bar node,
    136   // the other for the 'other bookmarks' folder.
    137   ASSERT_EQ(2, editor_root->child_count());
    138 
    139   BookmarkEditorView::EditorNode* bb_node = editor_root->GetChild(0);
    140   // The root should have 2 nodes: folder F1 and F2.
    141   ASSERT_EQ(2, bb_node->child_count());
    142   ASSERT_EQ(ASCIIToUTF16("F1"), bb_node->GetChild(0)->GetTitle());
    143   ASSERT_EQ(ASCIIToUTF16("F2"), bb_node->GetChild(1)->GetTitle());
    144 
    145   // F1 should have one child, F11
    146   ASSERT_EQ(1, bb_node->GetChild(0)->child_count());
    147   ASSERT_EQ(ASCIIToUTF16("F11"), bb_node->GetChild(0)->GetChild(0)->GetTitle());
    148 
    149   BookmarkEditorView::EditorNode* other_node = editor_root->GetChild(1);
    150   // Other node should have one child (OF1).
    151   ASSERT_EQ(1, other_node->child_count());
    152   ASSERT_EQ(ASCIIToUTF16("OF1"), other_node->GetChild(0)->GetTitle());
    153 }
    154 
    155 // Changes the title and makes sure parent/visual order doesn't change.
    156 TEST_F(BookmarkEditorViewTest, EditTitleKeepsPosition) {
    157   CreateEditor(profile_.get(), NULL, BookmarkEditor::EditDetails(GetNode("a")),
    158                BookmarkEditorView::SHOW_TREE);
    159   SetTitleText(L"new_a");
    160 
    161   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0));
    162 
    163   const BookmarkNode* bb_node =
    164       profile_->GetBookmarkModel()->GetBookmarkBarNode();
    165   ASSERT_EQ(ASCIIToUTF16("new_a"), bb_node->GetChild(0)->GetTitle());
    166   // The URL shouldn't have changed.
    167   ASSERT_TRUE(GURL(base_path() + "a") == bb_node->GetChild(0)->GetURL());
    168 }
    169 
    170 // Changes the url and makes sure parent/visual order doesn't change.
    171 TEST_F(BookmarkEditorViewTest, EditURLKeepsPosition) {
    172   Time node_time = Time::Now() + TimeDelta::FromDays(2);
    173   GetMutableNode("a")->set_date_added(node_time);
    174   CreateEditor(profile_.get(), NULL, BookmarkEditor::EditDetails(GetNode("a")),
    175                BookmarkEditorView::SHOW_TREE);
    176 
    177   SetURLText(UTF8ToWide(GURL(base_path() + "new_a").spec()));
    178 
    179   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0));
    180 
    181   const BookmarkNode* bb_node =
    182       profile_->GetBookmarkModel()->GetBookmarkBarNode();
    183   ASSERT_EQ(ASCIIToUTF16("a"), bb_node->GetChild(0)->GetTitle());
    184   // The URL should have changed.
    185   ASSERT_TRUE(GURL(base_path() + "new_a") == bb_node->GetChild(0)->GetURL());
    186   ASSERT_TRUE(node_time == bb_node->GetChild(0)->date_added());
    187 }
    188 
    189 // Moves 'a' to be a child of the other node.
    190 TEST_F(BookmarkEditorViewTest, ChangeParent) {
    191   CreateEditor(profile_.get(), NULL, BookmarkEditor::EditDetails(GetNode("a")),
    192                BookmarkEditorView::SHOW_TREE);
    193 
    194   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1));
    195 
    196   const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
    197   ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
    198   ASSERT_TRUE(GURL(base_path() + "a") == other_node->GetChild(2)->GetURL());
    199 }
    200 
    201 // Moves 'a' to be a child of the other node and changes its url to new_a.
    202 TEST_F(BookmarkEditorViewTest, ChangeParentAndURL) {
    203   Time node_time = Time::Now() + TimeDelta::FromDays(2);
    204   GetMutableNode("a")->set_date_added(node_time);
    205   CreateEditor(profile_.get(), NULL, BookmarkEditor::EditDetails(GetNode("a")),
    206                BookmarkEditorView::SHOW_TREE);
    207 
    208   SetURLText(UTF8ToWide(GURL(base_path() + "new_a").spec()));
    209 
    210   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1));
    211 
    212   const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
    213   ASSERT_EQ(ASCIIToUTF16("a"), other_node->GetChild(2)->GetTitle());
    214   ASSERT_TRUE(GURL(base_path() + "new_a") == other_node->GetChild(2)->GetURL());
    215   ASSERT_TRUE(node_time == other_node->GetChild(2)->date_added());
    216 }
    217 
    218 // Creates a new folder and moves a node to it.
    219 TEST_F(BookmarkEditorViewTest, MoveToNewParent) {
    220   CreateEditor(profile_.get(), NULL, BookmarkEditor::EditDetails(GetNode("a")),
    221                BookmarkEditorView::SHOW_TREE);
    222 
    223   // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21".
    224   BookmarkEditorView::EditorNode* f2 =
    225       editor_tree_model()->GetRoot()->GetChild(0)->GetChild(1);
    226   BookmarkEditorView::EditorNode* f21 = AddNewFolder(f2);
    227   f21->set_title(ASCIIToUTF16("F21"));
    228   BookmarkEditorView::EditorNode* f211 = AddNewFolder(f21);
    229   f211->set_title(ASCIIToUTF16("F211"));
    230 
    231   // Parent the node to "F21".
    232   ApplyEdits(f2);
    233 
    234   const BookmarkNode* bb_node =
    235       profile_->GetBookmarkModel()->GetBookmarkBarNode();
    236   const BookmarkNode* mf2 = bb_node->GetChild(1);
    237 
    238   // F2 in the model should have two children now: F21 and the node edited.
    239   ASSERT_EQ(2, mf2->child_count());
    240   // F21 should be first.
    241   ASSERT_EQ(ASCIIToUTF16("F21"), mf2->GetChild(0)->GetTitle());
    242   // Then a.
    243   ASSERT_EQ(ASCIIToUTF16("a"), mf2->GetChild(1)->GetTitle());
    244 
    245   // F21 should have one child, F211.
    246   const BookmarkNode* mf21 = mf2->GetChild(0);
    247   ASSERT_EQ(1, mf21->child_count());
    248   ASSERT_EQ(ASCIIToUTF16("F211"), mf21->GetChild(0)->GetTitle());
    249 }
    250 
    251 // Brings up the editor, creating a new URL on the bookmark bar.
    252 TEST_F(BookmarkEditorViewTest, NewURL) {
    253   CreateEditor(profile_.get(), NULL, BookmarkEditor::EditDetails(),
    254                BookmarkEditorView::SHOW_TREE);
    255 
    256   SetURLText(UTF8ToWide(GURL(base_path() + "a").spec()));
    257   SetTitleText(L"new_a");
    258 
    259   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0));
    260 
    261   const BookmarkNode* bb_node =
    262       profile_->GetBookmarkModel()->GetBookmarkBarNode();
    263   ASSERT_EQ(4, bb_node->child_count());
    264 
    265   const BookmarkNode* new_node = bb_node->GetChild(3);
    266 
    267   EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
    268   EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
    269 }
    270 
    271 // Brings up the editor with no tree and modifies the url.
    272 TEST_F(BookmarkEditorViewTest, ChangeURLNoTree) {
    273   CreateEditor(profile_.get(), NULL,
    274                BookmarkEditor::EditDetails(model_->other_node()->GetChild(0)),
    275                BookmarkEditorView::NO_TREE);
    276 
    277   SetURLText(UTF8ToWide(GURL(base_path() + "a").spec()));
    278   SetTitleText(L"new_a");
    279 
    280   ApplyEdits(NULL);
    281 
    282   const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
    283   ASSERT_EQ(2, other_node->child_count());
    284 
    285   const BookmarkNode* new_node = other_node->GetChild(0);
    286 
    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 only the title.
    292 TEST_F(BookmarkEditorViewTest, ChangeTitleNoTree) {
    293   CreateEditor(profile_.get(), NULL,
    294                BookmarkEditor::EditDetails(model_->other_node()->GetChild(0)),
    295                BookmarkEditorView::NO_TREE);
    296 
    297   SetTitleText(L"new_a");
    298 
    299   ApplyEdits(NULL);
    300 
    301   const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
    302   ASSERT_EQ(2, other_node->child_count());
    303 
    304   const BookmarkNode* new_node = other_node->GetChild(0);
    305 
    306   EXPECT_EQ(ASCIIToUTF16("new_a"), new_node->GetTitle());
    307 }
    308 
    309 // Creates a new folder.
    310 TEST_F(BookmarkEditorViewTest, NewFolder) {
    311   BookmarkEditor::EditDetails details;
    312   details.urls.push_back(std::make_pair(GURL(base_path() + "x"),
    313                                         ASCIIToUTF16("z")));
    314   details.type = BookmarkEditor::EditDetails::NEW_FOLDER;
    315   CreateEditor(profile_.get(), model_->GetBookmarkBarNode(),
    316                details, BookmarkEditorView::SHOW_TREE);
    317 
    318   // The url field shouldn't be visible.
    319   EXPECT_FALSE(URLTFHasParent());
    320   SetTitleText(L"new_F");
    321 
    322   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0));
    323 
    324   // Make sure the folder was created.
    325   ASSERT_EQ(4, model_->GetBookmarkBarNode()->child_count());
    326   const BookmarkNode* new_node =
    327       model_->GetBookmarkBarNode()->GetChild(3);
    328   EXPECT_EQ(BookmarkNode::FOLDER, new_node->type());
    329   EXPECT_EQ(ASCIIToUTF16("new_F"), new_node->GetTitle());
    330   // The node should have one child.
    331   ASSERT_EQ(1, new_node->child_count());
    332   const BookmarkNode* new_child = new_node->GetChild(0);
    333   // Make sure the child url/title match.
    334   EXPECT_EQ(BookmarkNode::URL, new_child->type());
    335   EXPECT_EQ(WideToUTF16Hack(details.urls[0].second), new_child->GetTitle());
    336   EXPECT_EQ(details.urls[0].first, new_child->GetURL());
    337 }
    338 
    339 // Creates a new folder and selects a different folder for the folder to appear
    340 // in then the editor is initially created showing.
    341 TEST_F(BookmarkEditorViewTest, MoveFolder) {
    342   BookmarkEditor::EditDetails details;
    343   details.urls.push_back(std::make_pair(GURL(base_path() + "x"),
    344                                         ASCIIToUTF16("z")));
    345   details.type = BookmarkEditor::EditDetails::NEW_FOLDER;
    346   CreateEditor(profile_.get(), model_->GetBookmarkBarNode(),
    347                details, BookmarkEditorView::SHOW_TREE);
    348 
    349   SetTitleText(L"new_F");
    350 
    351   // Create the folder in the 'other' folder.
    352   ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1));
    353 
    354   // Make sure the folder we edited is still there.
    355   ASSERT_EQ(3, model_->other_node()->child_count());
    356   const BookmarkNode* new_node = model_->other_node()->GetChild(2);
    357   EXPECT_EQ(BookmarkNode::FOLDER, new_node->type());
    358   EXPECT_EQ(ASCIIToUTF16("new_F"), new_node->GetTitle());
    359   // The node should have one child.
    360   ASSERT_EQ(1, new_node->child_count());
    361   const BookmarkNode* new_child = new_node->GetChild(0);
    362   // Make sure the child url/title match.
    363   EXPECT_EQ(BookmarkNode::URL, new_child->type());
    364   EXPECT_EQ(WideToUTF16Hack(details.urls[0].second), new_child->GetTitle());
    365   EXPECT_EQ(details.urls[0].first, new_child->GetURL());
    366 }
    367