Commit bed477c5 authored by Sebastien Lalancette's avatar Sebastien Lalancette Committed by Commit Bot

[SH-iOS][iOS] Link-To-Text EarlGrey Test

Runs only on iOS 13+, and will:
- Select a word on a test page,
- Tap on "Link to Text",
- Tap on the "Copy" activity,
- Assert that the expected URL was added to the pasteboard.

Test is skipped on iOS 12 due to the activity view not being accessible
by EarlGrey.

Test is disabled on iPads due to:
Bug: 1149603

Change-Id: Ia1011f538e6d2b6aed00a12cccd19df40da13472
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2530389
Commit-Queue: Sebastien Lalancette <seblalancette@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Reviewed-by: default avatarsebsg <sebsg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#828195}
parent d9d3a1d2
......@@ -49,12 +49,15 @@ source_set("eg2_tests") {
deps = [
"//base",
"//base/test:test_support",
"//components/shared_highlighting/core/common",
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/test/earl_grey:eg_test_support+eg2",
"//ios/testing/earl_grey:eg_test_support+eg2",
"//ios/third_party/earl_grey2:test_lib",
"//ios/web/common:features",
"//ios/web/public/navigation:navigation",
"//ios/web/public/test:element_selector",
"//ios/web/public/test/http_server",
"//net",
"//net:test_support",
......
......@@ -2,8 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <vector>
#import "base/ios/ios_util.h"
#import "base/strings/string_util.h"
#import "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#import "components/shared_highlighting/core/common/text_fragment.h"
#import "components/shared_highlighting/core/common/text_fragments_utils.h"
#import "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/chrome/test/earl_grey/chrome_actions.h"
#import "ios/chrome/test/earl_grey/chrome_actions_app_interface.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h"
......@@ -12,6 +20,8 @@
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#import "ios/web/common/features.h"
#import "ios/web/public/test/element_selector.h"
#import "net/base/mac/url_conversions.h"
#import "net/test/embedded_test_server/default_handlers.h"
#import "net/test/embedded_test_server/http_request.h"
#import "net/test/embedded_test_server/http_response.h"
......@@ -21,11 +31,15 @@
#error "This file requires ARC support."
#endif
using shared_highlighting::TextFragment;
namespace {
const char kFirstFragmentText[] = "Hello foo!";
const char kSecondFragmentText[] = "bar";
const char kTestPageTextSample[] = "Lorem ipsum";
const char kSimpleTextElementId[] = "toBeSelected";
const char kToBeSelectedText[] = "VeryUniqueWord";
const char kTestURL[] = "/testPage";
const char kURLWithTwoFragments[] = "/testPage/#:~:text=Hello%20foo!&text=bar";
......@@ -37,6 +51,7 @@ const char kHTMLOfTestPage[] =
"minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip "
"ex ea "
"commodo consequat. bar</p>"
"<p id=\"toBeSelected\">VeryUniqueWord</p>"
"</body></html>";
const char kTestLongPageURL[] = "/longTestPage";
......@@ -106,6 +121,7 @@ std::unique_ptr<net::test_server::HttpResponse> LoadHtml(
- (AppLaunchConfiguration)appConfigurationForTestCase {
AppLaunchConfiguration config;
config.features_enabled.push_back(web::features::kScrollToTextIOS);
config.features_enabled.push_back(kSharedHighlightingIOS);
return config;
}
......@@ -123,14 +139,10 @@ std::unique_ptr<net::test_server::HttpResponse> LoadHtml(
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
}
- (void)loadURLPath:(const char*)path {
[ChromeEarlGrey loadURL:self.testServer->GetURL(path)];
}
// Tests that navigating to a URL with text fragments will highlight all
// fragments.
- (void)testHighlightAllFragments {
[self loadURLPath:kURLWithTwoFragments];
[ChromeEarlGrey loadURL:self.testServer->GetURL(kURLWithTwoFragments)];
[ChromeEarlGrey waitForWebStateContainingText:kTestPageTextSample];
NSArray<NSString*>* markedText = GetMarkedText();
......@@ -145,7 +157,7 @@ std::unique_ptr<net::test_server::HttpResponse> LoadHtml(
// Tests that a fragment will be scrolled to if it's lower on the page.
- (void)testScrollToHighlight {
[self loadURLPath:kLongPageURLWithOneFragment];
[ChromeEarlGrey loadURL:self.testServer->GetURL(kLongPageURLWithOneFragment)];
[ChromeEarlGrey waitForWebStateContainingText:kTestPageTextSample];
__block NSString* firstVisibleMark;
......@@ -169,4 +181,74 @@ std::unique_ptr<net::test_server::HttpResponse> LoadHtml(
@"Visible marked text is not valid.");
}
// Tests that a link can be generated for a simple text selection.
- (void)testGenerateLinkForSimpleText {
if (!base::ios::IsRunningOnIOS13OrLater()) {
// Skip test on iOS 12 as the Activity View on that version is not
// accessible by Earl Grey.
EARL_GREY_TEST_SKIPPED(@"Test skipped on iOS 12.");
}
// TODO(crbug.com/1149603): Re-enable this test on iPad once presenting
// popovers work.
if ([ChromeEarlGrey isIPadIdiom]) {
EARL_GREY_TEST_DISABLED(@"Test is disabled on iPad.");
}
if (@available(iOS 13, *)) {
GURL pageURL = self.testServer->GetURL(kTestURL);
[ChromeEarlGrey loadURL:pageURL];
[ChromeEarlGrey waitForWebStateContainingText:kTestPageTextSample];
[ChromeTestCase removeAnyOpenMenusAndInfoBars];
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:chrome_test_util::LongPressElementForContextMenu(
[ElementSelector
selectorWithElementID:kSimpleTextElementId],
true)];
// Edit menu should be there.
id<GREYMatcher> linkToTextButton =
chrome_test_util::SystemSelectionCalloutLinkToTextButton();
[ChromeEarlGrey
waitForSufficientlyVisibleElementWithMatcher:linkToTextButton];
[[EarlGrey selectElementWithMatcher:linkToTextButton]
performAction:grey_tap()];
// Make sure the Edit menu is gone.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::SystemSelectionCallout()]
assertWithMatcher:grey_notVisible()];
// Wait for the Activity View to show up (look for the Copy action).
id<GREYMatcher> copyActivityButton = chrome_test_util::CopyActivityButton();
[ChromeEarlGrey
waitForSufficientlyVisibleElementWithMatcher:copyActivityButton];
// Tap on the Copy action.
[[EarlGrey selectElementWithMatcher:copyActivityButton]
performAction:grey_tap()];
// Assert the values stored in the pasteboard. Lower-casing the expected
// GURL as that is what the JS library is doing.
std::vector<TextFragment> fragments{
TextFragment(base::ToLowerASCII(kToBeSelectedText))};
GURL expectedGURL =
shared_highlighting::AppendFragmentDirectives(pageURL, fragments);
// Wait for the value to be in the pasteboard.
GREYCondition* getPasteboardValue = [GREYCondition
conditionWithName:@"Could not get an expected URL from the pasteboard."
block:^{
return expectedGURL == [ChromeEarlGrey pasteboardURL];
}];
GREYAssert([getPasteboardValue
waitWithTimeout:base::test::ios::kWaitForActionTimeout],
@"Could not get expected URL from pasteboard.");
}
}
@end
......@@ -585,6 +585,10 @@ id ExecuteJavaScript(NSString* javascript, NSError* __autoreleasing* out_error);
// Verifies that |text| was copied to the pasteboard.
- (void)verifyStringCopied:(NSString*)text;
// Retrieves the GURL stored in the Pasteboard. Returns an empty GURL if no
// URL is currently in the pasteboard.
- (GURL)pasteboardURL;
#pragma mark - Context Menus Utilities (EG2)
// Taps on the Copy Link context menu action and verifies that the |text| has
......
......@@ -1046,6 +1046,12 @@ GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(ChromeEarlGreyAppInterface)
@"Waiting for '%@' to be copied to pasteboard.", text);
}
- (GURL)pasteboardURL {
NSString* absoluteString = [ChromeEarlGreyAppInterface pasteboardURLSpec];
return absoluteString ? GURL(base::SysNSStringToUTF8(absoluteString))
: GURL::EmptyGURL();
}
#pragma mark - Context Menus Utilities (EG2)
- (void)verifyCopyLinkActionWithText:(NSString*)text
......
......@@ -515,6 +515,10 @@
// perspective.
+ (NSString*)pasteboardString;
// Retrieves the currently stored URL on the pasteboard from the tested app's
// perspective.
+ (NSString*)pasteboardURLSpec;
@end
#endif // IOS_CHROME_TEST_EARL_GREY_CHROME_EARL_GREY_APP_INTERFACE_H_
......@@ -932,4 +932,8 @@ base::test::ScopedFeatureList closeAllTabsScopedFeatureList;
return [UIPasteboard generalPasteboard].string;
}
+ (NSString*)pasteboardURLSpec {
return [UIPasteboard generalPasteboard].URL.absoluteString;
}
@end
......@@ -338,9 +338,17 @@ id<GREYMatcher> RecentTabsMenuButton();
// Returns matcher for the system selection callout.
id<GREYMatcher> SystemSelectionCallout();
// Returns a matcher for the Link to text button in the edit menu.
id<GREYMatcher> SystemSelectionCalloutLinkToTextButton();
// Returns matcher for the copy button on the system selection callout.
id<GREYMatcher> SystemSelectionCalloutCopyButton();
// Matcher for a Copy button, such as the one in the Activity View. This matcher
// is very broad and will look for any button with a matching string.
// Only the iOS 13 Activity View is reachable by EarlGrey.
id<GREYMatcher> CopyActivityButton() API_AVAILABLE(ios(13));
// Matcher for the Copy Link option in the updated context menus when long
// pressing on a link. |use_new_string| determines which string to use.
id<GREYMatcher> CopyLinkButton(BOOL use_new_string);
......
......@@ -429,10 +429,18 @@ id<GREYMatcher> SystemSelectionCallout() {
return [ChromeMatchersAppInterface systemSelectionCallout];
}
id<GREYMatcher> SystemSelectionCalloutLinkToTextButton() {
return [ChromeMatchersAppInterface systemSelectionCalloutLinkToTextButton];
}
id<GREYMatcher> SystemSelectionCalloutCopyButton() {
return [ChromeMatchersAppInterface systemSelectionCalloutCopyButton];
}
id<GREYMatcher> CopyActivityButton() API_AVAILABLE(ios(13)) {
return [ChromeMatchersAppInterface copyActivityButton];
}
id<GREYMatcher> CopyLinkButton(BOOL use_new_string) {
return [ChromeMatchersAppInterface
copyLinkButtonWithUseNewString:use_new_string];
......
......@@ -338,9 +338,16 @@
// Returns matcher for the system selection callout.
+ (id<GREYMatcher>)systemSelectionCallout;
// Returns a matcher for the Link to text button in the edit menu.
+ (id<GREYMatcher>)systemSelectionCalloutLinkToTextButton;
// Returns matcher for the copy button on the system selection callout.
+ (id<GREYMatcher>)systemSelectionCalloutCopyButton;
// Matcher for a Copy button, such as the one in the Activity View. This matcher
// is very broad and will look for any button with a matching string.
+ (id<GREYMatcher>)copyActivityButton API_AVAILABLE(ios(13));
// Matcher for the Copy Link option in the updated context menus when long
// pressing on a link. |useNewString| determines which string to use.
+ (id<GREYMatcher>)copyLinkButtonWithUseNewString:(BOOL)useNewString;
......
......@@ -700,6 +700,21 @@ UIView* SubviewWithAccessibilityIdentifier(NSString* accessibility_id,
[self systemSelectionCallout], nil);
}
+ (id<GREYMatcher>)systemSelectionCalloutLinkToTextButton {
return grey_allOf(grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_SHARE_LINK_TO_TEXT)),
[self systemSelectionCallout], nil);
}
+ (id<GREYMatcher>)copyActivityButton API_AVAILABLE(ios(13)) {
id<GREYMatcher> copyStaticText = [ChromeMatchersAppInterface
staticTextWithAccessibilityLabel:l10n_util::GetNSString(
IDS_IOS_SHARE_MENU_COPY)];
return grey_allOf(
copyStaticText,
grey_ancestor(grey_kindOfClassName(@"UIActivityActionGroupCell")), nil);
}
+ (id<GREYMatcher>)copyLinkButtonWithUseNewString:(BOOL)useNewString {
int stringId = useNewString ? IDS_IOS_COPY_LINK_ACTION_TITLE
: IDS_IOS_CONTENT_CONTEXT_COPY;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment