blob: e4c5525c38c466bdf118eabac530fe106f565ada [file] [log] [blame]
// 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 <XCTest/XCTest.h>
#include "base/mac/foundation_util.h"
#include "base/metrics/field_trial.h"
#include "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#include "components/version_info/version_info.h"
#include "ios/chrome/browser/chrome_url_constants.h"
#include "ios/chrome/browser/system_flags.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.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_error_util.h"
#import "ios/chrome/test/earl_grey/chrome_matchers.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#import "ios/web/public/web_client.h"
#include "ui/base/device_form_factor.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/scheme_host_port.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using chrome_test_util::BackButton;
using chrome_test_util::ForwardButton;
namespace {
// Loads WebUI page with given |host|.
void LoadWebUIUrl(const std::string& host) {
GURL web_ui_url(url::SchemeHostPort(kChromeUIScheme, host, 0).Serialize());
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:web_ui_url]);
}
// Adds wait for omnibox text matcher so that omnibox text can be updated.
// TODO(crbug.com/642207): This method has to be unified with the omniboxText
// matcher or resides in the same location with the omniboxText matcher.
id<GREYMatcher> WaitForOmniboxText(std::string text) {
MatchesBlock matches = ^BOOL(UIView* view) {
if (![view isKindOfClass:[OmniboxTextFieldIOS class]]) {
return NO;
}
OmniboxTextFieldIOS* omnibox =
base::mac::ObjCCast<OmniboxTextFieldIOS>(view);
GREYAssert(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForUIElementTimeout,
^{
return base::SysNSStringToUTF8(omnibox.text) == text;
}),
@"Omnibox did not contain %@", base::SysUTF8ToNSString(text));
return YES;
};
DescribeToBlock describe = ^(id<GREYDescription> description) {
[description appendText:@"omnibox text "];
[description appendText:base::SysUTF8ToNSString(text)];
};
return grey_allOf(
chrome_test_util::Omnibox(),
[[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
descriptionBlock:describe],
nil);
}
} // namespace
// Test case for chrome://* WebUI pages.
@interface WebUITestCase : ChromeTestCase
@end
@implementation WebUITestCase
// Tests that chrome://version renders and contains correct version number and
// user agent string.
- (void)testVersion {
LoadWebUIUrl(kChromeUIVersionHost);
// Verify that app version is present on the page.
const std::string version = version_info::GetVersionNumber();
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:version]);
// Verify that mobile User Agent string is present on the page.
const std::string userAgent =
web::GetWebClient()->GetUserAgent(web::UserAgentType::MOBILE);
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:userAgent]);
}
// Tests that clicking on a chrome://terms link from chrome://chrome-urls
// navigates to terms page.
- (void)testChromeURLNavigateToTerms {
LoadWebUIUrl(kChromeUIChromeURLsHost);
// Tap on chrome://terms link on the page.
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
tapWebStateElementWithID:[NSString
stringWithUTF8String:kChromeUITermsHost]]);
// Verify that the resulting page is chrome://terms.
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://terms")]
assertWithMatcher:grey_notNil()];
const std::string kTermsText = "Google Chrome Terms of Service";
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:kTermsText]);
}
// Tests that back navigation functions properly after navigation via anchor
// click.
- (void)testChromeURLBackNavigationFromAnchorClick {
LoadWebUIUrl(kChromeUIChromeURLsHost);
// Tap on chrome://version link on the page.
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
tapWebStateElementWithID:[NSString
stringWithUTF8String:kChromeUIVersionHost]]);
// Verify that the resulting page is chrome://version.
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://version")]
assertWithMatcher:grey_notNil()];
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:"The Chromium Authors"]);
// Tap the back button in the toolbar and verify that the resulting page is
// the previously visited page chrome://chrome-urls.
[[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()];
[[EarlGrey
selectElementWithMatcher:WaitForOmniboxText("chrome://chrome-urls")]
assertWithMatcher:grey_notNil()];
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:"List of Chrome URLs"]);
}
// Tests that back and forward navigation between chrome URLs functions
// properly.
- (void)testChromeURLBackAndForwardAndReloadNavigation {
// Navigate to the first URL chrome://version.
LoadWebUIUrl(kChromeUIVersionHost);
// Navigate to the second URL chrome://flags.
LoadWebUIUrl(kChromeUIFlagsHost);
// Tap the back button in the toolbar and verify that the resulting page's URL
// corresponds to the first URL chrome://version that was loaded.
[[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://version")]
assertWithMatcher:grey_notNil()];
// Tap the forward button in the toolbar and verify that the resulting page's
// URL corresponds the second URL chrome://flags that was loaded.
[[EarlGrey selectElementWithMatcher:ForwardButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://flags")]
assertWithMatcher:grey_notNil()];
// Tap the back button in the toolbar then reload, and verify that the
// resulting page corresponds to the first URL.
[[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()];
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForPageToFinishLoading]);
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey reload]);
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://version")]
assertWithMatcher:grey_notNil()];
// Make sure forward navigation is still possible.
[[EarlGrey selectElementWithMatcher:ForwardButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://flags")]
assertWithMatcher:grey_notNil()];
}
// Tests that all URLs on chrome://chrome-urls page load without error.
- (void)testChromeURLsLoadWithoutError {
// Load WebUI pages and verify they load without any error.
for (size_t i = 0; i < kNumberOfChromeHostURLs; ++i) {
const char* host = kChromeHostURLs[i];
// Exclude non-WebUI pages, as they do not go through a "loading" phase as
// expected in LoadWebUIUrl.
if (host == kChromeUINewTabHost) {
continue;
}
LoadWebUIUrl(host);
const std::string chrome_url_path =
url::SchemeHostPort(kChromeUIScheme, kChromeHostURLs[i], 0).Serialize();
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText(chrome_url_path)]
assertWithMatcher:grey_notNil()];
}
}
// Tests that loading an invalid Chrome URL results in an error page.
- (void)testChromeURLInvalid {
// Navigate to the native error page chrome://invalidchromeurl.
const std::string kChromeInvalidURL = "chrome://invalidchromeurl";
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeInvalidURL)]);
// Verify that the resulting page is an error page.
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText(kChromeInvalidURL)]
assertWithMatcher:grey_notNil()];
std::string errorMessage = net::ErrorToShortString(net::ERR_INVALID_URL);
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:errorMessage]);
}
// Tests that repeated back/forward navigation from web URL is allowed.
- (void)testBackForwardFromWebURL {
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
// Not using kChromeUIVersionURL because it has a final "/" that is not
// displayed in Omnibox.
const char kChromeVersionURL[] = "chrome://version";
const char kChromeVersionWebText[] = "The Chromium Authors";
const char kWebPageText[] = "pony";
LoadWebUIUrl(kChromeUIVersionHost);
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText(kChromeVersionURL)]
assertWithMatcher:grey_notNil()];
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText]);
GURL webURL = self.testServer->GetURL("/pony.html");
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:webURL]);
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:kWebPageText]);
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey goBack]);
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText(kChromeVersionURL)]
assertWithMatcher:grey_notNil()];
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText]);
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey goForward]);
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:kWebPageText]);
CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey goBack]);
[[EarlGrey selectElementWithMatcher:WaitForOmniboxText(kChromeVersionURL)]
assertWithMatcher:grey_notNil()];
CHROME_EG_ASSERT_NO_ERROR(
[ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText]);
}
@end