| Index: ios/chrome/browser/web/browsing_egtest.mm
|
| diff --git a/ios/chrome/browser/web/browsing_egtest.mm b/ios/chrome/browser/web/browsing_egtest.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d7cbd57734b00bafedfa7a0ca6045e22c40aa1cf
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/web/browsing_egtest.mm
|
| @@ -0,0 +1,651 @@
|
| +// 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 <XCTest/XCTest.h>
|
| +#include <map>
|
| +#include <memory>
|
| +#include <string>
|
| +
|
| +#include "base/ios/ios_util.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "components/content_settings/core/browser/host_content_settings_map.h"
|
| +#include "components/content_settings/core/common/content_settings.h"
|
| +#include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h"
|
| +#import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
|
| +#include "ios/chrome/browser/ui/commands/ios_command_ids.h"
|
| +#include "ios/chrome/browser/ui/ui_util.h"
|
| +#include "ios/chrome/grit/ios_strings.h"
|
| +#import "ios/chrome/test/app/chrome_test_util.h"
|
| +#include "ios/chrome/test/app/navigation_test_util.h"
|
| +#include "ios/chrome/test/app/web_view_interaction_test_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/earl_grey/disabled_test_macros.h"
|
| +#import "ios/testing/wait_util.h"
|
| +#import "ios/web/public/test/earl_grey/web_view_actions.h"
|
| +#import "ios/web/public/test/earl_grey/web_view_matchers.h"
|
| +#import "ios/web/public/test/http_server.h"
|
| +#include "ios/web/public/test/http_server_util.h"
|
| +#include "ios/web/public/test/response_providers/data_response_provider.h"
|
| +#include "net/http/http_response_headers.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "url/gurl.h"
|
| +
|
| +using chrome_test_util::omniboxText;
|
| +using chrome_test_util::webViewContainingText;
|
| +
|
| +namespace {
|
| +
|
| +// URL used for the reload test.
|
| +const char kReloadTestUrl[] = "http://mock/reloadTest";
|
| +
|
| +// Returns the number of serviced requests in HTTP body.
|
| +class ReloadResponseProvider : public web::DataResponseProvider {
|
| + public:
|
| + ReloadResponseProvider() : request_number_(0) {}
|
| +
|
| + // URL used for the reload test.
|
| + static GURL GetReloadTestUrl() {
|
| + return web::test::HttpServer::MakeUrl(kReloadTestUrl);
|
| + }
|
| +
|
| + bool CanHandleRequest(const Request& request) override {
|
| + return request.url == ReloadResponseProvider::GetReloadTestUrl();
|
| + }
|
| +
|
| + void GetResponseHeadersAndBody(
|
| + const Request& request,
|
| + scoped_refptr<net::HttpResponseHeaders>* headers,
|
| + std::string* response_body) override {
|
| + DCHECK_EQ(ReloadResponseProvider::GetReloadTestUrl(), request.url);
|
| + *headers = GetDefaultResponseHeaders();
|
| + *response_body = GetResponseBody(request_number_++);
|
| + }
|
| +
|
| + // static
|
| + static std::string GetResponseBody(int request_number) {
|
| + return base::StringPrintf("Load request %d", request_number);
|
| + }
|
| +
|
| + private:
|
| + int request_number_; // Count of requests received by the response provider.
|
| +};
|
| +
|
| +// ScopedBlockPopupsPref modifies the block popups preference and resets the
|
| +// preference to its original value when this object goes out of scope.
|
| +// TODO(crbug.com/638674): Evaluate if this can move to shared code
|
| +class ScopedBlockPopupsPref {
|
| + public:
|
| + ScopedBlockPopupsPref(ContentSetting setting) {
|
| + original_setting_ = GetPrefValue();
|
| + SetPrefValue(setting);
|
| + }
|
| + ~ScopedBlockPopupsPref() { SetPrefValue(original_setting_); }
|
| +
|
| + private:
|
| + // Gets the current value of the preference.
|
| + ContentSetting GetPrefValue() {
|
| + ContentSetting popupSetting =
|
| + ios::HostContentSettingsMapFactory::GetForBrowserState(
|
| + chrome_test_util::GetOriginalBrowserState())
|
| + ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS, NULL);
|
| + return popupSetting;
|
| + }
|
| +
|
| + // Sets the preference to the given value.
|
| + void SetPrefValue(ContentSetting setting) {
|
| + DCHECK(setting == CONTENT_SETTING_BLOCK ||
|
| + setting == CONTENT_SETTING_ALLOW);
|
| + ios::ChromeBrowserState* state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + ios::HostContentSettingsMapFactory::GetForBrowserState(state)
|
| + ->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS, setting);
|
| + }
|
| +
|
| + // Saves the original pref setting so that it can be restored when the scoper
|
| + // is destroyed.
|
| + ContentSetting original_setting_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ScopedBlockPopupsPref);
|
| +};
|
| +} // namespace
|
| +
|
| +// Tests web browsing scenarios.
|
| +@interface BrowsingTestCase : ChromeTestCase
|
| +@end
|
| +
|
| +@implementation BrowsingTestCase
|
| +
|
| +// Matcher for the title of the current tab (on tablet only).
|
| +id<GREYMatcher> tabWithTitle(const std::string& tab_title) {
|
| + id<GREYMatcher> notPartOfOmnibox =
|
| + grey_not(grey_ancestor(chrome_test_util::omnibox()));
|
| + return grey_allOf(grey_accessibilityLabel(base::SysUTF8ToNSString(tab_title)),
|
| + notPartOfOmnibox, nil);
|
| +}
|
| +
|
| +// Tests that page successfully reloads.
|
| +- (void)testReload {
|
| + // Set up test HTTP server responses.
|
| + std::unique_ptr<web::DataResponseProvider> provider(
|
| + new ReloadResponseProvider());
|
| + web::test::SetUpHttpServer(std::move(provider));
|
| +
|
| + GURL URL = ReloadResponseProvider::GetReloadTestUrl();
|
| + [ChromeEarlGrey loadURL:URL];
|
| + std::string expectedBodyBeforeReload(
|
| + ReloadResponseProvider::GetResponseBody(0 /* request number */));
|
| + [[EarlGrey
|
| + selectElementWithMatcher:webViewContainingText(expectedBodyBeforeReload)]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + [ChromeEarlGreyUI reload];
|
| + std::string expectedBodyAfterReload(
|
| + ReloadResponseProvider::GetResponseBody(1 /* request_number */));
|
| + [[EarlGrey
|
| + selectElementWithMatcher:webViewContainingText(expectedBodyAfterReload)]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests that a tab's title is based on the URL when no other information is
|
| +// available.
|
| +- (void)testBrowsingTabTitleSetFromURL {
|
| + if (!IsIPadIdiom()) {
|
| + EARL_GREY_TEST_SKIPPED(@"Tab Title not displayed on handset.");
|
| + }
|
| +
|
| + web::test::SetUpFileBasedHttpServer();
|
| +
|
| + const GURL destinationURL = web::test::HttpServer::MakeUrl(
|
| + "http://ios/testing/data/http_server_files/destination.html");
|
| + [ChromeEarlGrey loadURL:destinationURL];
|
| +
|
| + // Add 3 for the "://" which is not considered part of the scheme
|
| + std::string URLWithoutScheme =
|
| + destinationURL.spec().substr(destinationURL.scheme().length() + 3);
|
| +
|
| + [[EarlGrey selectElementWithMatcher:tabWithTitle(URLWithoutScheme)]
|
| + assertWithMatcher:grey_sufficientlyVisible()];
|
| +}
|
| +
|
| +// Tests that after a PDF is loaded, the title appears in the tab bar on iPad.
|
| +- (void)testPDFLoadTitle {
|
| + if (!IsIPadIdiom()) {
|
| + EARL_GREY_TEST_SKIPPED(@"Tab Title not displayed on handset.");
|
| + }
|
| +
|
| + web::test::SetUpFileBasedHttpServer();
|
| +
|
| + const GURL destinationURL = web::test::HttpServer::MakeUrl(
|
| + "http://ios/testing/data/http_server_files/testpage.pdf");
|
| + [ChromeEarlGrey loadURL:destinationURL];
|
| +
|
| + // Add 3 for the "://" which is not considered part of the scheme
|
| + std::string URLWithoutScheme =
|
| + destinationURL.spec().substr(destinationURL.scheme().length() + 3);
|
| +
|
| + [[EarlGrey selectElementWithMatcher:tabWithTitle(URLWithoutScheme)]
|
| + assertWithMatcher:grey_sufficientlyVisible()];
|
| +}
|
| +
|
| +// Tests that tab title is set to the specified title from a JavaScript.
|
| +- (void)testBrowsingTabTitleSetFromScript {
|
| + if (!IsIPadIdiom()) {
|
| + EARL_GREY_TEST_SKIPPED(@"Tab Title not displayed on handset.");
|
| + }
|
| +
|
| + const char* kPageTitle = "Some title";
|
| + const GURL URL = GURL(base::StringPrintf(
|
| + "data:text/html;charset=utf-8,<script>document.title = "
|
| + "\"%s\"</script>",
|
| + kPageTitle));
|
| + [ChromeEarlGrey loadURL:URL];
|
| +
|
| + [[EarlGrey selectElementWithMatcher:tabWithTitle(kPageTitle)]
|
| + assertWithMatcher:grey_sufficientlyVisible()];
|
| +}
|
| +
|
| +// Tests clicking a link with target="_blank" and "event.stopPropagation()"
|
| +// opens a new tab.
|
| +- (void)testBrowsingStopPropagation {
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL URL = web::test::HttpServer::MakeUrl("http://stopPropagation");
|
| + const GURL destinationURL =
|
| + web::test::HttpServer::MakeUrl("http://destination");
|
| + // This is a page with a link to |kDestination|.
|
| + responses[URL] = base::StringPrintf(
|
| + "<a id='link' href='%s' target='_blank' "
|
| + "onclick='event.stopPropagation()'>link</a>",
|
| + destinationURL.spec().c_str());
|
| + // This is the destination page; it just contains some text.
|
| + responses[destinationURL] = "You've arrived!";
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_ALLOW);
|
| +
|
| + [ChromeEarlGrey loadURL:URL];
|
| + chrome_test_util::AssertMainTabCount(1);
|
| +
|
| + chrome_test_util::TapWebViewElementWithId("link");
|
| +
|
| + chrome_test_util::AssertMainTabCount(2);
|
| +
|
| + // Verify the new tab was opened with the expected URL.
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(destinationURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests clicking a relative link with target="_blank" and
|
| +// "event.stopPropagation()" opens a new tab.
|
| +- (void)testBrowsingStopPropagationRelativePath {
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL URL = web::test::HttpServer::MakeUrl("http://stopPropRel");
|
| + const GURL destinationURL =
|
| + web::test::HttpServer::MakeUrl("http://stopPropRel/#test");
|
| + // This is page with a relative link to "#test".
|
| + responses[URL] =
|
| + "<a id='link' href='#test' target='_blank' "
|
| + "onclick='event.stopPropagation()'>link</a>";
|
| + // This is the page that should be showing at the end of the test.
|
| + responses[destinationURL] = "You've arrived!";
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_ALLOW);
|
| +
|
| + [ChromeEarlGrey loadURL:URL];
|
| + chrome_test_util::AssertMainTabCount(1);
|
| +
|
| + chrome_test_util::TapWebViewElementWithId("link");
|
| +
|
| + chrome_test_util::AssertMainTabCount(2);
|
| +
|
| + // Verify the new tab was opened with the expected URL.
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(destinationURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests that clicking a link with URL changed by onclick uses the href of the
|
| +// anchor tag instead of the one specified in JavaScript. Also verifies a new
|
| +// tab is opened by target '_blank'.
|
| +- (void)testBrowsingPreventDefaultWithLinkOpenedByJavascript {
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL URL = web::test::HttpServer::MakeUrl(
|
| + "http://preventDefaultWithLinkOpenedByJavascript");
|
| + const GURL anchorURL =
|
| + web::test::HttpServer::MakeUrl("http://anchorDestination");
|
| + const GURL destinationURL =
|
| + web::test::HttpServer::MakeUrl("http://javaScriptDestination");
|
| + // This is a page with a link where the href and JavaScript are setting the
|
| + // destination to two different URLs so the test can verify which one the
|
| + // browser uses.
|
| + responses[URL] = base::StringPrintf(
|
| + "<a id='link' href='%s' target='_blank' "
|
| + "onclick='window.location.href=\"%s\"; "
|
| + "event.stopPropagation()' id='link'>link</a>",
|
| + anchorURL.spec().c_str(), destinationURL.spec().c_str());
|
| + responses[anchorURL] = "anchor destination";
|
| +
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_ALLOW);
|
| +
|
| + [ChromeEarlGrey loadURL:URL];
|
| + chrome_test_util::AssertMainTabCount(1);
|
| +
|
| + chrome_test_util::TapWebViewElementWithId("link");
|
| +
|
| + chrome_test_util::AssertMainTabCount(2);
|
| +
|
| + // Verify the new tab was opened with the expected URL.
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(anchorURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests tapping a link that navigates to a page that immediately navigates
|
| +// again via document.location.href.
|
| +- (void)testBrowsingWindowDataLinkScriptRedirect {
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL URL =
|
| + web::test::HttpServer::MakeUrl("http://windowDataLinkScriptRedirect");
|
| + const GURL intermediateURL =
|
| + web::test::HttpServer::MakeUrl("http://intermediate");
|
| + const GURL destinationURL =
|
| + web::test::HttpServer::MakeUrl("http://destination");
|
| + // This is a page with a link to the intermediate page.
|
| + responses[URL] =
|
| + base::StringPrintf("<a id='link' href='%s' target='_blank'>link</a>",
|
| + intermediateURL.spec().c_str());
|
| + // This intermediate page uses JavaScript to immediately navigate to the
|
| + // destination page.
|
| + responses[intermediateURL] =
|
| + base::StringPrintf("<script>document.location.href=\"%s\"</script>",
|
| + destinationURL.spec().c_str());
|
| + // This is the page that should be showing at the end of the test.
|
| + responses[destinationURL] = "You've arrived!";
|
| +
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_ALLOW);
|
| +
|
| + [ChromeEarlGrey loadURL:URL];
|
| + chrome_test_util::AssertMainTabCount(1);
|
| +
|
| + chrome_test_util::TapWebViewElementWithId("link");
|
| +
|
| + chrome_test_util::AssertMainTabCount(2);
|
| +
|
| + // Verify the new tab was opened with the expected URL.
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(destinationURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests that pressing the button on a POST-based form changes the page and that
|
| +// the back button works as expected afterwards.
|
| +- (void)testBrowsingPostEntryWithButton {
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL URL = web::test::HttpServer::MakeUrl("http://postEntryWithButton");
|
| + const GURL destinationURL = web::test::HttpServer::MakeUrl("http://foo");
|
| + // This is a page with a button that posts to the destination.
|
| + responses[URL] = base::StringPrintf(
|
| + "<form action='%s' method='post'>"
|
| + "<input value='button' type='submit' id='button'></form>",
|
| + destinationURL.spec().c_str());
|
| + // This is the page that should be showing at the end of the test.
|
| + responses[destinationURL] = "bar!";
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + [ChromeEarlGrey loadURL:URL];
|
| + chrome_test_util::TapWebViewElementWithId("button");
|
| +
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(destinationURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + // Go back and verify the browser navigates to the original URL.
|
| + [self goBack];
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(URL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests that a link with a JavaScript-based navigation changes the page and
|
| +// that the back button works as expected afterwards.
|
| +- (void)testBrowsingJavaScriptBasedNavigation {
|
| + std::map<GURL, std::string> responses;
|
| + const GURL URL = web::test::HttpServer::MakeUrl("http://origin");
|
| + const GURL destURL = web::test::HttpServer::MakeUrl("http://destination");
|
| + // Page containing a link with onclick attribute that sets window.location
|
| + // to the destination URL.
|
| + responses[URL] = base::StringPrintf(
|
| + "<a href='#' onclick=\"window.location='%s';\" id='link'>Link</a>",
|
| + destURL.spec().c_str());
|
| + // Page with some text.
|
| + responses[destURL] = "You've arrived!";
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + [ChromeEarlGrey loadURL:URL];
|
| + chrome_test_util::TapWebViewElementWithId("link");
|
| +
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(destURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + [self goBack];
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(URL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// TODO(crbug.com/638674): Evaluate if this can move to shared code
|
| +// Navigates back to the previous webpage.
|
| +- (void)goBack {
|
| + base::scoped_nsobject<GenericChromeCommand> backCommand(
|
| + [[GenericChromeCommand alloc] initWithTag:IDC_BACK]);
|
| + chrome_test_util::RunCommandWithActiveViewController(backCommand);
|
| +
|
| + [ChromeEarlGrey waitForPageToFinishLoading];
|
| +}
|
| +
|
| +// Navigates forward to a previous webpage.
|
| +// TODO(crbug.com/638674): Evaluate if this can move to shared code
|
| +- (void)goForward {
|
| + base::scoped_nsobject<GenericChromeCommand> forwardCommand(
|
| + [[GenericChromeCommand alloc] initWithTag:IDC_FORWARD]);
|
| + chrome_test_util::RunCommandWithActiveViewController(forwardCommand);
|
| +
|
| + [ChromeEarlGrey waitForPageToFinishLoading];
|
| +}
|
| +
|
| +// Tests that a link with WebUI URL does not trigger a load. WebUI pages may
|
| +// have increased power and using the same web process (which may potentially
|
| +// be controlled by an attacker) is dangerous.
|
| +- (void)testTapLinkWithWebUIURL {
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL URL(web::test::HttpServer::MakeUrl("http://pageWithWebUILink"));
|
| + const char kPageHTML[] =
|
| + "<script>"
|
| + " function printMsg() {"
|
| + " document.body.appendChild(document.createTextNode('Hello world!'));"
|
| + " }"
|
| + "</script>"
|
| + "<a href='chrome://version' id='link' onclick='printMsg()'>Version</a>";
|
| + responses[URL] = kPageHTML;
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + // Assert that test is starting with one tab.
|
| + chrome_test_util::AssertMainTabCount(1U);
|
| + chrome_test_util::AssertIncognitoTabCount(0U);
|
| +
|
| + [ChromeEarlGrey loadURL:URL];
|
| +
|
| + // Tap on chrome://version link.
|
| + [ChromeEarlGrey tapWebViewElementWithID:@"link"];
|
| +
|
| + // Verify that page did not change by checking its URL and message printed by
|
| + // onclick event.
|
| + [[EarlGrey selectElementWithMatcher:omniboxText("chrome://version")]
|
| + assertWithMatcher:grey_nil()];
|
| + [[EarlGrey selectElementWithMatcher:webViewContainingText("Hello world!")]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + // Verify that no new tabs were open which could load chrome://version.
|
| + chrome_test_util::AssertMainTabCount(1U);
|
| +}
|
| +
|
| +// Tests that pressing the button on a POST-based form with same-page action
|
| +// does not change the page and that the back button works as expected
|
| +// afterwards.
|
| +- (void)testBrowsingPostToSamePage {
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL firstURL = web::test::HttpServer::MakeUrl("http://first");
|
| + const GURL formURL = web::test::HttpServer::MakeUrl("http://form");
|
| + // This is just a page with some text.
|
| + responses[firstURL] = "foo";
|
| + // This is a page with at button that posts to the current URL.
|
| + responses[formURL] =
|
| + "<form method='post'>"
|
| + "<input value='button' type='submit' id='button'></form>";
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + // Open the first URL so it's in history.
|
| + [ChromeEarlGrey loadURL:firstURL];
|
| +
|
| + // Open the second URL, tap the button, and verify the browser navigates to
|
| + // the expected URL.
|
| + [ChromeEarlGrey loadURL:formURL];
|
| + chrome_test_util::TapWebViewElementWithId("button");
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(formURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + // Go back once and verify the browser navigates to the form URL.
|
| + [self goBack];
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(formURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + // Go back a second time and verify the browser navigates to the first URL.
|
| + [self goBack];
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(firstURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests that evaluating user JavaScript that causes navigation correctly
|
| +// modifies history.
|
| +- (void)testBrowsingUserJavaScriptNavigation {
|
| + // TODO(crbug.com/640220): Keyboard entry inside the omnibox fails only on
|
| + // iPad running iOS 10.
|
| + if (IsIPadIdiom() && base::ios::IsRunningOnIOS10OrLater())
|
| + return;
|
| +
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL startURL = web::test::HttpServer::MakeUrl("http://startpage");
|
| + responses[startURL] = "<html><body><p>Ready to begin.</p></body></html>";
|
| + const GURL targetURL = web::test::HttpServer::MakeUrl("http://targetpage");
|
| + responses[targetURL] = "<html><body><p>You've arrived!</p></body></html>";
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + // Load the first page and run JS (using the codepath that user-entered JS in
|
| + // the omnibox would take, not page-triggered) that should navigate.
|
| + [ChromeEarlGrey loadURL:startURL];
|
| +
|
| + NSString* script =
|
| + [NSString stringWithFormat:@"javascript:window.location='%s'",
|
| + targetURL.spec().c_str()];
|
| + [[EarlGrey selectElementWithMatcher:chrome_test_util::omnibox()]
|
| + performAction:grey_typeText(script)];
|
| + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Go")]
|
| + performAction:grey_tap()];
|
| + [ChromeEarlGrey waitForPageToFinishLoading];
|
| +
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(targetURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + [self goBack];
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(startURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests that evaluating non-navigation user JavaScript doesn't affect history.
|
| +- (void)testBrowsingUserJavaScriptWithoutNavigation {
|
| + // TODO(crbug.com/640220): Keyboard entry inside the omnibox fails only on
|
| + // iPad running iOS 10.
|
| + if (IsIPadIdiom() && base::ios::IsRunningOnIOS10OrLater())
|
| + return;
|
| +
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL firstURL = web::test::HttpServer::MakeUrl("http://firstURL");
|
| + const std::string firstResponse = "Test Page 1";
|
| + const GURL secondURL = web::test::HttpServer::MakeUrl("http://secondURL");
|
| + const std::string secondResponse = "Test Page 2";
|
| + responses[firstURL] = firstResponse;
|
| + responses[secondURL] = secondResponse;
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + [ChromeEarlGrey loadURL:firstURL];
|
| + [ChromeEarlGrey loadURL:secondURL];
|
| +
|
| + // Execute some JavaScript in the omnibox.
|
| + [[EarlGrey selectElementWithMatcher:chrome_test_util::omnibox()]
|
| + performAction:grey_typeText(@"javascript:document.write('foo')")];
|
| + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Go")]
|
| + performAction:grey_tap()];
|
| +
|
| + id<GREYMatcher> webView = chrome_test_util::webViewContainingText("foo");
|
| + [[EarlGrey selectElementWithMatcher:webView] assertWithMatcher:grey_notNil()];
|
| +
|
| + // Verify that the JavaScript did not affect history by going back and then
|
| + // forward again.
|
| + [self goBack];
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(firstURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| + [self goForward];
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(secondURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +// Tests that submitting a POST-based form by tapping the 'Go' button on the
|
| +// keyboard navigates to the correct URL and the back button works as expected
|
| +// afterwards.
|
| +// TODO(crbug.com/670380): Enable this test on device.
|
| +#if TARGET_IPHONE_SIMULATOR
|
| +#define MAYBE_testBrowsingPostEntryWithKeyboard \
|
| + testBrowsingPostEntryWithKeyboard
|
| +#else
|
| +#define MAYBE_testBrowsingPostEntryWithKeyboard \
|
| + FLAKY_testBrowsingPostEntryWithKeyboard
|
| +#endif
|
| +- (void)MAYBE_testBrowsingPostEntryWithKeyboard {
|
| + // Create map of canned responses and set up the test HTML server.
|
| + std::map<GURL, std::string> responses;
|
| + const GURL URL =
|
| + web::test::HttpServer::MakeUrl("http://postEntryWithKeyboard");
|
| + const GURL destinationURL = web::test::HttpServer::MakeUrl("http://foo");
|
| + // This is a page this an input text field and a button that posts to the
|
| + // destination.
|
| + responses[URL] = base::StringPrintf(
|
| + "hello!"
|
| + "<form action='%s' method='post'>"
|
| + "<input value='textfield' id='textfield' type='text'></label>"
|
| + "<input type='submit'></form>",
|
| + destinationURL.spec().c_str());
|
| + // This is the page that should be showing at the end of the test.
|
| + responses[destinationURL] = "baz!";
|
| + web::test::SetUpSimpleHttpServer(responses);
|
| +
|
| + // Open the URL, focus the textfield,and submit via keyboard.
|
| + [ChromeEarlGrey loadURL:URL];
|
| + [[EarlGrey selectElementWithMatcher:webViewContainingText("hello!")]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + web::WebState* currentWebState = chrome_test_util::GetCurrentWebState();
|
| + [[EarlGrey selectElementWithMatcher:web::webViewInWebState(currentWebState)]
|
| + performAction:web::webViewTapElement(currentWebState, "textfield")];
|
| +
|
| + // Disable EarlGrey's synchronization since it is blocked by opening the
|
| + // keyboard from a web view.
|
| + [[GREYConfiguration sharedInstance]
|
| + setValue:@NO
|
| + forConfigKey:kGREYConfigKeySynchronizationEnabled];
|
| +
|
| + // Wait until the keyboard shows up before tapping.
|
| + GREYCondition* condition = [GREYCondition
|
| + conditionWithName:@"Wait for the keyboard to show up."
|
| + block:^BOOL {
|
| + NSError* error = nil;
|
| + [[EarlGrey
|
| + selectElementWithMatcher:grey_accessibilityID(@"Go")]
|
| + assertWithMatcher:grey_notNil()
|
| + error:&error];
|
| + return (error == nil);
|
| + }];
|
| + GREYAssert([condition waitWithTimeout:10],
|
| + @"No keyboard with 'Go' button showed up.");
|
| +
|
| + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Go")]
|
| + performAction:grey_tap()];
|
| +
|
| + // Reenable synchronization now that the keyboard has been closed.
|
| + [[GREYConfiguration sharedInstance]
|
| + setValue:@YES
|
| + forConfigKey:kGREYConfigKeySynchronizationEnabled];
|
| +
|
| + // Verify that the browser navigates to the expected URL.
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(destinationURL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +
|
| + // Go back and verify that the browser navigates to the original URL.
|
| + [self goBack];
|
| + [[EarlGrey selectElementWithMatcher:omniboxText(URL.GetContent())]
|
| + assertWithMatcher:grey_notNil()];
|
| +}
|
| +
|
| +@end
|
|
|