OLD | NEW |
| (Empty) |
1 // Copyright 2013 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/undo/bookmark_undo_service.h" | |
6 | |
7 #include "base/strings/utf_string_conversions.h" | |
8 #include "components/bookmarks/browser/bookmark_model.h" | |
9 #include "components/bookmarks/test/bookmark_test_helpers.h" | |
10 #include "components/bookmarks/test/test_bookmark_client.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 using base::ASCIIToUTF16; | |
14 using bookmarks::BookmarkModel; | |
15 using bookmarks::BookmarkNode; | |
16 | |
17 namespace { | |
18 | |
19 class BookmarkUndoServiceTest : public testing::Test { | |
20 public: | |
21 BookmarkUndoServiceTest(); | |
22 | |
23 void SetUp() override; | |
24 void TearDown() override; | |
25 | |
26 BookmarkModel* GetModel(); | |
27 BookmarkUndoService* GetUndoService(); | |
28 | |
29 private: | |
30 scoped_ptr<bookmarks::TestBookmarkClient> test_bookmark_client_; | |
31 scoped_ptr<bookmarks::BookmarkModel> bookmark_model_; | |
32 scoped_ptr<BookmarkUndoService> bookmark_undo_service_; | |
33 | |
34 DISALLOW_COPY_AND_ASSIGN(BookmarkUndoServiceTest); | |
35 }; | |
36 | |
37 BookmarkUndoServiceTest::BookmarkUndoServiceTest() {} | |
38 | |
39 void BookmarkUndoServiceTest::SetUp() { | |
40 DCHECK(!test_bookmark_client_); | |
41 DCHECK(!bookmark_model_); | |
42 DCHECK(!bookmark_undo_service_); | |
43 test_bookmark_client_.reset(new bookmarks::TestBookmarkClient); | |
44 bookmark_model_ = test_bookmark_client_->CreateModel(); | |
45 bookmark_undo_service_.reset(new BookmarkUndoService); | |
46 bookmark_undo_service_->Start(bookmark_model_.get()); | |
47 bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model_.get()); | |
48 } | |
49 | |
50 BookmarkModel* BookmarkUndoServiceTest::GetModel() { | |
51 return bookmark_model_.get(); | |
52 } | |
53 | |
54 BookmarkUndoService* BookmarkUndoServiceTest::GetUndoService() { | |
55 return bookmark_undo_service_.get(); | |
56 } | |
57 | |
58 void BookmarkUndoServiceTest::TearDown() { | |
59 // Implement two-phase KeyedService shutdown for test KeyedServices. | |
60 bookmark_undo_service_->Shutdown(); | |
61 bookmark_model_->Shutdown(); | |
62 test_bookmark_client_->Shutdown(); | |
63 bookmark_undo_service_.reset(); | |
64 bookmark_model_.reset(); | |
65 test_bookmark_client_.reset(); | |
66 } | |
67 | |
68 TEST_F(BookmarkUndoServiceTest, AddBookmark) { | |
69 BookmarkModel* model = GetModel(); | |
70 BookmarkUndoService* undo_service = GetUndoService(); | |
71 | |
72 const BookmarkNode* parent = model->other_node(); | |
73 model->AddURL(parent, 0, ASCIIToUTF16("foo"), GURL("http://www.bar.com")); | |
74 | |
75 // Undo bookmark creation and test for no bookmarks. | |
76 undo_service->undo_manager()->Undo(); | |
77 EXPECT_EQ(0, model->other_node()->child_count()); | |
78 | |
79 // Redo bookmark creation and ensure bookmark information is valid. | |
80 undo_service->undo_manager()->Redo(); | |
81 const BookmarkNode* node = parent->GetChild(0); | |
82 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("foo")); | |
83 EXPECT_EQ(node->url(), GURL("http://www.bar.com")); | |
84 } | |
85 | |
86 // Test that a bookmark removal action can be undone and redone. | |
87 TEST_F(BookmarkUndoServiceTest, UndoBookmarkRemove) { | |
88 BookmarkModel* model = GetModel(); | |
89 BookmarkUndoService* undo_service = GetUndoService(); | |
90 | |
91 const BookmarkNode* parent = model->other_node(); | |
92 model->AddURL(parent, 0, ASCIIToUTF16("foo"), GURL("http://www.bar.com")); | |
93 model->Remove(parent, 0); | |
94 | |
95 EXPECT_EQ(2U, undo_service->undo_manager()->undo_count()); | |
96 EXPECT_EQ(0U, undo_service->undo_manager()->redo_count()); | |
97 | |
98 // Undo the deletion of the only bookmark and check the bookmark values. | |
99 undo_service->undo_manager()->Undo(); | |
100 EXPECT_EQ(1, model->other_node()->child_count()); | |
101 const BookmarkNode* node = parent->GetChild(0); | |
102 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("foo")); | |
103 EXPECT_EQ(node->url(), GURL("http://www.bar.com")); | |
104 | |
105 EXPECT_EQ(1U, undo_service->undo_manager()->undo_count()); | |
106 EXPECT_EQ(1U, undo_service->undo_manager()->redo_count()); | |
107 | |
108 // Redo the deletion and check that there are no bookmarks left. | |
109 undo_service->undo_manager()->Redo(); | |
110 EXPECT_EQ(0, model->other_node()->child_count()); | |
111 | |
112 EXPECT_EQ(2U, undo_service->undo_manager()->undo_count()); | |
113 EXPECT_EQ(0U, undo_service->undo_manager()->redo_count()); | |
114 } | |
115 | |
116 // Ensure the undo/redo works for editing of bookmark information grouped into | |
117 // one action. | |
118 TEST_F(BookmarkUndoServiceTest, UndoBookmarkGroupedAction) { | |
119 BookmarkModel* model = GetModel(); | |
120 BookmarkUndoService* undo_service = GetUndoService(); | |
121 | |
122 const BookmarkNode* n1 = model->AddURL(model->other_node(), | |
123 0, | |
124 ASCIIToUTF16("foo"), | |
125 GURL("http://www.foo.com")); | |
126 undo_service->undo_manager()->StartGroupingActions(); | |
127 model->SetTitle(n1, ASCIIToUTF16("bar")); | |
128 model->SetURL(n1, GURL("http://www.bar.com")); | |
129 undo_service->undo_manager()->EndGroupingActions(); | |
130 | |
131 EXPECT_EQ(2U, undo_service->undo_manager()->undo_count()); | |
132 EXPECT_EQ(0U, undo_service->undo_manager()->redo_count()); | |
133 | |
134 // Undo the modification of the bookmark and check for the original values. | |
135 undo_service->undo_manager()->Undo(); | |
136 EXPECT_EQ(1, model->other_node()->child_count()); | |
137 const BookmarkNode* node = model->other_node()->GetChild(0); | |
138 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("foo")); | |
139 EXPECT_EQ(node->url(), GURL("http://www.foo.com")); | |
140 | |
141 // Redo the modifications and ensure the newer values are present. | |
142 undo_service->undo_manager()->Redo(); | |
143 EXPECT_EQ(1, model->other_node()->child_count()); | |
144 node = model->other_node()->GetChild(0); | |
145 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("bar")); | |
146 EXPECT_EQ(node->url(), GURL("http://www.bar.com")); | |
147 | |
148 EXPECT_EQ(2U, undo_service->undo_manager()->undo_count()); | |
149 EXPECT_EQ(0U, undo_service->undo_manager()->redo_count()); | |
150 } | |
151 | |
152 // Test moving bookmarks within a folder and between folders. | |
153 TEST_F(BookmarkUndoServiceTest, UndoBookmarkMoveWithinFolder) { | |
154 BookmarkModel* model = GetModel(); | |
155 BookmarkUndoService* undo_service = GetUndoService(); | |
156 | |
157 const BookmarkNode* n1 = model->AddURL(model->other_node(), | |
158 0, | |
159 ASCIIToUTF16("foo"), | |
160 GURL("http://www.foo.com")); | |
161 const BookmarkNode* n2 = model->AddURL(model->other_node(), | |
162 1, | |
163 ASCIIToUTF16("moo"), | |
164 GURL("http://www.moo.com")); | |
165 const BookmarkNode* n3 = model->AddURL(model->other_node(), | |
166 2, | |
167 ASCIIToUTF16("bar"), | |
168 GURL("http://www.bar.com")); | |
169 model->Move(n1, model->other_node(), 3); | |
170 | |
171 // Undo the move and check that the nodes are in order. | |
172 undo_service->undo_manager()->Undo(); | |
173 EXPECT_EQ(model->other_node()->GetChild(0), n1); | |
174 EXPECT_EQ(model->other_node()->GetChild(1), n2); | |
175 EXPECT_EQ(model->other_node()->GetChild(2), n3); | |
176 | |
177 // Redo the move and check that the first node is in the last position. | |
178 undo_service->undo_manager()->Redo(); | |
179 EXPECT_EQ(model->other_node()->GetChild(0), n2); | |
180 EXPECT_EQ(model->other_node()->GetChild(1), n3); | |
181 EXPECT_EQ(model->other_node()->GetChild(2), n1); | |
182 } | |
183 | |
184 // Test undo of a bookmark moved to a different folder. | |
185 TEST_F(BookmarkUndoServiceTest, UndoBookmarkMoveToOtherFolder) { | |
186 BookmarkModel* model = GetModel(); | |
187 BookmarkUndoService* undo_service = GetUndoService(); | |
188 | |
189 const BookmarkNode* n1 = model->AddURL(model->other_node(), | |
190 0, | |
191 ASCIIToUTF16("foo"), | |
192 GURL("http://www.foo.com")); | |
193 const BookmarkNode* n2 = model->AddURL(model->other_node(), | |
194 1, | |
195 ASCIIToUTF16("moo"), | |
196 GURL("http://www.moo.com")); | |
197 const BookmarkNode* n3 = model->AddURL(model->other_node(), | |
198 2, | |
199 ASCIIToUTF16("bar"), | |
200 GURL("http://www.bar.com")); | |
201 const BookmarkNode* f1 = | |
202 model->AddFolder(model->other_node(), 3, ASCIIToUTF16("folder")); | |
203 model->Move(n3, f1, 0); | |
204 | |
205 // Undo the move and check that the bookmark and folder are in place. | |
206 undo_service->undo_manager()->Undo(); | |
207 ASSERT_EQ(4, model->other_node()->child_count()); | |
208 EXPECT_EQ(model->other_node()->GetChild(0), n1); | |
209 EXPECT_EQ(model->other_node()->GetChild(1), n2); | |
210 EXPECT_EQ(model->other_node()->GetChild(2), n3); | |
211 EXPECT_EQ(model->other_node()->GetChild(3), f1); | |
212 EXPECT_EQ(0, f1->child_count()); | |
213 | |
214 // Redo the move back into the folder and check validity. | |
215 undo_service->undo_manager()->Redo(); | |
216 ASSERT_EQ(3, model->other_node()->child_count()); | |
217 EXPECT_EQ(model->other_node()->GetChild(0), n1); | |
218 EXPECT_EQ(model->other_node()->GetChild(1), n2); | |
219 EXPECT_EQ(model->other_node()->GetChild(2), f1); | |
220 ASSERT_EQ(1, f1->child_count()); | |
221 EXPECT_EQ(f1->GetChild(0), n3); | |
222 } | |
223 | |
224 // Tests the handling of multiple modifications that include renumbering of the | |
225 // bookmark identifiers. | |
226 TEST_F(BookmarkUndoServiceTest, UndoBookmarkRenameDelete) { | |
227 BookmarkModel* model = GetModel(); | |
228 BookmarkUndoService* undo_service = GetUndoService(); | |
229 | |
230 const BookmarkNode* f1 = model->AddFolder(model->other_node(), | |
231 0, | |
232 ASCIIToUTF16("folder")); | |
233 model->AddURL(f1, 0, ASCIIToUTF16("foo"), GURL("http://www.foo.com")); | |
234 model->SetTitle(f1, ASCIIToUTF16("Renamed")); | |
235 model->Remove(model->other_node(), 0); | |
236 | |
237 // Undo the folder removal and ensure the folder and bookmark were restored. | |
238 undo_service->undo_manager()->Undo(); | |
239 ASSERT_EQ(1, model->other_node()->child_count()); | |
240 ASSERT_EQ(1, model->other_node()->GetChild(0)->child_count()); | |
241 const BookmarkNode* node = model->other_node()->GetChild(0); | |
242 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("Renamed")); | |
243 | |
244 node = model->other_node()->GetChild(0)->GetChild(0); | |
245 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("foo")); | |
246 EXPECT_EQ(node->url(), GURL("http://www.foo.com")); | |
247 | |
248 // Undo the title change and ensure the folder was updated even though the | |
249 // id has changed. | |
250 undo_service->undo_manager()->Undo(); | |
251 node = model->other_node()->GetChild(0); | |
252 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("folder")); | |
253 | |
254 // Undo bookmark creation and test for removal of bookmark. | |
255 undo_service->undo_manager()->Undo(); | |
256 ASSERT_EQ(0, model->other_node()->GetChild(0)->child_count()); | |
257 | |
258 // Undo folder creation and confirm the bookmark model is empty. | |
259 undo_service->undo_manager()->Undo(); | |
260 ASSERT_EQ(0, model->other_node()->child_count()); | |
261 | |
262 // Redo all the actions and ensure the folder and bookmark are restored. | |
263 undo_service->undo_manager()->Redo(); // folder creation | |
264 undo_service->undo_manager()->Redo(); // bookmark creation | |
265 undo_service->undo_manager()->Redo(); // bookmark title change | |
266 ASSERT_EQ(1, model->other_node()->child_count()); | |
267 ASSERT_EQ(1, model->other_node()->GetChild(0)->child_count()); | |
268 node = model->other_node()->GetChild(0); | |
269 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("Renamed")); | |
270 node = model->other_node()->GetChild(0)->GetChild(0); | |
271 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("foo")); | |
272 EXPECT_EQ(node->url(), GURL("http://www.foo.com")); | |
273 | |
274 undo_service->undo_manager()->Redo(); // folder deletion | |
275 EXPECT_EQ(0, model->other_node()->child_count()); | |
276 } | |
277 | |
278 // Test the undo of SortChildren and ReorderChildren. | |
279 TEST_F(BookmarkUndoServiceTest, UndoBookmarkReorder) { | |
280 BookmarkModel* model = GetModel(); | |
281 BookmarkUndoService* undo_service = GetUndoService(); | |
282 | |
283 const BookmarkNode* parent = model->other_node(); | |
284 model->AddURL(parent, 0, ASCIIToUTF16("foo"), GURL("http://www.foo.com")); | |
285 model->AddURL(parent, 1, ASCIIToUTF16("moo"), GURL("http://www.moo.com")); | |
286 model->AddURL(parent, 2, ASCIIToUTF16("bar"), GURL("http://www.bar.com")); | |
287 model->SortChildren(parent); | |
288 | |
289 // Test the undo of SortChildren. | |
290 undo_service->undo_manager()->Undo(); | |
291 const BookmarkNode* node = parent->GetChild(0); | |
292 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("foo")); | |
293 EXPECT_EQ(node->url(), GURL("http://www.foo.com")); | |
294 | |
295 node = parent->GetChild(1); | |
296 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("moo")); | |
297 EXPECT_EQ(node->url(), GURL("http://www.moo.com")); | |
298 | |
299 node = parent->GetChild(2); | |
300 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("bar")); | |
301 EXPECT_EQ(node->url(), GURL("http://www.bar.com")); | |
302 | |
303 // Test the redo of SortChildren. | |
304 undo_service->undo_manager()->Redo(); | |
305 node = parent->GetChild(0); | |
306 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("bar")); | |
307 EXPECT_EQ(node->url(), GURL("http://www.bar.com")); | |
308 | |
309 node = parent->GetChild(1); | |
310 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("foo")); | |
311 EXPECT_EQ(node->url(), GURL("http://www.foo.com")); | |
312 | |
313 node = parent->GetChild(2); | |
314 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("moo")); | |
315 EXPECT_EQ(node->url(), GURL("http://www.moo.com")); | |
316 | |
317 } | |
318 | |
319 TEST_F(BookmarkUndoServiceTest, UndoBookmarkRemoveAll) { | |
320 BookmarkModel* model = GetModel(); | |
321 BookmarkUndoService* undo_service = GetUndoService(); | |
322 | |
323 // Setup bookmarks in the Other Bookmarks and the Bookmark Bar. | |
324 const BookmarkNode* new_folder; | |
325 const BookmarkNode* parent = model->other_node(); | |
326 model->AddURL(parent, 0, ASCIIToUTF16("foo"), GURL("http://www.google.com")); | |
327 new_folder= model->AddFolder(parent, 1, ASCIIToUTF16("folder")); | |
328 model->AddURL(new_folder, 0, ASCIIToUTF16("bar"), GURL("http://www.bar.com")); | |
329 | |
330 parent = model->bookmark_bar_node(); | |
331 model->AddURL(parent, 0, ASCIIToUTF16("a"), GURL("http://www.a.com")); | |
332 new_folder = model->AddFolder(parent, 1, ASCIIToUTF16("folder")); | |
333 model->AddURL(new_folder, 0, ASCIIToUTF16("b"), GURL("http://www.b.com")); | |
334 | |
335 model->RemoveAllUserBookmarks(); | |
336 | |
337 // Test that the undo of RemoveAllUserBookmarks restores all folders and | |
338 // bookmarks. | |
339 undo_service->undo_manager()->Undo(); | |
340 | |
341 ASSERT_EQ(2, model->other_node()->child_count()); | |
342 EXPECT_EQ(1, model->other_node()->GetChild(1)->child_count()); | |
343 const BookmarkNode* node = model->other_node()->GetChild(1)->GetChild(0); | |
344 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("bar")); | |
345 EXPECT_EQ(node->url(), GURL("http://www.bar.com")); | |
346 | |
347 ASSERT_EQ(2, model->bookmark_bar_node()->child_count()); | |
348 EXPECT_EQ(1, model->bookmark_bar_node()->GetChild(1)->child_count()); | |
349 node = model->bookmark_bar_node()->GetChild(1)->GetChild(0); | |
350 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("b")); | |
351 EXPECT_EQ(node->url(), GURL("http://www.b.com")); | |
352 | |
353 // Test that the redo removes all folders and bookmarks. | |
354 undo_service->undo_manager()->Redo(); | |
355 EXPECT_EQ(0, model->other_node()->child_count()); | |
356 EXPECT_EQ(0, model->bookmark_bar_node()->child_count()); | |
357 } | |
358 | |
359 TEST_F(BookmarkUndoServiceTest, UndoRemoveFolderWithBookmarks) { | |
360 BookmarkModel* model = GetModel(); | |
361 BookmarkUndoService* undo_service = GetUndoService(); | |
362 | |
363 // Setup bookmarks in the Other Bookmarks. | |
364 const BookmarkNode* new_folder; | |
365 const BookmarkNode* parent = model->other_node(); | |
366 new_folder = model->AddFolder(parent, 0, ASCIIToUTF16("folder")); | |
367 model->AddURL(new_folder, 0, ASCIIToUTF16("bar"), GURL("http://www.bar.com")); | |
368 | |
369 model->Remove(parent, 0); | |
370 | |
371 // Test that the undo restores the bookmark and folder. | |
372 undo_service->undo_manager()->Undo(); | |
373 | |
374 ASSERT_EQ(1, model->other_node()->child_count()); | |
375 new_folder = model->other_node()->GetChild(0); | |
376 EXPECT_EQ(1, new_folder->child_count()); | |
377 const BookmarkNode* node = new_folder->GetChild(0); | |
378 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("bar")); | |
379 EXPECT_EQ(node->url(), GURL("http://www.bar.com")); | |
380 | |
381 // Test that the redo restores the bookmark and folder. | |
382 undo_service->undo_manager()->Redo(); | |
383 | |
384 ASSERT_EQ(0, model->other_node()->child_count()); | |
385 | |
386 // Test that the undo after a redo restores the bookmark and folder. | |
387 undo_service->undo_manager()->Undo(); | |
388 | |
389 ASSERT_EQ(1, model->other_node()->child_count()); | |
390 new_folder = model->other_node()->GetChild(0); | |
391 EXPECT_EQ(1, new_folder->child_count()); | |
392 node = new_folder->GetChild(0); | |
393 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("bar")); | |
394 EXPECT_EQ(node->url(), GURL("http://www.bar.com")); | |
395 } | |
396 | |
397 TEST_F(BookmarkUndoServiceTest, TestUpperLimit) { | |
398 BookmarkModel* model = GetModel(); | |
399 BookmarkUndoService* undo_service = GetUndoService(); | |
400 | |
401 // This maximum is set in undo_manager.cc | |
402 const size_t kMaxUndoGroups = 100; | |
403 | |
404 const BookmarkNode* parent = model->other_node(); | |
405 model->AddURL(parent, 0, ASCIIToUTF16("foo"), GURL("http://www.foo.com")); | |
406 for (size_t i = 1; i < kMaxUndoGroups + 1; ++i) | |
407 model->AddURL(parent, i, ASCIIToUTF16("bar"), GURL("http://www.bar.com")); | |
408 | |
409 EXPECT_EQ(kMaxUndoGroups, undo_service->undo_manager()->undo_count()); | |
410 | |
411 // Undo as many operations as possible. | |
412 while (undo_service->undo_manager()->undo_count()) | |
413 undo_service->undo_manager()->Undo(); | |
414 | |
415 EXPECT_EQ(1, parent->child_count()); | |
416 const BookmarkNode* node = model->other_node()->GetChild(0); | |
417 EXPECT_EQ(node->GetTitle(), ASCIIToUTF16("foo")); | |
418 EXPECT_EQ(node->url(), GURL("http://www.foo.com")); | |
419 } | |
420 | |
421 } // namespace | |
OLD | NEW |