blob: 738ceb3e147cd22933664ec705cc2773a2fa2dd0 [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 <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#include "base/strings/sys_string_conversions.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"
#import "ios/chrome/test/app/settings_test_util.h"
#import "ios/chrome/test/app/tab_test_util.h"
#include "ios/chrome/test/app/web_view_interaction_test_util.h"
#import "ios/chrome/test/earl_grey/chrome_actions.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_matchers.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#include "ios/chrome/test/earl_grey/chrome_util.h"
#import "ios/testing/wait_util.h"
#import "ios/web/public/test/earl_grey/web_view_matchers.h"
#import "ios/web/public/test/http_server.h"
#import "ios/web/public/test/http_server_util.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using chrome_test_util::ButtonWithAccessibilityLabelId;
namespace {
const char kUrlChromiumLogoPage[] =
"http://ios/testing/data/http_server_files/chromium_logo_page.html";
const char kUrlChromiumLogoImg[] =
"http://ios/testing/data/http_server_files/chromium_logo.png";
const char kUrlInitialPage[] = "http://scenarioContextMenuOpenInNewTab";
const char kUrlDestinationPage[] = "http://destination";
const char kChromiumImageID[] = "chromium_image";
const char kDestinationLinkID[] = "link";
// HTML content of the destination page that sets the page title.
const char kDestinationHtml[] =
"<script>document.title='new doc'</script>You made it!";
// Matcher for the open image button in the context menu.
id<GREYMatcher> OpenImageButton() {
return ButtonWithAccessibilityLabelId(IDS_IOS_CONTENT_CONTEXT_OPENIMAGE);
}
// Matcher for the open image in new tab button in the context menu.
id<GREYMatcher> OpenImageInNewTabButton() {
return ButtonWithAccessibilityLabelId(
IDS_IOS_CONTENT_CONTEXT_OPENIMAGENEWTAB);
}
// Matcher for the open link in new tab button in the context menu.
// TODO(crbug.com/638674): Clean up code duplication.
id<GREYMatcher> OpenLinkInNewTabButton() {
return ButtonWithAccessibilityLabelId(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB);
}
// Waits for the context menu item to disappear. TODO(crbug.com/682871): Remove
// this once EarlGrey is synchronized with context menu.
void WaitForContextMenuItemDisappeared(id<GREYMatcher> contextMenuItemButton) {
ConditionBlock condition = ^{
NSError* error = nil;
[[EarlGrey selectElementWithMatcher:contextMenuItemButton]
assertWithMatcher:grey_nil()
error:&error];
return error == nil;
};
GREYAssert(testing::WaitUntilConditionOrTimeout(
testing::kWaitForUIElementTimeout, condition),
@"Waiting for matcher %@ failed.", contextMenuItemButton);
}
// Long press on |elementId| to trigger context menu and then tap on
// |contextMenuItemButton| item.
void LongPressElementAndTapOnButton(const char* elementId,
id<GREYMatcher> contextMenuItemButton) {
id<GREYMatcher> webViewMatcher =
web::WebViewInWebState(chrome_test_util::GetCurrentWebState());
[[EarlGrey selectElementWithMatcher:webViewMatcher]
performAction:chrome_test_util::longPressElementForContextMenu(elementId,
true)];
[[EarlGrey selectElementWithMatcher:contextMenuItemButton]
assertWithMatcher:grey_notNil()];
[[EarlGrey selectElementWithMatcher:contextMenuItemButton]
performAction:grey_tap()];
WaitForContextMenuItemDisappeared(contextMenuItemButton);
}
// A simple wrapper that sleeps for 1s to wait for the animation, triggered from
// opening a new tab through context menu, to finish before selecting tab.
// TODO(crbug.com/643792): Remove this function when the bug is fixed.
void SelectTabAtIndexInCurrentMode(NSUInteger index) {
// Delay for 1 second.
GREYCondition* myCondition = [GREYCondition conditionWithName:@"delay"
block:^BOOL {
return NO;
}];
[myCondition waitWithTimeout:1U];
chrome_test_util::SelectTabAtIndexInCurrentMode(index);
}
} // namespace
// Context menu tests for Chrome.
@interface ContextMenuTestCase : ChromeTestCase
@end
@implementation ContextMenuTestCase
+ (void)setUp {
[super setUp];
chrome_test_util::SetContentSettingsBlockPopups(CONTENT_SETTING_ALLOW);
}
+ (void)tearDown {
chrome_test_util::SetContentSettingsBlockPopups(CONTENT_SETTING_DEFAULT);
[super tearDown];
}
// Tests that selecting "Open Image" from the context menu properly opens the
// image in the current tab.
- (void)testOpenImageInCurrentTabFromContextMenu {
GURL pageURL = web::test::HttpServer::MakeUrl(kUrlChromiumLogoPage);
GURL imageURL = web::test::HttpServer::MakeUrl(kUrlChromiumLogoImg);
web::test::SetUpFileBasedHttpServer();
[ChromeEarlGrey loadURL:pageURL];
chrome_test_util::AssertMainTabCount(1U);
LongPressElementAndTapOnButton(kChromiumImageID, OpenImageButton());
// Verify url and tab count.
[[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
imageURL.GetContent())]
assertWithMatcher:grey_notNil()];
chrome_test_util::AssertMainTabCount(1U);
}
// Tests that selecting "Open Image in New Tab" from the context menu properly
// opens the image in a new background tab.
- (void)testOpenImageInNewTabFromContextMenu {
GURL pageURL = web::test::HttpServer::MakeUrl(kUrlChromiumLogoPage);
GURL imageURL = web::test::HttpServer::MakeUrl(kUrlChromiumLogoImg);
web::test::SetUpFileBasedHttpServer();
[ChromeEarlGrey loadURL:pageURL];
chrome_test_util::AssertMainTabCount(1U);
LongPressElementAndTapOnButton(kChromiumImageID, OpenImageInNewTabButton());
SelectTabAtIndexInCurrentMode(1U);
// Verify url and tab count.
[[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
imageURL.GetContent())]
assertWithMatcher:grey_notNil()];
chrome_test_util::AssertMainTabCount(2U);
}
// Tests "Open in New Tab" on context menu.
- (void)testContextMenuOpenInNewTab {
// Set up test simple http server.
std::map<GURL, std::string> responses;
GURL initialURL = web::test::HttpServer::MakeUrl(kUrlInitialPage);
GURL destinationURL = web::test::HttpServer::MakeUrl(kUrlDestinationPage);
// The initial page contains a link to the destination page.
responses[initialURL] = "<a style='margin-left:50px' href='" +
destinationURL.spec() + "' id='link'>link</a>";
responses[destinationURL] = kDestinationHtml;
web::test::SetUpSimpleHttpServer(responses);
[ChromeEarlGrey loadURL:initialURL];
chrome_test_util::AssertMainTabCount(1U);
LongPressElementAndTapOnButton(kDestinationLinkID, OpenLinkInNewTabButton());
SelectTabAtIndexInCurrentMode(1U);
// Verify url and tab count.
[[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
destinationURL.GetContent())]
assertWithMatcher:grey_notNil()];
chrome_test_util::AssertMainTabCount(2U);
}
// Tests "Open in New Tab" on context menu on a link that requires scrolling
// on the page to verify that context menu can be properly triggered in the
// current screen view.
- (void)testContextMenuOpenInNewTabFromTallPage {
// Set up test simple http server.
std::map<GURL, std::string> responses;
GURL initialURL =
web::test::HttpServer::MakeUrl("http://scenarioContextMenuOpenInNewTab");
GURL destinationURL = web::test::HttpServer::MakeUrl("http://destination");
// The initial page contains a link to the destination page that is below a
// really tall div so that scrolling is required.
responses[initialURL] =
"<div style='height:4000px'></div>"
"<a style='margin-left:50px' href='" +
destinationURL.spec() + "' id='link'>link</a>";
responses[destinationURL] = kDestinationHtml;
web::test::SetUpSimpleHttpServer(responses);
[ChromeEarlGrey loadURL:initialURL];
chrome_test_util::AssertMainTabCount(1U);
// Scroll down on the web view to make the link visible.
[[EarlGrey
selectElementWithMatcher:WebViewScrollView(
chrome_test_util::GetCurrentWebState())]
performAction:grey_swipeFastInDirection(kGREYDirectionUp)];
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewContainingText(
kDestinationLinkID)]
assertWithMatcher:grey_notNil()];
LongPressElementAndTapOnButton(kDestinationLinkID, OpenLinkInNewTabButton());
// Earl Grey cannot preperly synchronize some animations, so adding a
// WaitUntilCondition to wait for the new tab opening animation to finish
// and the scroll view to become interactable.
ConditionBlock condition = ^{
NSError* error = nil;
[[EarlGrey
selectElementWithMatcher:WebViewScrollView(
chrome_test_util::GetCurrentWebState())]
assertWithMatcher:grey_interactable()
error:&error];
return !error;
};
GREYAssert(testing::WaitUntilConditionOrTimeout(
testing::kWaitForUIElementTimeout, condition),
@"Web view did not become interactable");
// Make the toolbar visible by scrolling up on the web view to select the
// newly opened tab.
[[EarlGrey
selectElementWithMatcher:WebViewScrollView(
chrome_test_util::GetCurrentWebState())]
performAction:grey_swipeFastInDirection(kGREYDirectionDown)];
chrome_test_util::AssertToolbarVisible();
SelectTabAtIndexInCurrentMode(1U);
// Verify url and tab count.
[[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
destinationURL.GetContent())]
assertWithMatcher:grey_notNil()];
chrome_test_util::AssertMainTabCount(2U);
}
@end