Skip to content

Commit

Permalink
Replace matcher that waits for blocked or loaded images.
Browse files Browse the repository at this point in the history
Create ChromeEarlGrey method to wait for an image in a web view.

Bug: 757982
Change-Id: Ibfb2945950a9acf8be7ca8866607808bf209ba2d
Reviewed-on: https://chromium-review.googlesource.com/627598
Commit-Queue: Mike Baxley <baxley@chromium.org>
Reviewed-by: Eugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#497759}
  • Loading branch information
Mike Baxley authored and Commit Bot committed Aug 28, 2017
1 parent a40b440 commit d8423f6
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 7 deletions.
8 changes: 8 additions & 0 deletions ios/chrome/test/earl_grey/chrome_earl_grey.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ id ExecuteJavaScript(NSString* javascript,
// Waits for there to be |count| number of incognito tabs. If the condition is
// not met within a timeout, a GREYAssert is induced.
+ (void)waitForIncognitoTabCount:(NSUInteger)count;

// Waits for there to be a web view containing a blocked |image_id|. When
// blocked, the image element will be smaller than the actual image size.
+ (void)waitForWebViewContainingBlockedImageElementWithID:(std::string)imageID;

// Waits for there to be a web view containing loaded image with |image_id|.
// When loaded, the image element will have the same size as actual image.
+ (void)waitForWebViewContainingLoadedImageElementWithID:(std::string)imageID;
@end

#endif // IOS_CHROME_TEST_EARL_GREY_CHROME_EARL_GREY_H_
14 changes: 14 additions & 0 deletions ios/chrome/test/earl_grey/chrome_earl_grey.mm
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,18 @@ + (void)waitForIncognitoTabCount:(NSUInteger)count {
@"Failed waiting for incognito tab count to become %" PRIuNS,
count);
}

+ (void)waitForWebViewContainingBlockedImageElementWithID:(std::string)imageID {
GREYAssert(web::test::WaitForWebViewContainingImage(
imageID, chrome_test_util::GetCurrentWebState(),
web::test::IMAGE_STATE_BLOCKED),
@"Failed waiting for web view blocked image %s", imageID.c_str());
}

+ (void)waitForWebViewContainingLoadedImageElementWithID:(std::string)imageID {
GREYAssert(web::test::WaitForWebViewContainingImage(
imageID, chrome_test_util::GetCurrentWebState(),
web::test::IMAGE_STATE_LOADED),
@"Failed waiting for web view loaded image %s", imageID.c_str());
}
@end
3 changes: 0 additions & 3 deletions ios/chrome/test/earl_grey/chrome_matchers.mm
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

#include "base/mac/foundation_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#import "base/test/ios/wait_util.h"
#include "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h"
Expand All @@ -29,7 +27,6 @@
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#include "ios/chrome/grit/ios_strings.h"
#import "ios/chrome/test/app/chrome_test_util.h"
#import "ios/testing/wait_util.h"
#import "ios/web/public/block_types.h"
#import "ios/web/public/test/earl_grey/web_view_matchers.h"
#include "ui/base/l10n/l10n_util.h"
Expand Down
9 changes: 5 additions & 4 deletions ios/web/public/test/earl_grey/web_view_matchers.mm
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
using testing::kWaitForDownloadTimeout;
using testing::WaitUntilConditionOrTimeout;

// TODO(crbug.com/757982): Remove this class, after LoadImage() is removed.
// A helper delegate class that allows downloading responses with invalid
// SSL certs.
@interface TestURLSessionDelegate : NSObject<NSURLSessionDelegate>
@interface TestURLSessionDelegateDeprecated : NSObject<NSURLSessionDelegate>
@end

@implementation TestURLSessionDelegate
@implementation TestURLSessionDelegateDeprecated

- (void)URLSession:(NSURLSession*)session
didReceiveChallenge:(NSURLAuthenticationChallenge*)challenge
Expand Down Expand Up @@ -64,8 +65,8 @@ - (void)URLSession:(NSURLSession*)session
UIImage* LoadImage(const GURL& image_url) {
__block UIImage* image;
__block NSError* error;
TestURLSessionDelegate* session_delegate =
[[TestURLSessionDelegate alloc] init];
TestURLSessionDelegateDeprecated* session_delegate =
[[TestURLSessionDelegateDeprecated alloc] init];
NSURLSessionConfiguration* session_config =
[NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession* session =
Expand Down
13 changes: 13 additions & 0 deletions ios/web/public/test/web_view_content_test_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
namespace web {
namespace test {

// Enum describing loaded/blocked state of an image html element.
enum ImageStateElement {
// Element was not loaded by WebState.
IMAGE_STATE_BLOCKED = 1,
// Element was fullt loaded by WebState.
IMAGE_STATE_LOADED,
};

// Returns true if there is a web view for |web_state| that contains |text|.
// Otherwise, returns false.
bool IsWebViewContainingText(web::WebState* web_state, const std::string& text);
Expand All @@ -19,6 +27,11 @@ bool IsWebViewContainingText(web::WebState* web_state, const std::string& text);
bool WaitForWebViewContainingText(web::WebState* web_state,
std::string text) WARN_UNUSED_RESULT;

// Waits for a web view with the corresponding |image_id| and |image_state|, in
// the given |web_state|.
bool WaitForWebViewContainingImage(std::string image_id,
web::WebState* web_state,
ImageStateElement image_state);
} // namespace test
} // namespace web

Expand Down
109 changes: 109 additions & 0 deletions ios/web/public/test/web_view_content_test_util.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,71 @@
#import "ios/web/public/test/web_view_content_test_util.h"

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#import "ios/testing/wait_util.h"
#import "ios/web/public/test/web_view_interaction_test_util.h"
#import "net/base/mac/url_conversions.h"

using testing::kWaitForDownloadTimeout;
using testing::WaitUntilConditionOrTimeout;

// A helper delegate class that allows downloading responses with invalid
// SSL certs.
@interface TestURLSessionDelegate : NSObject<NSURLSessionDelegate>
@end

@implementation TestURLSessionDelegate

- (void)URLSession:(NSURLSession*)session
didReceiveChallenge:(NSURLAuthenticationChallenge*)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition,
NSURLCredential*))completionHandler {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
completionHandler(NSURLSessionAuthChallengeUseCredential,
[NSURLCredential credentialForTrust:serverTrust]);
}

@end

namespace {
// Script that returns document.body as a string.
char kGetDocumentBodyJavaScript[] =
"document.body ? document.body.textContent : null";

// Fetches the image from |image_url|.
UIImage* LoadImage(const GURL& image_url) {
__block UIImage* image;
__block NSError* error;
TestURLSessionDelegate* session_delegate =
[[TestURLSessionDelegate alloc] init];
NSURLSessionConfiguration* session_config =
[NSURLSessionConfiguration ephemeralSessionConfiguration];
NSURLSession* session =
[NSURLSession sessionWithConfiguration:session_config
delegate:session_delegate
delegateQueue:nil];
id completion_handler = ^(NSData* data, NSURLResponse*, NSError* task_error) {
error = task_error;
image = [[UIImage alloc] initWithData:data];
};

NSURLSessionDataTask* task =
[session dataTaskWithURL:net::NSURLWithGURL(image_url)
completionHandler:completion_handler];
[task resume];

bool task_completed = WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{
return image || error;
});

if (!task_completed) {
return nil;
}
return image;
}
}

using testing::WaitUntilConditionOrTimeout;
Expand All @@ -38,5 +95,57 @@ bool WaitForWebViewContainingText(web::WebState* web_state, std::string text) {
});
}

bool WaitForWebViewContainingImage(std::string image_id,
web::WebState* web_state,
ImageStateElement image_state) {
std::string get_url_script =
base::StringPrintf("document.getElementById('%s').src", image_id.c_str());
std::unique_ptr<base::Value> url_as_value =
web::test::ExecuteJavaScript(web_state, get_url_script);
std::string url_as_string;
if (!url_as_value->GetAsString(&url_as_string))
return false;

UIImage* image = LoadImage(GURL(url_as_string));
if (!image)
return false;

CGSize expected_size = image.size;

return WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^{
NSString* const kGetElementAttributesScript =
[NSString stringWithFormat:
@"var image = document.getElementById('%@');"
@"var imageHeight = image.height;"
@"var imageWidth = image.width;"
@"JSON.stringify({"
@" height:imageHeight,"
@" width:imageWidth"
@"});",
base::SysUTF8ToNSString(image_id)];
std::unique_ptr<base::Value> value = web::test::ExecuteJavaScript(
web_state, base::SysNSStringToUTF8(kGetElementAttributesScript));
std::string result;
if (value && value->GetAsString(&result)) {
NSString* evaluation_result = base::SysUTF8ToNSString(result);
NSData* image_attributes_as_data =
[evaluation_result dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* image_attributes =
[NSJSONSerialization JSONObjectWithData:image_attributes_as_data
options:0
error:nil];
CGFloat height = [image_attributes[@"height"] floatValue];
CGFloat width = [image_attributes[@"width"] floatValue];
switch (image_state) {
case IMAGE_STATE_BLOCKED:
return height < expected_size.height && width < expected_size.width;
case IMAGE_STATE_LOADED:
return height == expected_size.height && width == expected_size.width;
}
}
return false;
});
}

} // namespace test
} // namespace web

0 comments on commit d8423f6

Please sign in to comment.