Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(951)

Side by Side Diff: ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm

Issue 2586993002: Upstream Chrome on iOS source code [3/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 <vector>
6
7 #import <EarlGrey/EarlGrey.h>
8 #import <UIKit/UIKit.h>
9 #import <XCTest/XCTest.h>
10
11 #include "base/strings/sys_string_conversions.h"
12 #include "components/bookmarks/browser/bookmark_model.h"
13 #include "components/bookmarks/browser/titled_url_match.h"
14 #include "components/prefs/pref_service.h"
15 #include "components/strings/grit/components_strings.h"
16 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
17 #include "ios/chrome/browser/bookmarks/bookmarks_utils.h"
18 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
19 #include "ios/chrome/browser/experimental_flags.h"
20 #include "ios/chrome/browser/pref_names.h"
21 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
22 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
23 #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
24 #import "ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h"
25 #import "ios/chrome/browser/ui/uikit_ui_util.h"
26 #include "ios/chrome/grit/ios_strings.h"
27 #import "ios/chrome/test/app/bookmarks_test_util.h"
28 #import "ios/chrome/test/app/chrome_test_util.h"
29 #include "ios/chrome/test/app/navigation_test_util.h"
30 #import "ios/chrome/test/app/tab_test_util.h"
31 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
32 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
33 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
34 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
35 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
36 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service. h"
37 #import "ios/testing/wait_util.h"
38 #import "ios/web/public/test/http_server.h"
39 #include "ios/web/public/test/http_server_util.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/base/models/tree_node_iterator.h"
42 #include "url/gurl.h"
43
44 using chrome_test_util::buttonWithAccessibilityLabel;
45 using chrome_test_util::buttonWithAccessibilityLabelId;
46
47 namespace {
48 // TODO(crbug.com/616929): Move common matchers that are useful across tests
49 // into a shared location.
50
51 // Matcher for bookmarks tool tip star.
52 id<GREYMatcher> starButton() {
53 return buttonWithAccessibilityLabelId(IDS_TOOLTIP_STAR);
54 }
55
56 // Matcher for the button to add bookmark.
57 id<GREYMatcher> addBookmarkButton() {
58 return buttonWithAccessibilityLabelId(IDS_BOOKMARK_ADD_EDITOR_TITLE);
59 }
60
61 // Matcher for the lit star buttom on iPhone that will open the edit button
62 // screen.
63 id<GREYMatcher> litStarButtoniPhone() {
64 return buttonWithAccessibilityLabelId(IDS_IOS_TOOLS_MENU_EDIT_BOOKMARK);
65 }
66
67 // Matcher for the button to edit bookmark.
68 id<GREYMatcher> editBookmarkButton() {
69 return buttonWithAccessibilityLabelId(IDS_IOS_BOOKMARK_ACTION_EDIT);
70 }
71
72 // Matcher for the button to close the tools menu.
73 id<GREYMatcher> closeToolsMenuButton() {
74 NSString* closeMenuButtonText =
75 l10n_util::GetNSString(IDS_IOS_TOOLBAR_CLOSE_MENU);
76 return grey_allOf(grey_accessibilityID(kToolbarToolsMenuButtonIdentifier),
77 grey_accessibilityLabel(closeMenuButtonText), nil);
78 }
79
80 // Matcher for the Done button on the bookmarks UI.
81 id<GREYMatcher> bookmarksDoneButton() {
82 return grey_allOf(
83 buttonWithAccessibilityLabelId(IDS_IOS_BOOKMARK_DONE_BUTTON),
84 grey_not(grey_accessibilityTrait(UIAccessibilityTraitKeyboardKey)), nil);
85 }
86
87 // Types of actions possible in the contextual action sheet.
88 typedef NS_ENUM(NSUInteger, Action) {
89 ActionSelect,
90 ActionEdit,
91 ActionMove,
92 ActionDelete,
93 };
94
95 // Matcher for the action sheet's buttons.
96 id<GREYMatcher> actionSheet(Action action) {
97 int accessibilityLabelMessageID;
98 switch (action) {
99 case ActionSelect:
100 accessibilityLabelMessageID = IDS_IOS_BOOKMARK_ACTION_SELECT;
101 break;
102 case ActionEdit:
103 accessibilityLabelMessageID = IDS_IOS_BOOKMARK_ACTION_EDIT;
104 break;
105 case ActionMove:
106 accessibilityLabelMessageID = IDS_IOS_BOOKMARK_ACTION_MOVE;
107 break;
108 case ActionDelete:
109 accessibilityLabelMessageID = IDS_IOS_BOOKMARK_ACTION_DELETE;
110 break;
111 }
112
113 return grey_allOf(grey_accessibilityLabel(
114 l10n_util::GetNSString(accessibilityLabelMessageID)),
115 grey_accessibilityTrait(UIAccessibilityTraitButton),
116 grey_not(grey_accessibilityID(@"Edit_editing_bar")), nil);
117 }
118
119 } // namespace
120
121 // Bookmark integration tests for Chrome.
122 @interface BookmarksTestCase : ChromeTestCase
123 @end
124
125 @implementation BookmarksTestCase
126
127 - (void)setUp {
128 [super setUp];
129 // Wait for bookmark model to be loaded.
130 GREYAssert(testing::WaitUntilConditionOrTimeout(
131 testing::kWaitForUIElementTimeout,
132 ^{
133 return chrome_test_util::BookmarksLoaded();
134 }),
135 @"Bookmark model did not load");
136 GREYAssert(chrome_test_util::ClearBookmarks(),
137 @"Not all bookmarks were removed.");
138 }
139
140 // Tear down called once per test.
141 - (void)tearDown {
142 [super tearDown];
143 GREYAssert(chrome_test_util::ClearBookmarks(),
144 @"Not all bookmarks were removed.");
145 }
146
147 #pragma mark Tests
148
149 // Verifies that adding a bookmark and removing a bookmark via the UI properly
150 // updates the BookmarkModel.
151 - (void)testAddRemoveBookmark {
152 const GURL bookmarkedURL = web::test::HttpServer::MakeUrl(
153 "http://ios/testing/data/http_server_files/pony.html");
154 std::string expectedURLContent = bookmarkedURL.GetContent();
155 NSString* bookmarkTitle = @"my bookmark";
156
157 [ChromeEarlGrey loadURL:bookmarkedURL];
158 [[EarlGrey selectElementWithMatcher:chrome_test_util::omniboxText(
159 expectedURLContent)]
160 assertWithMatcher:grey_notNil()];
161
162 // Add the bookmark from the UI.
163 [[self class] bookmarkCurrentTabWithTitle:bookmarkTitle];
164
165 // Verify the bookmark is set.
166 [[self class] assertBookmarksWithTitle:bookmarkTitle expectedCount:1];
167
168 NSString* const kStarLitLabel =
169 !IsCompact() ? l10n_util::GetNSString(IDS_TOOLTIP_STAR)
170 : l10n_util::GetNSString(IDS_IOS_BOOKMARK_EDIT_SCREEN_TITLE);
171 // Verify the star is lit.
172 if (IsCompact()) {
173 [ChromeEarlGreyUI openToolsMenu];
174 }
175 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kStarLitLabel)]
176 assertWithMatcher:grey_notNil()];
177
178 // Clear the bookmark via the UI.
179 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kStarLitLabel)]
180 performAction:grey_tap()];
181 [[EarlGrey selectElementWithMatcher:actionSheet(ActionDelete)]
182 performAction:grey_tap()];
183
184 // Verify the bookmark is not in the BookmarkModel.
185 [[self class] assertBookmarksWithTitle:bookmarkTitle expectedCount:0];
186
187 NSString* const kStarUnlitLabel =
188 !IsCompact() ? l10n_util::GetNSString(IDS_TOOLTIP_STAR)
189 : l10n_util::GetNSString(IDS_BOOKMARK_ADD_EDITOR_TITLE);
190
191 // Verify the star is not lit.
192 if (IsCompact()) {
193 [ChromeEarlGreyUI openToolsMenu];
194 }
195 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kStarUnlitLabel)]
196 assertWithMatcher:grey_notNil()];
197
198 // TODO(crbug.com/617652): This code should be removed when a common helper
199 // is added to close any menus, which should be run as test setup.
200 if (IsCompact()) {
201 [[EarlGrey selectElementWithMatcher:closeToolsMenuButton()]
202 performAction:grey_tap()];
203 }
204
205 // Close the opened tab.
206 base::scoped_nsobject<GenericChromeCommand> command(
207 [[GenericChromeCommand alloc] initWithTag:IDC_CLOSE_TAB]);
208 chrome_test_util::RunCommandWithActiveViewController(command);
209 }
210
211 // Tests that tapping a bookmark on the NTP navigates to the proper URL.
212 - (void)testTapBookmark {
213 const GURL bookmarkURL = web::test::HttpServer::MakeUrl(
214 "http://ios/testing/data/http_server_files/destination.html");
215 NSString* kBookmarkTitle = @"smokeTapBookmark";
216
217 // Load a bookmark into the bookmark model.
218 [[self class] addBookmark:bookmarkURL withTitle:kBookmarkTitle];
219
220 // Open the UI for Bookmarks.
221 [[self class] openMobileBookmarks];
222
223 // Wait for the bookmark to appear.
224 [[EarlGrey
225 selectElementWithMatcher:buttonWithAccessibilityLabel(kBookmarkTitle)]
226 assertWithMatcher:grey_sufficientlyVisible()
227 error:nil];
228
229 // Tap on the bookmark and verify the URL that appears in the omnibox.
230 [[EarlGrey
231 selectElementWithMatcher:buttonWithAccessibilityLabel(kBookmarkTitle)]
232 performAction:grey_tap()];
233 [[EarlGrey selectElementWithMatcher:chrome_test_util::omniboxText(
234 bookmarkURL.GetContent())]
235 assertWithMatcher:grey_notNil()];
236 }
237
238 // Test to set bookmarks in multiple tabs.
239 - (void)testBookmarkMultipleTabs {
240 const GURL firstURL = web::test::HttpServer::MakeUrl(
241 "http://ios/testing/data/http_server_files/pony.html");
242 const GURL secondURL = web::test::HttpServer::MakeUrl(
243 "http://ios/testing/data/http_server_files/destination.html");
244 [ChromeEarlGrey loadURL:firstURL];
245 chrome_test_util::OpenNewTab();
246 [ChromeEarlGrey loadURL:secondURL];
247
248 [[self class] bookmarkCurrentTabWithTitle:@"my bookmark"];
249 [[self class] assertBookmarksWithTitle:@"my bookmark" expectedCount:1];
250 }
251
252 // Try navigating to the bookmark screen, and selecting a bookmark.
253 - (void)testSelectBookmark {
254 [[self class] setupStandardBookmarks];
255 [[self class] openMobileBookmarks];
256
257 // Tap on one of the standard bookmark. Verify that it loads.
258 [[EarlGrey selectElementWithMatcher:grey_text(@"Second URL")]
259 performAction:grey_tap()];
260
261 // Wait for the page to load.
262 [ChromeEarlGrey waitForPageToFinishLoading];
263
264 // Check the URL is correct.
265 const GURL secondURL = web::test::HttpServer::MakeUrl(
266 "http://ios/testing/data/http_server_files/destination.html");
267 [[EarlGrey selectElementWithMatcher:chrome_test_util::omnibox()]
268 assertWithMatcher:chrome_test_util::omniboxText(secondURL.GetContent())];
269 }
270
271 // Try deleting a bookmark, then undoing that delete.
272 - (void)testUndoDeleteBookmark {
273 [[self class] setupStandardBookmarks];
274 [[self class] openMobileBookmarks];
275
276 // Load the menu for a bookmark.
277 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Second URL Info")]
278 performAction:grey_tap()];
279
280 // Delete it.
281 [[EarlGrey selectElementWithMatcher:actionSheet(ActionDelete)]
282 performAction:grey_tap()];
283
284 // Wait until it's gone.
285 [[self class] waitForDeletionOfBookmarkWithTitle:@"Second URL"];
286
287 // Press undo
288 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Undo")]
289 performAction:grey_tap()];
290
291 // Verify it's back.
292 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Second URL")]
293 assertWithMatcher:grey_notNil()];
294 }
295
296 // Try deleting a bookmark from the edit screen, then undoing that delete.
297 - (void)testUndoDeleteBookmarkFromEditScreen {
298 [[self class] setupStandardBookmarks];
299 [[self class] openMobileBookmarks];
300
301 // Load the menu for a bookmark.
302 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Second URL Info")]
303 performAction:grey_tap()];
304
305 // Tap the edit action.
306 [[EarlGrey selectElementWithMatcher:actionSheet(ActionEdit)]
307 performAction:grey_tap()];
308
309 // Delete it.
310 [[EarlGrey selectElementWithMatcher:actionSheet(ActionDelete)]
311 performAction:grey_tap()];
312
313 // Wait until it's gone.
314 ConditionBlock condition = ^{
315 NSError* error = nil;
316 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Second URL")]
317 assertWithMatcher:grey_notVisible()
318 error:&error];
319 return error == nil;
320 };
321 GREYAssert(testing::WaitUntilConditionOrTimeout(10, condition),
322 @"Waiting for bookmark to go away");
323
324 // Press undo
325 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Undo")]
326 performAction:grey_tap()];
327
328 // Verify it's back.
329 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Second URL")]
330 assertWithMatcher:grey_notNil()];
331 }
332
333 // Try moving bookmarks, then undoing that move.
334 - (void)testUndoMoveBookmark {
335 [[self class] setupStandardBookmarks];
336 [[self class] openMobileBookmarks];
337
338 // Verify that folder 2 only has 1 child.
339 [[self class] assertChildCount:1 ofFolderWithName:@"Folder 2"];
340
341 // Load the menu for a bookmark.
342 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Second URL Info")]
343 performAction:grey_tap()];
344
345 // Select a first bookmark.
346 [[EarlGrey selectElementWithMatcher:actionSheet(ActionSelect)]
347 performAction:grey_tap()];
348
349 // Select a second bookmark.
350 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL")]
351 performAction:grey_tap()];
352
353 // Choose the move action.
354 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Move")]
355 performAction:grey_tap()];
356
357 // Pick the destination.
358 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder 2")]
359 performAction:grey_tap()];
360
361 // Wait for undo to show up (there is a 300ms delay for the user to see the
362 // change).
363 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Undo")]
364 assertWithMatcher:grey_sufficientlyVisible()];
365
366 // Verify that folder 2 has 3 children now, and that they are no longer
367 // visible.
368 [[self class] assertChildCount:3 ofFolderWithName:@"Folder 2"];
369 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Second URL")]
370 assertWithMatcher:grey_notVisible()];
371
372 // Press undo.
373 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Undo")]
374 performAction:grey_tap()];
375
376 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
377
378 // Verify it's back.
379 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Second URL")]
380 assertWithMatcher:grey_notNil()];
381
382 // Verify that folder 2 is back to one child.
383 [[self class] assertChildCount:1 ofFolderWithName:@"Folder 2"];
384 }
385
386 - (void)testLabelUpdatedUponMove {
387 [[self class] setupStandardBookmarks];
388 [[self class] openMobileBookmarks];
389
390 // Load the menu for a bookmark.
391 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL Info")]
392 performAction:grey_tap()];
393
394 // Tap on the Edit action.
395 [[EarlGrey selectElementWithMatcher:actionSheet(ActionEdit)]
396 performAction:grey_tap()];
397
398 // Tap the Folder button.
399 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Change Folder")]
400 performAction:grey_tap()];
401
402 // Create a new folder with default name.
403 [[self class] addFolderWithName:nil];
404
405 // Verify that the editor is present.
406 [[EarlGrey
407 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
408 assertWithMatcher:grey_notNil()];
409
410 // Check the new folder label.
411 [[EarlGrey
412 selectElementWithMatcher:grey_allOf(
413 grey_accessibilityID(@"Change Folder"),
414 grey_accessibilityLabel(@"New Folder"), nil)]
415 assertWithMatcher:grey_notNil()];
416 }
417
418 // Test the creation of a bookmark and new folder.
419 - (void)testAddBookmarkInNewFolder {
420 const GURL bookmarkedURL = web::test::HttpServer::MakeUrl(
421 "http://ios/testing/data/http_server_files/pony.html");
422 std::string expectedURLContent = bookmarkedURL.GetContent();
423
424 [ChromeEarlGrey loadURL:bookmarkedURL];
425 [[EarlGrey selectElementWithMatcher:chrome_test_util::omniboxText(
426 expectedURLContent)]
427 assertWithMatcher:grey_notNil()];
428
429 [[self class] starCurrentTab];
430
431 // Verify the snackbar title.
432 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Bookmarked")]
433 assertWithMatcher:grey_notNil()];
434
435 // Tap on the snackbar.
436 NSString* snackbarLabel =
437 l10n_util::GetNSString(IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON);
438 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
439 performAction:grey_tap()];
440
441 // Verify that the newly-created bookmark is in the BookmarkModel.
442 [[self class]
443 assertBookmarksWithTitle:base::SysUTF8ToNSString(expectedURLContent)
444 expectedCount:1];
445
446 // Verify that the editor is present.
447 [[EarlGrey
448 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
449 assertWithMatcher:grey_notNil()];
450
451 [[self class] assertFolderName:@"Mobile Bookmarks"];
452
453 // Tap the Folder button.
454 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Change Folder")]
455 performAction:grey_tap()];
456
457 // Create a new folder with default name.
458 [[self class] addFolderWithName:nil];
459
460 // Verify that the editor is present.
461 [[EarlGrey
462 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
463 assertWithMatcher:grey_notNil()];
464
465 [[self class] assertFolderExists:@"New Folder"];
466 }
467
468 // Tests that changing a folder's title in edit mode works as expected.
469 - (void)testChangeFolderTitle {
470 NSString* existingFolderTitle = @"Folder 1";
471 NSString* newFolderTitle = @"New Folder Title";
472
473 [[self class] setupStandardBookmarks];
474 [[self class] openMobileBookmarks];
475 [[self class] openEditBookmarkFolderWithFolderTitle:existingFolderTitle];
476 [[self class] renameBookmarkFolderWithFolderTitle:newFolderTitle];
477 [[self class] closeEditBookmarkFolder];
478
479 if (IsCompact()) {
480 // Exit from bookmarks modal. IPad shows bookmarks in tab.
481 [[EarlGrey selectElementWithMatcher:bookmarksDoneButton()]
482 performAction:grey_tap()];
483 }
484
485 // Verify that the change has been made.
486 [[self class] openMobileBookmarks];
487 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(existingFolderTitle)]
488 assertWithMatcher:grey_nil()];
489 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(newFolderTitle)]
490 assertWithMatcher:grey_notNil()];
491 }
492
493 // Tests that the default folder bookmarks are saved in is updated to the last
494 // used folder.
495 - (void)testStickyDefaultFolder {
496 [[self class] setupStandardBookmarks];
497 [[self class] openMobileBookmarks];
498
499 // Tap on the top-right button.
500 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL Info")]
501 performAction:grey_tap()];
502
503 // Tap the edit action.
504 [[EarlGrey selectElementWithMatcher:actionSheet(ActionEdit)]
505 performAction:grey_tap()];
506
507 // Tap the Folder button.
508 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Change Folder")]
509 performAction:grey_tap()];
510
511 // Create a new folder.
512 [[self class] addFolderWithName:@"Sticky Folder"];
513
514 // Verify that the editor is present.
515 [[EarlGrey
516 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
517 assertWithMatcher:grey_sufficientlyVisible()];
518
519 // Tap the Done button.
520 [[EarlGrey selectElementWithMatcher:bookmarksDoneButton()]
521 performAction:grey_tap()];
522 [[EarlGrey
523 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
524 assertWithMatcher:grey_notVisible()];
525
526 if (IsCompact()) {
527 // Dismiss the bookmarks screen.
528 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Exit")]
529 performAction:grey_tap()];
530 }
531
532 // Second, bookmark a page.
533
534 // Verify that the bookmark that is going to be added is not in the
535 // BookmarkModel.
536 const GURL bookmarkedURL = web::test::HttpServer::MakeUrl(
537 "http://ios/testing/data/http_server_files/fullscreen.html");
538 NSString* const bookmarkedURLString =
539 base::SysUTF8ToNSString(bookmarkedURL.spec());
540 [[self class] assertBookmarksWithTitle:bookmarkedURLString expectedCount:0];
541 // Open the page.
542 std::string expectedURLContent = bookmarkedURL.GetContent();
543 [ChromeEarlGrey loadURL:bookmarkedURL];
544 [[EarlGrey selectElementWithMatcher:chrome_test_util::omniboxText(
545 expectedURLContent)]
546 assertWithMatcher:grey_notNil()];
547
548 // Verify that the folder has only one element.
549 [[self class] assertChildCount:1 ofFolderWithName:@"Sticky Folder"];
550
551 // Bookmark the page.
552 [[self class] starCurrentTab];
553
554 // Verify the snackbar title.
555 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
556 @"Bookmarked to Sticky Folder")]
557 assertWithMatcher:grey_sufficientlyVisible()];
558
559 // Verify that the newly-created bookmark is in the BookmarkModel.
560 [[self class] assertBookmarksWithTitle:bookmarkedURLString expectedCount:1];
561
562 // Verify that the folder has now two elements.
563 [[self class] assertChildCount:2 ofFolderWithName:@"Sticky Folder"];
564 }
565
566 // Tests that changes to the parent folder from the Single Bookmark Controller
567 // are saved to the bookmark only when saving the results.
568 - (void)testMoveDoesSaveOnSave {
569 [[self class] setupStandardBookmarks];
570 [[self class] openTopLevelBookmarksFolder];
571
572 // Tap on the top-right button.
573 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL Info")]
574 performAction:grey_tap()];
575
576 // Tap the edit action.
577 [[EarlGrey selectElementWithMatcher:actionSheet(ActionEdit)]
578 performAction:grey_tap()];
579
580 // Tap the Folder button.
581 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Change Folder")]
582 performAction:grey_tap()];
583
584 // Create a new folder.
585 [[self class] addFolderWithName:nil];
586
587 // Verify that the editor is present.
588 [[EarlGrey
589 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
590 assertWithMatcher:grey_sufficientlyVisible()];
591
592 // Check that the new folder doesn't contain the bookmark.
593 [[self class] assertChildCount:0 ofFolderWithName:@"New Folder"];
594
595 // Tap the Done button.
596 [[EarlGrey selectElementWithMatcher:bookmarksDoneButton()]
597 performAction:grey_tap()];
598 [[EarlGrey
599 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
600 assertWithMatcher:grey_notVisible()];
601
602 // Check that the new folder contains the bookmark.
603 [[self class] assertChildCount:1 ofFolderWithName:@"New Folder"];
604
605 // Dismiss the bookmarks screen.
606 if (IsCompact()) {
607 // Dismiss the bookmarks screen.
608 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Exit")]
609 performAction:grey_tap()];
610 }
611
612 // Check that the new folder still contains the bookmark.
613 [[self class] assertChildCount:1 ofFolderWithName:@"New Folder"];
614 }
615
616 // Test thats editing a single bookmark correctly persists data.
617 - (void)testSingleBookmarkEdit {
618 [[self class] setupStandardBookmarks];
619 [[self class] openTopLevelBookmarksFolder];
620
621 // Load the menu for a bookmark.
622 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL Info")]
623 performAction:grey_tap()];
624
625 // Tap the edit action.
626 [[EarlGrey selectElementWithMatcher:actionSheet(ActionEdit)]
627 performAction:grey_tap()];
628
629 // Replace the title field with new text.
630 // TODO(crbug.com/644730): Use grey_replaceText instead of
631 // grey_clearText/grey_typeText when EarlGrey's issue is fixed:
632 // https://github.com/google/EarlGrey/issues/253
633 [[EarlGrey
634 selectElementWithMatcher:grey_accessibilityID(@"Title Field_textField")]
635 performAction:grey_clearText()];
636 [[EarlGrey
637 selectElementWithMatcher:grey_accessibilityID(@"Title Field_textField")]
638 performAction:grey_typeText(@"n5")];
639
640 // Replace the url field with new text.
641 // TODO(crbug.com/644730): Use grey_replaceText instead of
642 // grey_clearText/grey_typeText when EarlGrey's issue is fixed:
643 // https://github.com/google/EarlGrey/issues/253
644 [[EarlGrey
645 selectElementWithMatcher:grey_accessibilityID(@"URL Field_textField")]
646 performAction:grey_clearText()];
647 [[EarlGrey
648 selectElementWithMatcher:grey_accessibilityID(@"URL Field_textField")]
649 performAction:grey_typeText(@"www.a.fr")];
650
651 // Dismiss editor.
652 [[EarlGrey selectElementWithMatcher:bookmarksDoneButton()]
653 performAction:grey_tap()];
654 [[EarlGrey
655 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
656 assertWithMatcher:grey_notVisible()];
657
658 // Verify that the bookmark was updated.
659 [[EarlGrey selectElementWithMatcher:buttonWithAccessibilityLabel(@"n5")]
660 assertWithMatcher:grey_sufficientlyVisible()];
661 [[self class] assertExistenceOfBookmarkWithURL:@"http://www.a.fr" name:@"n5"];
662 }
663
664 // Tests that cancelling editing a single bookmark correctly doesn't persist
665 // data.
666 - (void)testSingleBookmarkCancelEdit {
667 [[self class] setupStandardBookmarks];
668 [[self class] openTopLevelBookmarksFolder];
669
670 // Load the menu for a bookmark.
671 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL Info")]
672 performAction:grey_tap()];
673
674 // Tap the edit action.
675 [[EarlGrey selectElementWithMatcher:actionSheet(ActionEdit)]
676 performAction:grey_tap()];
677
678 // Replace the title field with new text.
679 // TODO(crbug.com/644730): Use grey_replaceText instead of
680 // grey_clearText/grey_typeText when EarlGrey's issue is fixed:
681 // https://github.com/google/EarlGrey/issues/253
682 [[EarlGrey
683 selectElementWithMatcher:grey_accessibilityID(@"Title Field_textField")]
684 performAction:grey_clearText()];
685 [[EarlGrey
686 selectElementWithMatcher:grey_accessibilityID(@"Title Field_textField")]
687 performAction:grey_typeText(@"n5")];
688
689 // Replace the url field with new text.
690 // TODO(crbug.com/644730): Use grey_replaceText instead of
691 // grey_clearText/grey_typeText when EarlGrey's issue is fixed:
692 // https://github.com/google/EarlGrey/issues/253
693 [[EarlGrey
694 selectElementWithMatcher:grey_accessibilityID(@"URL Field_textField")]
695 performAction:grey_clearText()];
696 [[EarlGrey
697 selectElementWithMatcher:grey_accessibilityID(@"URL Field_textField")]
698 performAction:grey_typeText(@"www.a.fr")];
699
700 // Dismiss editor with Cancel button.
701 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Cancel")]
702 performAction:grey_tap()];
703 [[EarlGrey
704 selectElementWithMatcher:grey_accessibilityID(@"Single Bookmark Editor")]
705 assertWithMatcher:grey_notVisible()];
706
707 // Verify that the bookmark was not updated.
708 [[EarlGrey selectElementWithMatcher:buttonWithAccessibilityLabel(@"n5")]
709 assertWithMatcher:grey_notVisible()];
710 [[self class] assertAbsenceOfBookmarkWithURL:@"http://www.a.fr"];
711 }
712
713 // Tests that long pressing a bookmark selects it and gives access to editing,
714 // as does the Info menu.
715 - (void)testLongPressBookmark {
716 [[self class] setupStandardBookmarks];
717 [[self class] openTopLevelBookmarksFolder];
718
719 // Long press the top-right button.
720 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL Info")]
721 performAction:grey_longPress()];
722
723 // Tap the edit button.
724 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Edit_editing_bar")]
725 performAction:grey_tap()];
726
727 // Dismiss the editor screen.
728 [[EarlGrey selectElementWithMatcher:bookmarksDoneButton()]
729 performAction:grey_tap()];
730
731 // Tap on the top-right button.
732 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL Info")]
733 performAction:grey_tap()];
734
735 // Tap the edit action.
736 [[EarlGrey selectElementWithMatcher:actionSheet(ActionEdit)]
737 performAction:grey_tap()];
738
739 // Dismiss the editor screen.
740 [[EarlGrey selectElementWithMatcher:bookmarksDoneButton()]
741 performAction:grey_tap()];
742 }
743
744 // Tests the editing of a folder.
745 - (void)testEditFolder {
746 [[self class] setupStandardBookmarks];
747 [[self class] openBookmarkFolder:@"Folder 1"];
748
749 // Tap the Edit button in the navigation bar.
750 [[EarlGrey
751 selectElementWithMatcher:grey_accessibilityID(@"Edit_navigation_bar")]
752 performAction:grey_tap()];
753
754 // Change the title.
755 // TODO(crbug.com/644730): Use grey_replaceText instead of
756 // grey_clearText/grey_typeText when EarlGrey's issue is fixed:
757 // https://github.com/google/EarlGrey/issues/253
758 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Title_textField")]
759 performAction:grey_clearText()];
760 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Title_textField")]
761 performAction:grey_typeText(@"Renamed Folder")];
762
763 // Cancel without saving.
764 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Cancel")]
765 performAction:grey_tap()];
766
767 // Check that Folder 1 still exists at this name, and Renamed Folder doesn't.
768 [[self class] assertFolderExistsWithTitle:@"Folder 1"];
769 [[self class] assertFolderDoesntExistWithTitle:@"Renamed Folder"];
770
771 // Tap the Edit button in the navigation bar.
772 [[EarlGrey
773 selectElementWithMatcher:grey_accessibilityID(@"Edit_navigation_bar")]
774 performAction:grey_tap()];
775
776 // Change the title.
777 // TODO(crbug.com/644730): Use grey_replaceText instead of
778 // grey_clearText/grey_typeText when EarlGrey's issue is fixed:
779 // https://github.com/google/EarlGrey/issues/253
780 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Title_textField")]
781 performAction:grey_clearText()];
782 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Title_textField")]
783 performAction:grey_typeText(@"Renamed Folder")];
784
785 // Save.
786 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Save")]
787 performAction:grey_tap()];
788
789 // Check that Folder 1 doesn't exist and Renamed Folder does.
790 [[self class] assertFolderDoesntExistWithTitle:@"Folder 1"];
791 [[self class] assertFolderExistsWithTitle:@"Renamed Folder"];
792 }
793
794 // Tests the deletion of a folder.
795 - (void)testDeleteFolder {
796 [[self class] setupStandardBookmarks];
797 [[self class] openBookmarkFolder:@"Folder 1"];
798
799 // Delete the folder.
800 [[self class] deleteSelectedFolder];
801
802 // Check that the folder doesn't exist anymore.
803 [[self class] assertFolderDoesntExistWithTitle:@"Folder 1"];
804 }
805
806 // Navigates to a deeply nested folder, deletes it and makes sure the UI is
807 // consistent.
808 - (void)testDeleteCurrentSubfolder {
809 [[self class] setupStandardBookmarks];
810 [[self class] openBookmarkFolder:@"Folder 1"];
811 [[EarlGrey selectElementWithMatcher:buttonWithAccessibilityLabel(@"Folder 2")]
812 performAction:grey_tap()];
813 [[EarlGrey selectElementWithMatcher:buttonWithAccessibilityLabel(@"Folder 3")]
814 performAction:grey_tap()];
815
816 // Delete the folder.
817 [[self class] deleteSelectedFolder];
818
819 // Folder 3 is now deleted, UI should have moved to Folder 2, and Folder 2
820 // should be empty.
821 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Folder 2")]
822 assertWithMatcher:grey_sufficientlyVisible()];
823 [[self class] assertChildCount:0 ofFolderWithName:@"Folder 2"];
824 [[self class] assertFolderDoesntExistWithTitle:@"Folder 3"];
825 [[self class] waitForDeletionOfBookmarkWithTitle:@"Folder 3"];
826 }
827
828 // Navigates to a deeply nested folder, delete its parent programatically.
829 // Verifies that the UI is as expected.
830 - (void)testDeleteParentFolder {
831 [[self class] setupStandardBookmarks];
832 [[self class] openBookmarkFolder:@"Folder 1"];
833 [[EarlGrey selectElementWithMatcher:buttonWithAccessibilityLabel(@"Folder 2")]
834 performAction:grey_tap()];
835 [[EarlGrey selectElementWithMatcher:buttonWithAccessibilityLabel(@"Folder 3")]
836 performAction:grey_tap()];
837
838 // Remove the parent programmatically.
839 [[self class] removeBookmarkWithTitle:@"Folder 2"];
840
841 // Folder 2 and 3 are now deleted, UI should have moved to Folder1, and
842 // Folder 1 should be empty.
843 [[EarlGrey
844 selectElementWithMatcher:grey_allOf(
845 grey_kindOfClass(NSClassFromString(
846 @"BookmarkNavigationBar")),
847 grey_descendant(grey_text(@"Folder 1")),
848 nil)]
849 assertWithMatcher:grey_sufficientlyVisible()];
850 [[self class] assertChildCount:0 ofFolderWithName:@"Folder 1"];
851 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Folder 2")]
852 assertWithMatcher:grey_notVisible()];
853 [[self class] assertFolderDoesntExistWithTitle:@"Folder 2"];
854 [[self class] assertFolderDoesntExistWithTitle:@"Folder 3"];
855
856 // Check that the selected folder in the menu is Folder 1.
857 if (IsCompact()) {
858 // Opens the bookmark manager sidebar on handsets.
859 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Menu")]
860 performAction:grey_tap()];
861 }
862 [[EarlGrey
863 selectElementWithMatcher:grey_allOf(
864 grey_kindOfClass(
865 NSClassFromString(@"BookmarkMenuCell")),
866 grey_descendant(grey_text(@"Folder 1")),
867 nil)]
868 assertWithMatcher:grey_sufficientlyVisible()];
869 }
870
871 // Tests that the menu button changes to a back button as expected when browsing
872 // nested folders.
873 - (void)testBrowseNestedFolders {
874 [[self class] setupStandardBookmarks];
875 [[self class] openMobileBookmarks];
876
877 // Navigate down the nested folders.
878 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder 1")]
879 performAction:grey_tap()];
880 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder 2")]
881 performAction:grey_tap()];
882 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder 3")]
883 performAction:grey_tap()];
884
885 // Verify the back button is visible to be able to go back to parent.
886 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Parent")]
887 assertWithMatcher:grey_sufficientlyVisible()];
888
889 if (IsCompact()) {
890 // Verify menu button becomes back button in phone only.
891 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Menu")]
892 assertWithMatcher:grey_notVisible()];
893 }
894
895 // Go back two levels to Folder 1.
896 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Parent")]
897 performAction:grey_tap()];
898 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Parent")]
899 performAction:grey_tap()];
900
901 // Verify back button is hidden again.
902 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Parent")]
903 assertWithMatcher:grey_notVisible()];
904
905 if (IsCompact()) {
906 // Verify menu button reappears.
907 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Menu")]
908 assertWithMatcher:grey_sufficientlyVisible()];
909 }
910 }
911
912 // Tests moving a bookmark into a new folder created in the moving process.
913 - (void)testCreateNewFolderWhileMovingBookmark {
914 [[self class] setupStandardBookmarks];
915 [[self class] openMobileBookmarks];
916
917 // Tap the info disclosure indicator for the bookmark we want to move.
918 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL Info")]
919 performAction:grey_tap()];
920
921 // Choose to move the bookmark in the context menu.
922 [[EarlGrey selectElementWithMatcher:actionSheet(ActionMove)]
923 performAction:grey_tap()];
924
925 // Choose to move the bookmark into a new folder.
926 [[EarlGrey
927 selectElementWithMatcher:grey_accessibilityID(@"Create New Folder")]
928 performAction:grey_tap()];
929
930 // Enter custom new folder name.
931 [[self class] renameBookmarkFolderWithFolderTitle:@"Title For New Folder"];
932
933 // Verify current parent folder (Change Folder) is Bookmarks folder.
934 [[EarlGrey
935 selectElementWithMatcher:grey_allOf(
936 grey_accessibilityID(@"Change Folder"),
937 grey_accessibilityLabel(@"Mobile Bookmarks"),
938 nil)]
939 assertWithMatcher:grey_sufficientlyVisible()];
940
941 // Choose new parent folder (Change Folder).
942 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Change Folder")]
943 performAction:grey_tap()];
944
945 // Verify folder picker UI is displayed.
946 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Picker")]
947 assertWithMatcher:grey_sufficientlyVisible()];
948
949 // Verify Folder 2 only has one item.
950 [[self class] assertChildCount:1 ofFolderWithName:@"Folder 2"];
951
952 // Select Folder 2 as new Change Folder.
953 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder 2")]
954 performAction:grey_tap()];
955
956 // Verify folder picker is dismissed and folder creator is now visible.
957 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Creator")]
958 assertWithMatcher:grey_sufficientlyVisible()];
959 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Picker")]
960 assertWithMatcher:grey_notVisible()];
961
962 // Verify picked parent folder (Change Folder) is Folder 2.
963 [[EarlGrey
964 selectElementWithMatcher:grey_allOf(
965 grey_accessibilityID(@"Change Folder"),
966 grey_accessibilityLabel(@"Folder 2"), nil)]
967 assertWithMatcher:grey_sufficientlyVisible()];
968
969 // Tap Done (accessibilityID is 'Save') to close bookmark move flow.
970 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Save")]
971 performAction:grey_tap()];
972
973 // Verify all folder flow UI is now closed.
974 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Creator")]
975 assertWithMatcher:grey_notVisible()];
976 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Picker")]
977 assertWithMatcher:grey_notVisible()];
978 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Editor")]
979 assertWithMatcher:grey_notVisible()];
980
981 // Verify new folder has been created under Folder 2.
982 [[self class] assertChildCount:2 ofFolderWithName:@"Folder 2"];
983
984 // Verify new folder has one bookmark.
985 [[self class] assertChildCount:1 ofFolderWithName:@"Title For New Folder"];
986 }
987
988 // Navigates to a deeply nested folder, deletes its root ancestor and checks
989 // that the UI is on the top level folder.
990 - (void)testDeleteRootFolder {
991 [[self class] setupStandardBookmarks];
992 [[self class] openBookmarkFolder:@"Folder 1"];
993 [[EarlGrey selectElementWithMatcher:grey_text(@"Folder 2")]
994 performAction:grey_tap()];
995 [[EarlGrey selectElementWithMatcher:grey_text(@"Folder 3")]
996 performAction:grey_tap()];
997
998 [[self class] removeBookmarkWithTitle:@"Folder 1"];
999
1000 NSString* rootFolderTitle = nil;
1001 if (experimental_flags::IsAllBookmarksEnabled()) {
1002 rootFolderTitle = @"Bookmarks";
1003 } else {
1004 rootFolderTitle = @"Mobile Bookmarks";
1005 }
1006
1007 // Folder 2 and 3 are now deleted, UI should have moved to top level folder.
1008 [[EarlGrey
1009 selectElementWithMatcher:grey_allOf(
1010 grey_kindOfClass(NSClassFromString(
1011 @"BookmarkNavigationBar")),
1012 grey_descendant(grey_text(rootFolderTitle)),
1013 nil)] assertWithMatcher:grey_notNil()];
1014 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Folder 1")]
1015 assertWithMatcher:grey_notVisible()];
1016
1017 if (IsCompact()) {
1018 // Opens the bookmark manager sidebar on handsets.
1019 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Menu")]
1020 performAction:grey_tap()];
1021
1022 // Test that the root folder is selected in the menu. This is only the case
1023 // on iPhone.
1024 if (experimental_flags::IsAllBookmarksEnabled()) {
1025 rootFolderTitle = @"All Bookmarks";
1026 }
1027
1028 GREYElementMatcherBlock* selectedMatcher =
1029 [GREYElementMatcherBlock matcherWithMatchesBlock:^BOOL(id element) {
1030 UITableViewCell* cell = (UITableViewCell*)element;
1031 return [cell isSelected];
1032 }
1033 descriptionBlock:^void(id<GREYDescription> description) {
1034 [description appendText:@"Selected UI element."];
1035 }];
1036 [[EarlGrey
1037 selectElementWithMatcher:grey_allOf(grey_kindOfClass(NSClassFromString(
1038 @"BookmarkMenuCell")),
1039 grey_descendant(
1040 grey_text(rootFolderTitle)),
1041 nil)]
1042 assertWithMatcher:selectedMatcher];
1043 }
1044
1045 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Folder 1")]
1046 assertWithMatcher:grey_notVisible()];
1047 }
1048
1049 // Tests that keyboard commands are registered when a bookmark is added with the
1050 // new bookmark UI as it shows only a snackbar.
1051 - (void)testKeyboardCommandsRegistered_AddBookmark {
1052 // Add the bookmark.
1053 [[self class] starCurrentTab];
1054 GREYAssertTrue(chrome_test_util::GetRegisteredKeyCommandsCount() > 0,
1055 @"Some keyboard commands are registered.");
1056 }
1057
1058 // Tests that keyboard commands are not registered when a bookmark is edited, as
1059 // the edit screen is presented modally.
1060 - (void)testKeyboardCommandsNotRegistered_EditBookmark {
1061 [[self class] setupStandardBookmarks];
1062 [[self class] openMobileBookmarks];
1063
1064 // Go to a bookmarked page. Tap on one of the standard bookmark.
1065 [[EarlGrey selectElementWithMatcher:grey_text(@"Second URL")]
1066 performAction:grey_tap()];
1067
1068 // Edit the bookmark.
1069 if (!IsCompact()) {
1070 [[EarlGrey selectElementWithMatcher:starButton()] performAction:grey_tap()];
1071 } else {
1072 [ChromeEarlGreyUI openToolsMenu];
1073 [[EarlGrey selectElementWithMatcher:litStarButtoniPhone()]
1074 performAction:grey_tap()];
1075 }
1076 GREYAssertTrue(chrome_test_util::GetRegisteredKeyCommandsCount() == 0,
1077 @"No keyboard commands are registered.");
1078 }
1079
1080 // Tests that tapping No thanks on the promo make it disappear.
1081 - (void)testPromoNoThanksMakeItDisappear {
1082 [[self class] setupStandardBookmarks];
1083 [[self class] openTopLevelBookmarksFolder];
1084
1085 // We are going to set the PromoAlreadySeen preference. Set a teardown handler
1086 // to reset it.
1087 [self setTearDownHandler:^{
1088 [[self class] setPromoAlreadySeen:NO];
1089 }];
1090 // Check that promo is visible.
1091 [[self class] verifyPromoAlreadySeen:NO];
1092 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")]
1093 assertWithMatcher:grey_notNil()];
1094
1095 // Tap the dismiss button.
1096 [[EarlGrey
1097 selectElementWithMatcher:grey_accessibilityID(@"promo_no_thanks_button")]
1098 performAction:grey_tap()];
1099
1100 // Wait until promo is gone.
1101 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")]
1102 assertWithMatcher:grey_notVisible()];
1103
1104 // Check that the promo already seen state is updated.
1105 [[self class] verifyPromoAlreadySeen:YES];
1106 }
1107
1108 // Tests that tapping Sign in on the promo make the Sign in sheet appear and
1109 // the promo still appears after dismissing the Sign in sheet.
1110 - (void)testUIPromoSignIn {
1111 [[self class] setupStandardBookmarks];
1112 [[self class] openTopLevelBookmarksFolder];
1113 // Set up a fake identity.
1114 ChromeIdentity* identity =
1115 [FakeChromeIdentity identityWithEmail:@"fakefoo@egmail.com"
1116 gaiaID:@"fakefoopassword"
1117 name:@"Fake Foo"];
1118 ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity(
1119 identity);
1120
1121 // Check that promo is visible.
1122 [[self class] verifyPromoAlreadySeen:NO];
1123 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")]
1124 assertWithMatcher:grey_notNil()];
1125
1126 // Tap the Sign in button.
1127 [[EarlGrey
1128 selectElementWithMatcher:grey_accessibilityID(@"promo_sign_in_button")]
1129 performAction:grey_tap()];
1130
1131 // Tap the CANCEL button.
1132 [[EarlGrey selectElementWithMatcher:
1133 grey_buttonTitle([l10n_util::GetNSString(
1134 IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SKIP_BUTTON)
1135 uppercaseString])] performAction:grey_tap()];
1136
1137 // Check that the bookmarks UI reappeared and the cell is still here.
1138 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")]
1139 assertWithMatcher:grey_notNil()];
1140
1141 [[self class] verifyPromoAlreadySeen:NO];
1142 }
1143
1144 #pragma mark Helper Methods
1145
1146 // Navigates to the bookmark manager UI.
1147 + (void)openBookmarks {
1148 [ChromeEarlGreyUI openToolsMenu];
1149
1150 // Opens the bookmark manager.
1151 [[EarlGrey
1152 selectElementWithMatcher:grey_accessibilityID(kToolsMenuBookmarksId)]
1153 performAction:grey_tap()];
1154
1155 // Wait for it to load, and the menu to go away.
1156 [[EarlGrey
1157 selectElementWithMatcher:grey_accessibilityID(kToolsMenuBookmarksId)]
1158 assertWithMatcher:grey_nil()];
1159 }
1160
1161 // Navigates to the bookmark manager UI, and selects |bookmarkFolder|.
1162 + (void)openBookmarkFolder:(NSString*)bookmarkFolder {
1163 [BookmarksTestCase openBookmarks];
1164 if (IsCompact()) {
1165 // Opens the bookmark manager sidebar on handsets.
1166 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Menu")]
1167 performAction:grey_tap()];
1168 }
1169
1170 // Selects the folder with label |bookmarkFolder|.
1171 [[EarlGrey
1172 selectElementWithMatcher:grey_allOf(
1173 grey_kindOfClass(
1174 NSClassFromString(@"BookmarkMenuCell")),
1175 grey_descendant(grey_text(bookmarkFolder)),
1176 nil)] performAction:grey_tap()];
1177 }
1178
1179 // Navigates to the bookmark manager UI, and selects the top level folder.
1180 + (void)openTopLevelBookmarksFolder {
1181 if (experimental_flags::IsAllBookmarksEnabled()) {
1182 [BookmarksTestCase openBookmarkFolder:@"All Bookmarks"];
1183 } else {
1184 [BookmarksTestCase openMobileBookmarks];
1185 }
1186 }
1187
1188 // Navigates to the bookmark manager UI, and selects MobileBookmarks.
1189 + (void)openMobileBookmarks {
1190 [BookmarksTestCase openBookmarkFolder:@"Mobile Bookmarks"];
1191 }
1192
1193 // Navigates to the edit folder UI for |folderTitle|.
1194 + (void)openEditBookmarkFolderWithFolderTitle:(NSString*)folderTitle {
1195 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(folderTitle)]
1196 performAction:grey_tap()];
1197 [[EarlGrey selectElementWithMatcher:editBookmarkButton()]
1198 performAction:grey_tap()];
1199 }
1200
1201 // Dismisses the edit folder UI.
1202 + (void)closeEditBookmarkFolder {
1203 [[EarlGrey selectElementWithMatcher:bookmarksDoneButton()]
1204 performAction:grey_tap()];
1205 }
1206
1207 // Rename folder title to |folderTitle|. Must be in edit folder UI.
1208 + (void)renameBookmarkFolderWithFolderTitle:(NSString*)folderTitle {
1209 NSString* titleIdentifier = @"Title_textField";
1210 NSString* clearTextFieldIdentifier = @"Clear text";
1211
1212 // Edit the title field.
1213 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(titleIdentifier)]
1214 performAction:grey_tap()];
1215 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
1216 clearTextFieldIdentifier)]
1217 performAction:grey_tap()];
1218
1219 // Type in the new title and use '\n' to dismiss the keyboard.
1220 NSString* folderTitleWithNewLine =
1221 [NSString stringWithFormat:@"%@\n", folderTitle];
1222 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(titleIdentifier)]
1223 performAction:grey_typeText(folderTitleWithNewLine)];
1224 }
1225
1226 // Tap on the star to bookmark a page, then edit the bookmark to change the
1227 // title to |title|.
1228 + (void)bookmarkCurrentTabWithTitle:(NSString*)title {
1229 [[self class] waitForBookmarkModelLoaded:YES];
1230 // Add the bookmark from the UI.
1231 [[self class] starCurrentTab];
1232
1233 // Set the bookmark name.
1234 [[EarlGrey selectElementWithMatcher:editBookmarkButton()]
1235 performAction:grey_tap()];
1236 NSString* titleIdentifier = @"Title Field_textField";
1237 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(titleIdentifier)]
1238 performAction:grey_tap()];
1239 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Clear text")]
1240 performAction:grey_tap()];
1241
1242 // Use '\n' to tap Done and dismiss the keyboard.
1243 NSString* bookmarkTitle = [NSString stringWithFormat:@"%@\n", title];
1244 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(titleIdentifier)]
1245 performAction:grey_typeText(bookmarkTitle)];
1246
1247 // Dismiss the window.
1248 [[EarlGrey selectElementWithMatcher:bookmarksDoneButton()]
1249 performAction:grey_tap()];
1250 }
1251
1252 // Waits for the bookmark model to be loaded in memory.
1253 + (void)waitForBookmarkModelLoaded:(BOOL)loaded {
1254 bookmarks::BookmarkModel* bookmarkModel =
1255 ios::BookmarkModelFactory::GetForBrowserState(
1256 chrome_test_util::GetOriginalBrowserState());
1257 GREYAssert(testing::WaitUntilConditionOrTimeout(
1258 testing::kWaitForUIElementTimeout,
1259 ^{
1260 return bookmarkModel->loaded() == loaded;
1261 }),
1262 @"Bookmark model was not loaded");
1263 }
1264
1265 // Asserts that a folder called |title| exists.
1266 + (void)assertFolderExists:(NSString*)title {
1267 base::string16 folderTitle16(base::SysNSStringToUTF16(title));
1268 bookmarks::BookmarkModel* bookmark_model =
1269 ios::BookmarkModelFactory::GetForBrowserState(
1270 chrome_test_util::GetOriginalBrowserState());
1271
1272 ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator(
1273 bookmark_model->root_node());
1274 BOOL folderExists = NO;
1275
1276 while (iterator.has_next()) {
1277 const bookmarks::BookmarkNode* bookmark = iterator.Next();
1278 if (bookmark->is_url())
1279 continue;
1280 // This is a folder.
1281 if (bookmark->GetTitle() == folderTitle16) {
1282 folderExists = YES;
1283 break;
1284 }
1285 }
1286
1287 NSString* assertMessage =
1288 [NSString stringWithFormat:@"Folder %@ doesn't exist", title];
1289 GREYAssert(folderExists, assertMessage);
1290 }
1291
1292 // Asserts that |expectedCount| bookmarks exist with the corresponding |title|
1293 // using the BookmarkModel.
1294 + (void)assertBookmarksWithTitle:(NSString*)title
1295 expectedCount:(NSUInteger)expectedCount {
1296 // Get BookmarkModel and wait for it to be loaded.
1297 bookmarks::BookmarkModel* bookmarkModel =
1298 ios::BookmarkModelFactory::GetForBrowserState(
1299 chrome_test_util::GetOriginalBrowserState());
1300
1301 // Verify the correct number of bookmarks exist.
1302 base::string16 matchString = base::SysNSStringToUTF16(title);
1303 std::vector<bookmarks::TitledUrlMatch> matches;
1304 bookmarkModel->GetBookmarksMatching(matchString, 50, &matches);
1305 const size_t count = matches.size();
1306 GREYAssertEqual(expectedCount, count, @"Unexpected number of bookmarks");
1307 }
1308
1309 // Check that the currently edited bookmark is in |folderName| folder.
1310 + (void)assertFolderName:(NSString*)folderName {
1311 [[EarlGrey
1312 selectElementWithMatcher:grey_allOf(
1313 grey_accessibilityID(@"Change Folder"),
1314 grey_accessibilityLabel(folderName), nil)]
1315 assertWithMatcher:grey_notNil()];
1316 }
1317
1318 // Verifies that there is |count| children on the bookmark folder with |name|.
1319 + (void)assertChildCount:(int)count ofFolderWithName:(NSString*)name {
1320 base::string16 name16(base::SysNSStringToUTF16(name));
1321 bookmarks::BookmarkModel* bookmarkModel =
1322 ios::BookmarkModelFactory::GetForBrowserState(
1323 chrome_test_util::GetOriginalBrowserState());
1324
1325 ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator(
1326 bookmarkModel->root_node());
1327
1328 const bookmarks::BookmarkNode* folder = NULL;
1329 while (iterator.has_next()) {
1330 const bookmarks::BookmarkNode* bookmark = iterator.Next();
1331 if (bookmark->is_folder() && bookmark->GetTitle() == name16) {
1332 folder = bookmark;
1333 break;
1334 }
1335 }
1336 GREYAssert(folder, @"No folder named %@", name);
1337 GREYAssertEqual(
1338 folder->child_count(), count,
1339 @"Unexpected number of children in folder '%@': %d instead of %d", name,
1340 folder->child_count(), count);
1341 }
1342
1343 // Adds a bookmark with the given |url| and |title| into the Mobile Bookmarks
1344 // folder.
1345 + (void)addBookmark:(const GURL)url withTitle:(NSString*)title {
1346 [[self class] waitForBookmarkModelLoaded:YES];
1347 bookmarks::BookmarkModel* bookmark_model =
1348 ios::BookmarkModelFactory::GetForBrowserState(
1349 chrome_test_util::GetOriginalBrowserState());
1350 bookmark_model->AddURL(bookmark_model->mobile_node(), 0,
1351 base::SysNSStringToUTF16(title), url);
1352 }
1353
1354 // Creates a new folder starting from the folder picker.
1355 // Passing a |name| of 0 length will use the default value.
1356 + (void)addFolderWithName:(NSString*)name {
1357 // Wait for folder picker to appear.
1358 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Picker")]
1359 assertWithMatcher:grey_sufficientlyVisible()];
1360
1361 // Tap on Create new folder.
1362 [[EarlGrey
1363 selectElementWithMatcher:grey_accessibilityID(@"Create New Folder")]
1364 performAction:grey_tap()];
1365
1366 // Verify the folder creator is displayed.
1367 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Creator")]
1368 assertWithMatcher:grey_sufficientlyVisible()];
1369
1370 // Change the name of the folder.
1371 if (name.length > 0) {
1372 // TODO(crbug.com/644730): Use grey_replaceText instead of
1373 // grey_clearText/grey_typeText when EarlGrey's issue is fixed:
1374 // https://github.com/google/EarlGrey/issues/253
1375 [[EarlGrey
1376 selectElementWithMatcher:grey_accessibilityID(@"Title_textField")]
1377 performAction:grey_clearText()];
1378 [[EarlGrey
1379 selectElementWithMatcher:grey_accessibilityID(@"Title_textField")]
1380 performAction:grey_typeText(name)];
1381 }
1382
1383 // Tap the Save button.
1384 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Save")]
1385 performAction:grey_tap()];
1386 }
1387
1388 // Loads a set of default bookmarks in the model for the tests to use.
1389 + (void)setupStandardBookmarks {
1390 [[self class] waitForBookmarkModelLoaded:YES];
1391
1392 bookmarks::BookmarkModel* bookmark_model =
1393 ios::BookmarkModelFactory::GetForBrowserState(
1394 chrome_test_util::GetOriginalBrowserState());
1395
1396 const GURL firstURL = web::test::HttpServer::MakeUrl(
1397 "http://ios/testing/data/http_server_files/pony.html");
1398 NSString* firstTitle = @"First URL";
1399 bookmark_model->AddURL(bookmark_model->mobile_node(), 0,
1400 base::SysNSStringToUTF16(firstTitle), firstURL);
1401
1402 const GURL secondURL = web::test::HttpServer::MakeUrl(
1403 "http://ios/testing/data/http_server_files/destination.html");
1404 NSString* secondTitle = @"Second URL";
1405 bookmark_model->AddURL(bookmark_model->mobile_node(), 0,
1406 base::SysNSStringToUTF16(secondTitle), secondURL);
1407
1408 NSString* folderTitle = @"Folder 1";
1409 const bookmarks::BookmarkNode* folder1 = bookmark_model->AddFolder(
1410 bookmark_model->mobile_node(), 0, base::SysNSStringToUTF16(folderTitle));
1411
1412 folderTitle = @"Folder 2";
1413 const bookmarks::BookmarkNode* folder2 = bookmark_model->AddFolder(
1414 folder1, 0, base::SysNSStringToUTF16(folderTitle));
1415
1416 folderTitle = @"Folder 3";
1417 const bookmarks::BookmarkNode* folder3 = bookmark_model->AddFolder(
1418 folder2, 0, base::SysNSStringToUTF16(folderTitle));
1419
1420 const GURL thirdURL = web::test::HttpServer::MakeUrl(
1421 "http://ios/testing/data/http_server_files/chromium_logo_page.html");
1422 NSString* thirdTitle = @"Third URL";
1423 bookmark_model->AddURL(folder3, 0, base::SysNSStringToUTF16(thirdTitle),
1424 thirdURL);
1425 }
1426
1427 // Checks that the promo has already been seen or not.
1428 + (void)verifyPromoAlreadySeen:(BOOL)seen {
1429 ios::ChromeBrowserState* browserState =
1430 chrome_test_util::GetOriginalBrowserState();
1431 PrefService* prefs = browserState->GetPrefs();
1432 if (prefs->GetBoolean(prefs::kIosBookmarkPromoAlreadySeen) == seen) {
1433 return;
1434 }
1435 NSString* errorDesc = (seen)
1436 ? @"Expected promo already seen, but it wasn't."
1437 : @"Expected promo not already seen, but it was.";
1438 GREYFail(errorDesc);
1439 }
1440
1441 // Checks that the promo has already been seen or not.
1442 + (void)setPromoAlreadySeen:(BOOL)seen {
1443 ios::ChromeBrowserState* browserState =
1444 chrome_test_util::GetOriginalBrowserState();
1445 PrefService* prefs = browserState->GetPrefs();
1446 prefs->SetBoolean(prefs::kIosBookmarkPromoAlreadySeen, seen);
1447 }
1448
1449 + (void)assertExistenceOfBookmarkWithURL:(NSString*)URL name:(NSString*)name {
1450 bookmarks::BookmarkModel* bookmarkModel =
1451 ios::BookmarkModelFactory::GetForBrowserState(
1452 chrome_test_util::GetOriginalBrowserState());
1453 const bookmarks::BookmarkNode* bookmark =
1454 bookmarkModel->GetMostRecentlyAddedUserNodeForURL(
1455 GURL(base::SysNSStringToUTF16(URL)));
1456 GREYAssert(bookmark->GetTitle() == base::SysNSStringToUTF16(name),
1457 @"Could not find bookmark named %@ for %@", name, URL);
1458 }
1459
1460 + (void)assertAbsenceOfBookmarkWithURL:(NSString*)URL {
1461 bookmarks::BookmarkModel* bookmarkModel =
1462 ios::BookmarkModelFactory::GetForBrowserState(
1463 chrome_test_util::GetOriginalBrowserState());
1464 const bookmarks::BookmarkNode* bookmark =
1465 bookmarkModel->GetMostRecentlyAddedUserNodeForURL(
1466 GURL(base::SysNSStringToUTF16(URL)));
1467 GREYAssert(!bookmark, @"There is a bookmark for %@", URL);
1468 }
1469
1470 // Whether there is a bookmark folder with the given title.
1471 + (BOOL)folderExistsWithTitle:(NSString*)folderTitle {
1472 base::string16 folderTitle16(base::SysNSStringToUTF16(folderTitle));
1473 bookmarks::BookmarkModel* bookmarkModel =
1474 ios::BookmarkModelFactory::GetForBrowserState(
1475 chrome_test_util::GetOriginalBrowserState());
1476
1477 ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator(
1478 bookmarkModel->root_node());
1479
1480 while (iterator.has_next()) {
1481 const bookmarks::BookmarkNode* bookmark = iterator.Next();
1482 if (bookmark->is_url())
1483 continue;
1484 // This is a folder.
1485 if (bookmark->GetTitle() == folderTitle16)
1486 return YES;
1487 }
1488 return NO;
1489 }
1490
1491 // Asserts that there is a bookmark folder with the given title.
1492 + (void)assertFolderExistsWithTitle:(NSString*)folderTitle {
1493 GREYAssert([[self class] folderExistsWithTitle:folderTitle],
1494 @"There is no folder named %@", folderTitle);
1495 }
1496
1497 // Asserts that there is no bookmark folder with the given title.
1498 + (void)assertFolderDoesntExistWithTitle:(NSString*)folderTitle {
1499 GREYAssert(![[self class] folderExistsWithTitle:folderTitle],
1500 @"There is a folder named %@", folderTitle);
1501 }
1502
1503 // Deletes via the UI the currently focused folder. This must be called once
1504 // already in a non permanent folder (i.e. not Mobile Bookmarks, etc.).
1505 + (void)deleteSelectedFolder {
1506 // Enter edit mode.
1507 [[EarlGrey
1508 selectElementWithMatcher:grey_accessibilityID(@"Edit_navigation_bar")]
1509 performAction:grey_tap()];
1510
1511 // Delete the folder.
1512 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Delete Folder")]
1513 performAction:grey_tap()];
1514 }
1515
1516 // Removes programmatically the first bookmark with the given title.
1517 + (void)removeBookmarkWithTitle:(NSString*)title {
1518 base::string16 name16(base::SysNSStringToUTF16(title));
1519 bookmarks::BookmarkModel* bookmarkModel =
1520 ios::BookmarkModelFactory::GetForBrowserState(
1521 chrome_test_util::GetOriginalBrowserState());
1522 ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator(
1523 bookmarkModel->root_node());
1524 while (iterator.has_next()) {
1525 const bookmarks::BookmarkNode* bookmark = iterator.Next();
1526 if (bookmark->GetTitle() == name16) {
1527 bookmarkModel->Remove(bookmark);
1528 return;
1529 }
1530 }
1531 GREYFail(@"Could not remove bookmark with name %@", title);
1532 }
1533
1534 // Waits for the disparition of the given |title| in the UI.
1535 + (void)waitForDeletionOfBookmarkWithTitle:(NSString*)title {
1536 // Wait until it's gone.
1537 ConditionBlock condition = ^{
1538 NSError* error = nil;
1539 [[EarlGrey selectElementWithMatcher:grey_accessibilityID(title)]
1540 assertWithMatcher:grey_notVisible()
1541 error:&error];
1542 return error == nil;
1543 };
1544 GREYAssert(testing::WaitUntilConditionOrTimeout(10, condition),
1545 @"Waiting for bookmark to go away");
1546 }
1547
1548 // Adds a bookmark for the current tab. Must be called when on a tab.
1549 + (void)starCurrentTab {
1550 if (!IsCompact()) {
1551 [[EarlGrey selectElementWithMatcher:starButton()] performAction:grey_tap()];
1552 } else {
1553 [ChromeEarlGreyUI openToolsMenu];
1554 [[EarlGrey selectElementWithMatcher:addBookmarkButton()]
1555 performAction:grey_tap()];
1556 }
1557 }
1558
1559 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698