Index: ios/chrome/browser/ui/history/history_ui_egtest.mm |
diff --git a/ios/chrome/browser/ui/history/history_ui_egtest.mm b/ios/chrome/browser/ui/history/history_ui_egtest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..79819ea98e3e6ff88787978ccbf385d2b588d0b4 |
--- /dev/null |
+++ b/ios/chrome/browser/ui/history/history_ui_egtest.mm |
@@ -0,0 +1,425 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import <EarlGrey/EarlGrey.h> |
+#import <UIKit/UIKit.h> |
+#import <XCTest/XCTest.h> |
+ |
+#include "base/strings/sys_string_conversions.h" |
+#include "components/browsing_data/core/pref_names.h" |
+#include "components/prefs/pref_service.h" |
+#include "components/strings/grit/components_strings.h" |
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
+#import "ios/chrome/browser/ui/history/history_entry_item.h" |
+#import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h" |
+#include "ios/chrome/grit/ios_strings.h" |
+#import "ios/chrome/test/app/chrome_test_util.h" |
+#import "ios/chrome/test/earl_grey/accessibility_util.h" |
+#import "ios/chrome/test/earl_grey/chrome_assertions.h" |
+#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" |
+#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" |
+#import "ios/chrome/test/earl_grey/chrome_matchers.h" |
+#import "ios/chrome/test/earl_grey/chrome_test_case.h" |
+#import "ios/testing/wait_util.h" |
+#import "ios/web/public/test/http_server.h" |
+#import "ios/web/public/test/http_server_util.h" |
+#import "net/base/mac/url_conversions.h" |
+#include "ui/base/l10n/l10n_util.h" |
+ |
+using chrome_test_util::buttonWithAccessibilityLabelId; |
+ |
+namespace { |
+char kURL1[] = "http://firstURL"; |
+char kURL2[] = "http://secondURL"; |
+char kURL3[] = "http://thirdURL"; |
+char kResponse1[] = "Test Page 1"; |
+char kResponse2[] = "Test Page 2"; |
+char kResponse3[] = "Test Page 3"; |
+ |
+// Matcher for entry in history for URL. |
+id<GREYMatcher> historyEntryWithURL(const GURL& url) { |
+ NSString* url_spec = base::SysUTF8ToNSString(url.spec()); |
+ return grey_allOf(grey_text(url_spec), grey_sufficientlyVisible(), nil); |
+} |
+// Matcher for the history button in the tools menu. |
+id<GREYMatcher> historyButton() { |
+ return buttonWithAccessibilityLabelId(IDS_HISTORY_SHOW_HISTORY); |
+} |
+// Matcher for the done button in the navigation bar. |
+id<GREYMatcher> navigationDoneButton() { |
+ // Include sufficientlyVisible condition for the case of the clear browsing |
+ // dialog, which also has a "Done" button and is displayed over the history |
+ // panel. |
+ return grey_allOf( |
+ buttonWithAccessibilityLabelId(IDS_IOS_NAVIGATION_BAR_DONE_BUTTON), |
+ grey_sufficientlyVisible(), nil); |
+} |
+// Matcher for the edit button in the navigation bar. |
+id<GREYMatcher> navigationEditButton() { |
+ return buttonWithAccessibilityLabelId(IDS_HISTORY_START_EDITING_BUTTON); |
+} |
+// Matcher for the delete button. |
+id<GREYMatcher> deleteHistoryEntriesButton() { |
+ // Include class restriction to exclude MDCCollectionViewInfoBar, which is |
+ // hidden. |
+ return grey_allOf(buttonWithAccessibilityLabelId( |
+ IDS_HISTORY_DELETE_SELECTED_ENTRIES_BUTTON), |
+ grey_kindOfClass([UIButton class]), nil); |
+} |
+// Matcher for the search button. |
+id<GREYMatcher> searchIconButton() { |
+ return buttonWithAccessibilityLabelId(IDS_IOS_ICON_SEARCH); |
+} |
+// Matcher for the cancel button. |
+id<GREYMatcher> cancelButton() { |
+ return buttonWithAccessibilityLabelId(IDS_HISTORY_CANCEL_EDITING_BUTTON); |
+} |
+// Matcher for the button to open the clear browsing data panel. |
+id<GREYMatcher> openClearBrowsingDataButton() { |
+ return buttonWithAccessibilityLabelId( |
+ IDS_HISTORY_OPEN_CLEAR_BROWSING_DATA_DIALOG); |
+} |
+// Matcher for the Open in New Tab option in the context menu. |
+id<GREYMatcher> openInNewTabButton() { |
+ return buttonWithAccessibilityLabelId(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB); |
+} |
+// Matcher for the Open in New Incognito Tab option in the context menu. |
+id<GREYMatcher> openInNewIncognitoTabButton() { |
+ return buttonWithAccessibilityLabelId( |
+ IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB); |
+} |
+// Matcher for the Copy URL option in the context menu. |
+id<GREYMatcher> copyUrlButton() { |
+ return buttonWithAccessibilityLabelId(IDS_IOS_CONTENT_CONTEXT_COPY); |
+} |
+// Matcher for the clear cookies cell on the clear browsing data panel. |
+id<GREYMatcher> clearCookiesButton() { |
+ return grey_accessibilityID(kClearCookiesCellId); |
+} |
+// Matcher for the clear cache cell on the clear browsing data panel. |
+id<GREYMatcher> clearCacheButton() { |
+ return grey_allOf(grey_accessibilityID(kClearCacheCellId), |
+ grey_sufficientlyVisible(), nil); |
+} |
+// Matcher for the clear browsing data button on the clear browsing data panel. |
+id<GREYMatcher> clearBrowsingDataButton() { |
+ return buttonWithAccessibilityLabelId(IDS_IOS_CLEAR_BUTTON); |
+} |
+ |
+} // namespace |
+ |
+// History UI tests. |
+@interface HistoryUITestCase : ChromeTestCase { |
+ GURL _URL1; |
+ GURL _URL2; |
+ GURL _URL3; |
+} |
+ |
+// Loads three test URLs. |
+- (void)loadTestURLs; |
+// Displays the history UI. |
+- (void)openHistoryPanel; |
+// Asserts that the history UI displays no history entries. |
+- (void)assertNoHistoryShown; |
+// Resets which data is selected in the Clear Browsing Data UI. |
+- (void)resetBrowsingDataPrefs; |
+ |
+@end |
+ |
+@implementation HistoryUITestCase |
+ |
+// Set up called once for the class. |
++ (void)setUp { |
+ [super setUp]; |
+ std::map<GURL, std::string> responses; |
+ responses[web::test::HttpServer::MakeUrl(kURL1)] = kResponse1; |
+ responses[web::test::HttpServer::MakeUrl(kURL2)] = kResponse2; |
+ responses[web::test::HttpServer::MakeUrl(kURL3)] = kResponse3; |
+ web::test::SetUpSimpleHttpServer(responses); |
+} |
+ |
+- (void)setUp { |
+ [super setUp]; |
+ _URL1 = web::test::HttpServer::MakeUrl(kURL1); |
+ _URL2 = web::test::HttpServer::MakeUrl(kURL2); |
+ _URL3 = web::test::HttpServer::MakeUrl(kURL3); |
+ [ChromeEarlGrey clearBrowsingHistory]; |
+ // Some tests rely on a clean state for the "Clear Browsing Data" settings |
+ // screen. |
+ [self resetBrowsingDataPrefs]; |
+} |
+ |
+- (void)tearDown { |
+ NSError* error = nil; |
+ // Dismiss search bar by pressing cancel, if present. Passing error prevents |
+ // failure if the element is not found. |
+ [[EarlGrey selectElementWithMatcher:cancelButton()] performAction:grey_tap() |
+ error:&error]; |
+ // Dismiss history panel by pressing done, if present. Passing error prevents |
+ // failure if the element is not found. |
+ [[EarlGrey selectElementWithMatcher:navigationDoneButton()] |
+ performAction:grey_tap() |
+ error:&error]; |
+ |
+ // Some tests change the default values for the "Clear Browsing Data" settings |
+ // screen. |
+ [self resetBrowsingDataPrefs]; |
+ [super tearDown]; |
+} |
+ |
+#pragma mark Tests |
+ |
+// Tests that no history is shown if there has been no navigation. |
+- (void)testDisplayNoHistory { |
+ [self openHistoryPanel]; |
+ [self assertNoHistoryShown]; |
+} |
+ |
+// Tests that the history panel displays navigation history. |
+- (void)testDisplayHistory { |
+ [self loadTestURLs]; |
+ [self openHistoryPanel]; |
+ |
+ // Assert that history displays three entries. |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ assertWithMatcher:grey_notNil()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL2)] |
+ assertWithMatcher:grey_notNil()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL3)] |
+ assertWithMatcher:grey_notNil()]; |
+ |
+ // Tap a history entry and assert that navigation to that entry's URL occurs. |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ performAction:grey_tap()]; |
+ id<GREYMatcher> webViewMatcher = |
+ chrome_test_util::webViewContainingText(kResponse1); |
+ [[EarlGrey selectElementWithMatcher:webViewMatcher] |
+ assertWithMatcher:grey_notNil()]; |
+} |
+ |
+// Tests that searching history displays only entries matching the search term. |
+- (void)testSearchHistory { |
+ [self loadTestURLs]; |
+ [self openHistoryPanel]; |
+ [[EarlGrey selectElementWithMatcher:searchIconButton()] |
+ performAction:grey_tap()]; |
+ |
+ NSString* searchString = |
+ [NSString stringWithFormat:@"%s", _URL1.path().c_str()]; |
+ [[EarlGrey selectElementWithMatcher:grey_keyWindow()] |
+ performAction:grey_typeText(searchString)]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ assertWithMatcher:grey_notNil()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL2)] |
+ assertWithMatcher:grey_nil()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL3)] |
+ assertWithMatcher:grey_nil()]; |
+} |
+ |
+// Tests deletion of history entries. |
+- (void)testDeleteHistory { |
+ [self loadTestURLs]; |
+ [self openHistoryPanel]; |
+ |
+ // Assert that three history elements are present. |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ assertWithMatcher:grey_notNil()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL2)] |
+ assertWithMatcher:grey_notNil()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL3)] |
+ assertWithMatcher:grey_notNil()]; |
+ |
+ // Enter edit mode, select a history element, and press delete. |
+ [[EarlGrey selectElementWithMatcher:navigationEditButton()] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:deleteHistoryEntriesButton()] |
+ performAction:grey_tap()]; |
+ |
+ // Assert that the deleted entry is gone and the other two remain. |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ assertWithMatcher:grey_nil()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL2)] |
+ assertWithMatcher:grey_notNil()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL3)] |
+ assertWithMatcher:grey_notNil()]; |
+ |
+ // Enter edit mode, select both remaining entries, and press delete. |
+ [[EarlGrey selectElementWithMatcher:navigationEditButton()] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL2)] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL3)] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:deleteHistoryEntriesButton()] |
+ performAction:grey_tap()]; |
+ |
+ [self assertNoHistoryShown]; |
+} |
+ |
+// Tests clear browsing history. |
+- (void)testClearBrowsingHistory { |
+ [self loadTestURLs]; |
+ [self openHistoryPanel]; |
+ |
+ // Open the Clear Browsing Data dialog. |
+ [[EarlGrey selectElementWithMatcher:openClearBrowsingDataButton()] |
+ performAction:grey_tap()]; |
+ |
+ // Uncheck "Cookies, Site Data" and "Cached Images and Files," which are |
+ // checked by default, and press "Clear Browsing Data" |
+ [[EarlGrey selectElementWithMatcher:clearCookiesButton()] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:clearCacheButton()] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:clearBrowsingDataButton()] |
+ performAction:grey_tap()]; |
+ |
+ // There is not currently a matcher for acessibilityElementIsFocused or |
+ // userInteractionEnabled which could be used here instead of checking that |
+ // the button is not a MDCCollectionViewTextCell. Use when available. |
+ // TODO(crbug.com/638674): Evaluate if this can move to shared code. |
+ id<GREYMatcher> confirmClear = grey_allOf( |
+ clearBrowsingDataButton(), |
+ grey_not(grey_kindOfClass([MDCCollectionViewTextCell class])), nil); |
+ [[EarlGrey selectElementWithMatcher:confirmClear] performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:navigationDoneButton()] |
+ performAction:grey_tap()]; |
+ |
+ [self assertNoHistoryShown]; |
+} |
+ |
+// Tests display and selection of 'Open in New Tab' in a context menu on a |
+// history entry. |
+- (void)testContextMenuOpenInNewTab { |
+ [self loadTestURLs]; |
+ [self openHistoryPanel]; |
+ |
+ // Long press on the history element. |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ performAction:grey_longPress()]; |
+ |
+ // Select "Open in New Tab" and confirm that new tab is opened with selected |
+ // URL. |
+ [[EarlGrey selectElementWithMatcher:openInNewTabButton()] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:chrome_test_util::omniboxText( |
+ _URL1.GetContent())] |
+ assertWithMatcher:grey_notNil()]; |
+ chrome_test_util::AssertMainTabCount(2); |
+} |
+ |
+// Tests display and selection of 'Open in New Incognito Tab' in a context menu |
+// on a history entry. |
+- (void)testContextMenuOpenInNewIncognitoTab { |
+ [self loadTestURLs]; |
+ [self openHistoryPanel]; |
+ |
+ // Long press on the history element. |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ performAction:grey_longPress()]; |
+ |
+ // Select "Open in New Incognito Tab" and confirm that new tab is opened in |
+ // incognito with the selected URL. |
+ [[EarlGrey selectElementWithMatcher:openInNewIncognitoTabButton()] |
+ performAction:grey_tap()]; |
+ [[EarlGrey selectElementWithMatcher:chrome_test_util::omniboxText( |
+ _URL1.GetContent())] |
+ assertWithMatcher:grey_notNil()]; |
+ chrome_test_util::AssertMainTabCount(1); |
+ chrome_test_util::AssertIncognitoTabCount(1); |
+} |
+ |
+// Tests display and selection of 'Copy URL' in a context menu on a history |
+// entry. |
+- (void)testContextMenuCopy { |
+ ProceduralBlock clearPasteboard = ^{ |
+ [[UIPasteboard generalPasteboard] setURLs:nil]; |
+ }; |
+ [self setTearDownHandler:clearPasteboard]; |
+ clearPasteboard(); |
+ |
+ [self loadTestURLs]; |
+ [self openHistoryPanel]; |
+ |
+ // Long press on the history element. |
+ [[EarlGrey selectElementWithMatcher:historyEntryWithURL(_URL1)] |
+ performAction:grey_longPress()]; |
+ |
+ // Tap "Copy URL" and wait for the URL to be copied to the pasteboard. |
+ [[EarlGrey selectElementWithMatcher:copyUrlButton()] |
+ performAction:grey_tap()]; |
+ bool success = |
+ testing::WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{ |
+ return _URL1 == |
+ net::GURLWithNSURL([UIPasteboard generalPasteboard].URL); |
+ }); |
+ GREYAssertTrue(success, @"Pasteboard URL was not set to %s", |
+ _URL1.spec().c_str()); |
+} |
+ |
+// Navigates to history and checks elements for accessibility. |
+- (void)testAccessibilityOnHistory { |
+ [self openHistoryPanel]; |
+ chrome_test_util::VerifyAccessibilityForCurrentScreen(); |
+ // Close history. |
+ [[EarlGrey |
+ selectElementWithMatcher:chrome_test_util::buttonWithAccessibilityLabelId( |
+ IDS_IOS_NAVIGATION_BAR_DONE_BUTTON)] |
+ performAction:grey_tap()]; |
+} |
+ |
+#pragma mark Helper Methods |
+ |
+- (void)loadTestURLs { |
+ [ChromeEarlGrey loadURL:_URL1]; |
+ id<GREYMatcher> response1Matcher = |
+ chrome_test_util::webViewContainingText(kResponse1); |
+ [[EarlGrey selectElementWithMatcher:response1Matcher] |
+ assertWithMatcher:grey_notNil()]; |
+ |
+ [ChromeEarlGrey loadURL:_URL2]; |
+ id<GREYMatcher> response2Matcher = |
+ chrome_test_util::webViewContainingText(kResponse2); |
+ [[EarlGrey selectElementWithMatcher:response2Matcher] |
+ assertWithMatcher:grey_notNil()]; |
+ |
+ [ChromeEarlGrey loadURL:_URL3]; |
+ id<GREYMatcher> response3Matcher = |
+ chrome_test_util::webViewContainingText(kResponse3); |
+ [[EarlGrey selectElementWithMatcher:response3Matcher] |
+ assertWithMatcher:grey_notNil()]; |
+} |
+ |
+- (void)openHistoryPanel { |
+ [ChromeEarlGreyUI openToolsMenu]; |
+ [[EarlGrey selectElementWithMatcher:historyButton()] |
+ performAction:grey_tap()]; |
+} |
+ |
+- (void)assertNoHistoryShown { |
+ id<GREYMatcher> noHistoryMessageMatcher = |
+ grey_allOf(grey_text(l10n_util::GetNSString(IDS_HISTORY_NO_RESULTS)), |
+ grey_sufficientlyVisible(), nil); |
+ [[EarlGrey selectElementWithMatcher:noHistoryMessageMatcher] |
+ assertWithMatcher:grey_notNil()]; |
+ |
+ id<GREYMatcher> historyEntryMatcher = |
+ grey_allOf(grey_kindOfClass([HistoryEntryCell class]), |
+ grey_sufficientlyVisible(), nil); |
+ [[EarlGrey selectElementWithMatcher:historyEntryMatcher] |
+ assertWithMatcher:grey_nil()]; |
+} |
+ |
+- (void)resetBrowsingDataPrefs { |
+ PrefService* prefs = chrome_test_util::GetOriginalBrowserState()->GetPrefs(); |
+ prefs->ClearPref(browsing_data::prefs::kDeleteBrowsingHistory); |
+ prefs->ClearPref(browsing_data::prefs::kDeleteCookies); |
+ prefs->ClearPref(browsing_data::prefs::kDeleteCache); |
+ prefs->ClearPref(browsing_data::prefs::kDeletePasswords); |
+ prefs->ClearPref(browsing_data::prefs::kDeleteFormData); |
+} |
+ |
+@end |