Chromium Code Reviews| Index: ios/chrome/browser/web/forms_egtest.mm |
| diff --git a/ios/chrome/browser/web/forms_egtest.mm b/ios/chrome/browser/web/forms_egtest.mm |
| index 4c712c51431e2066a23b9ab5d719259ec10cf3f5..7cbaebc8e5d7e6f72a0b06692c5c0e9a4a2f45f5 100644 |
| --- a/ios/chrome/browser/web/forms_egtest.mm |
| +++ b/ios/chrome/browser/web/forms_egtest.mm |
| @@ -17,6 +17,8 @@ |
| #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/earl_grey/web_view_actions.h" |
| +#import "ios/web/public/test/earl_grey/web_view_matchers.h" |
| #include "ios/web/public/test/http_server/data_response_provider.h" |
| #import "ios/web/public/test/http_server/http_server.h" |
| #include "ios/web/public/test/http_server/http_server_util.h" |
| @@ -55,12 +57,17 @@ const GURL GetFormUrl() { |
| return web::test::HttpServer::MakeUrl("http://form"); |
| } |
| +// GURL of a page with a form that posts data to |GetDestinationUrl|. |
| +const GURL GetFormPostOnSamePageUrl() { |
| + return web::test::HttpServer::MakeUrl("http://form"); |
| +} |
| + |
| // GURL of the page to which the |GetFormUrl| posts data to. |
| const GURL GetDestinationUrl() { |
| return web::test::HttpServer::MakeUrl("http://destination"); |
| } |
| -#pragma mark - TestFormRedirectResponseProvider |
| +#pragma mark - TestFormResponseProvider |
| // URL that redirects to |GetDestinationUrl| with a 302. |
| const GURL GetRedirectUrl() { |
| @@ -72,8 +79,8 @@ const GURL GetRedirectFormUrl() { |
| return web::test::HttpServer::MakeUrl("http://formRedirect"); |
| } |
| -// A ResponseProvider that provides html response or a redirect. |
| -class TestFormRedirectResponseProvider : public web::DataResponseProvider { |
| +// A ResponseProvider that provides html response, post response or a redirect. |
| +class TestFormResponseProvider : public web::DataResponseProvider { |
| public: |
| // TestResponseProvider implementation. |
| bool CanHandleRequest(const Request& request) override; |
| @@ -83,14 +90,14 @@ class TestFormRedirectResponseProvider : public web::DataResponseProvider { |
| std::string* response_body) override; |
| }; |
| -bool TestFormRedirectResponseProvider::CanHandleRequest( |
| - const Request& request) { |
| +bool TestFormResponseProvider::CanHandleRequest(const Request& request) { |
| const GURL& url = request.url; |
| return url == GetDestinationUrl() || url == GetRedirectUrl() || |
| - url == GetRedirectFormUrl(); |
| + url == GetRedirectFormUrl() || url == GetFormPostOnSamePageUrl() || |
| + url == GetGenericUrl(); |
| } |
| -void TestFormRedirectResponseProvider::GetResponseHeadersAndBody( |
| +void TestFormResponseProvider::GetResponseHeadersAndBody( |
| const Request& request, |
| scoped_refptr<net::HttpResponseHeaders>* headers, |
| std::string* response_body) { |
| @@ -102,6 +109,21 @@ void TestFormRedirectResponseProvider::GetResponseHeadersAndBody( |
| } |
| *headers = web::ResponseProvider::GetDefaultResponseHeaders(); |
| + if (url == GetGenericUrl()) { |
| + *response_body = "A generic page"; |
| + return; |
| + } |
| + if (url == GetFormPostOnSamePageUrl()) { |
| + if (request.method == "POST") { |
| + *response_body = request.method + std::string(" ") + request.body; |
| + } else { |
| + *response_body = |
| + "<form method='post'>" |
| + "<input value='button' type='submit' id='button'></form>"; |
| + } |
| + return; |
| + } |
| + |
| if (url == GetRedirectFormUrl()) { |
| *response_body = |
| base::StringPrintf(kFormHtmlTemplate, GetRedirectUrl().spec().c_str()); |
| @@ -121,6 +143,11 @@ void TestFormRedirectResponseProvider::GetResponseHeadersAndBody( |
| @implementation FormsTestCase |
| +// Matcher for a Go button that is interactable. |
| +id<GREYMatcher> GoButtonMatcher() { |
| + return grey_allOf(grey_accessibilityID(@"Go"), grey_interactable(), nil); |
| +} |
| + |
| // Waits for view with Tab History accessibility ID. |
| - (void)waitForTabHistoryView { |
| GREYCondition* condition = [GREYCondition |
| @@ -327,8 +354,7 @@ void TestFormRedirectResponseProvider::GetResponseHeadersAndBody( |
| // Tests that a POST followed by a redirect does not show the popup. |
| - (void)testRepostFormCancellingAfterRedirect { |
| - web::test::SetUpHttpServer( |
| - base::MakeUnique<TestFormRedirectResponseProvider>()); |
| + web::test::SetUpHttpServer(base::MakeUnique<TestFormResponseProvider>()); |
| const GURL destinationURL = GetDestinationUrl(); |
| [ChromeEarlGrey loadURL:GetRedirectFormUrl()]; |
| @@ -355,4 +381,117 @@ void TestFormRedirectResponseProvider::GetResponseHeadersAndBody( |
| assertWithMatcher:grey_notNil()]; |
| } |
| +// Tests that pressing the button on a POST-based form with same-page action |
| +// does not change the page URL and that the back button works as expected |
| +// afterwards. |
| +- (void)testPostFormToSamePage { |
| +// TODO(crbug.com/714303): Re-enable this test on devices. |
| +#if !TARGET_IPHONE_SIMULATOR |
| + EARL_GREY_TEST_DISABLED(@"Test disabled on device."); |
| +#endif |
| + |
| + web::test::SetUpHttpServer(base::MakeUnique<TestFormResponseProvider>()); |
| + // Open the first URL so it's in history. |
| + [ChromeEarlGrey loadURL:GetGenericUrl()]; |
| + |
| + // Open the second URL, tap the button, and verify the browser navigates to |
| + // the expected URL. |
| + [ChromeEarlGrey loadURL:GetFormPostOnSamePageUrl()]; |
| + chrome_test_util::TapWebViewElementWithId("button"); |
| + [ChromeEarlGrey waitForWebViewContainingText:"POST"]; |
| + [[EarlGrey |
| + selectElementWithMatcher:OmniboxText( |
| + GetFormPostOnSamePageUrl().GetContent())] |
|
Eugene But (OOO till 7-30)
2017/06/24 01:32:20
nit: Do you want to use a local variable for this
|
| + assertWithMatcher:grey_notNil()]; |
| + |
| + // Go back once and verify the browser navigates to the form URL. |
| + [ChromeEarlGrey goBack]; |
| + [[EarlGrey |
| + selectElementWithMatcher:OmniboxText( |
| + GetFormPostOnSamePageUrl().GetContent())] |
| + assertWithMatcher:grey_notNil()]; |
| + |
| + // Go back a second time and verify the browser navigates to the first URL. |
| + [ChromeEarlGrey goBack]; |
| + [[EarlGrey selectElementWithMatcher:OmniboxText(GetGenericUrl().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. |
| +- (void)testPostFormEntryWithKeyboard { |
| +// TODO(crbug.com/704618): Re-enable this test on devices. |
| +#if !TARGET_IPHONE_SIMULATOR |
| + EARL_GREY_TEST_DISABLED(@"Test disabled on device."); |
| +#endif |
| + |
| + [self setUpFormTestSimpleHttpServer]; |
| + const GURL destinationURL = GetDestinationUrl(); |
| + |
| + [ChromeEarlGrey loadURL:GetFormUrl()]; |
| + [self submitFormUsingKeyboardGoButtonWithInputID:"textfield"]; |
| + |
| + // Verify that the browser navigates to the expected URL. |
| + [ChromeEarlGrey waitForWebViewContainingText:"bar!"]; |
| + [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())] |
| + assertWithMatcher:grey_notNil()]; |
| + |
| + // Go back and verify that the browser navigates to the original URL. |
| + [ChromeEarlGrey goBack]; |
| + [[EarlGrey selectElementWithMatcher:OmniboxText(GetFormUrl().GetContent())] |
| + assertWithMatcher:grey_notNil()]; |
| +} |
| + |
| +// Tap the text field indicated by |ID| to open the keyboard, and then |
| +// press the keyboard's "Go" button to submit the form. |
| +- (void)submitFormUsingKeyboardGoButtonWithInputID:(const std::string&)ID { |
| + // Disable EarlGrey's synchronization since it is blocked by opening the |
| + // keyboard from a web view. |
| + [[GREYConfiguration sharedInstance] |
| + setValue:@NO |
| + forConfigKey:kGREYConfigKeySynchronizationEnabled]; |
| + |
| + // Wait for web view to be interactable before tapping. |
| + GREYCondition* interactableCondition = [GREYCondition |
| + conditionWithName:@"Wait for web view to be interactable." |
| + block:^BOOL { |
| + NSError* error = nil; |
| + id<GREYMatcher> webViewMatcher = WebViewInWebState( |
| + chrome_test_util::GetCurrentWebState()); |
| + [[EarlGrey selectElementWithMatcher:webViewMatcher] |
| + assertWithMatcher:grey_interactable() |
| + error:&error]; |
| + return !error; |
| + }]; |
| + GREYAssert( |
| + [interactableCondition waitWithTimeout:testing::kWaitForUIElementTimeout], |
| + @"Web view did not become interactable."); |
| + |
| + web::WebState* currentWebState = chrome_test_util::GetCurrentWebState(); |
| + [[EarlGrey selectElementWithMatcher:web::WebViewInWebState(currentWebState)] |
| + performAction:web::WebViewTapElement(currentWebState, ID)]; |
| + |
| + // 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:GoButtonMatcher()] |
| + assertWithMatcher:grey_notNil() |
| + error:&error]; |
| + return (error == nil); |
| + }]; |
| + GREYAssert([condition waitWithTimeout:10], |
|
Eugene But (OOO till 7-30)
2017/06/24 01:32:20
Do we need a constant for this timeout?
|
| + @"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]; |
| +} |
| + |
| @end |