Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make adjusting screenshot coordinate configurable - screenshotOrientation settings api #277

Merged
16 changes: 16 additions & 0 deletions WebDriverAgentLib/Commands/FBSessionCommands.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
static NSString* const INCLUDE_NON_MODAL_ELEMENTS = @"includeNonModalElements";
static NSString* const ACCEPT_ALERT_BUTTON_SELECTOR = @"acceptAlertButtonSelector";
static NSString* const DISMISS_ALERT_BUTTON_SELECTOR = @"dismissAlertButtonSelector";
static NSString* const SCREENSHOT_ORIENTATION = @"screenshotOrientation";


@implementation FBSessionCommands
Expand Down Expand Up @@ -258,6 +259,9 @@ + (NSArray *)routes
INCLUDE_NON_MODAL_ELEMENTS: @([FBConfiguration includeNonModalElements]),
ACCEPT_ALERT_BUTTON_SELECTOR: FBConfiguration.acceptAlertButtonSelector,
DISMISS_ALERT_BUTTON_SELECTOR: FBConfiguration.dismissAlertButtonSelector,
#if !TARGET_OS_TV
SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation],
#endif
}
);
}
Expand Down Expand Up @@ -328,6 +332,18 @@ + (NSArray *)routes
[FBConfiguration setDismissAlertButtonSelector:(NSString *)[settings objectForKey:DISMISS_ALERT_BUTTON_SELECTOR]];
}

#if !TARGET_OS_TV

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

if (nil != [settings objectForKey:SCREENSHOT_ORIENTATION]) {
NSError *error;
if (![FBConfiguration setScreenshotOrientation:(NSString *)[settings objectForKey:SCREENSHOT_ORIENTATION]
error:&error]) {
return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.description traceback:nil]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}


}
#endif

return [self handleGetSettings:request];
}

Expand Down
29 changes: 29 additions & 0 deletions WebDriverAgentLib/Utilities/FBConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,35 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)setDismissAlertButtonSelector:(NSString *)classChainSelector;
+ (NSString *)dismissAlertButtonSelector;

#if !TARGET_OS_TV
/**
Set the screenshot orientation for iOS

It helps to fix the screenshot orientation when the device under test's orientation changes.
For example, when a device changes to the landscape, the screenshot orientation could be wrong.
Then, this setting can force change the screenshot orientation.
Xcode versions, OS versions or device models and simulator or real device could influence it.

@param orientation Set the orientation to adjust the screenshot.
Case insensitive "portrait", "portraitUpsideDown", "landscapeRight" and "landscapeLeft" are available
to force the coodinate adjust. Other words are handled as "auto", which handles
the adjustment automatically. Defaults to "auto".
@param error If no availale orientation strategy was given, it returns an NSError object that describes the problem.
*/
+ (BOOL)setScreenshotOrientation:(NSString *)orientation error:(NSError **)error;

/**
@return The value of UIInterfaceOrientation
*/
+ (NSInteger)screenshotOrientation;

/**
@return The orientation as String for human read
*/
+ (NSString *)humanReadableScreenshotOrientation;

#endif

@end

NS_ASSUME_NONNULL_END
49 changes: 49 additions & 0 deletions WebDriverAgentLib/Utilities/FBConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
static NSString *FBSnapshotMaxDepthKey = @"maxDepth";
static NSMutableDictionary *FBSnapshotRequestParameters;

#if !TARGET_OS_TV
static UIInterfaceOrientation FBScreenshotOrientation = UIInterfaceOrientationUnknown;
#endif

@implementation FBConfiguration

Expand Down Expand Up @@ -343,6 +346,52 @@ + (NSString *)dismissAlertButtonSelector
return FBDismissAlertButtonSelector;
}

#if !TARGET_OS_TV
+ (BOOL)setScreenshotOrientation:(NSString *)orientation error:(NSError **)error
{
// Only UIInterfaceOrientationUnknown is over iOS 8. Others are over iOS 2.
// https://developer.apple.com/documentation/uikit/uiinterfaceorientation/uiinterfaceorientationunknown
if ([orientation.lowercaseString isEqualToString:@"portrait"]) {
FBScreenshotOrientation = UIInterfaceOrientationPortrait;
} else if ([orientation.lowercaseString isEqualToString:@"portraitupsidedown"]) {
FBScreenshotOrientation = UIInterfaceOrientationPortraitUpsideDown;
} else if ([orientation.lowercaseString isEqualToString:@"landscaperight"]) {
FBScreenshotOrientation = UIInterfaceOrientationLandscapeRight;
} else if ([orientation.lowercaseString isEqualToString:@"landscapeleft"]) {
FBScreenshotOrientation = UIInterfaceOrientationLandscapeLeft;
} else if ([orientation.lowercaseString isEqualToString:@"auto"]) {
FBScreenshotOrientation = UIInterfaceOrientationUnknown;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather throw an error if an unknown setting value is provided

} else {
return [[FBErrorBuilder.builder withDescriptionFormat:
@"The orientation value '%@' is not known. Only the following orientation values are supported: " \
"'auto', 'portrate', 'portraitUpsideDown', 'landscapeRight' and 'landscapeLeft'", orientation]
buildError:error];
}
return YES;
}

+ (NSInteger)screenshotOrientation
{
return FBScreenshotOrientation;
}

+ (NSString *)humanReadableScreenshotOrientation
{
switch (FBScreenshotOrientation) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

case UIInterfaceOrientationPortrait:
return @"portrait";
case UIInterfaceOrientationPortraitUpsideDown:
return @"portraitUpsideDown";
case UIInterfaceOrientationLandscapeRight:
return @"landscapeRight";
case UIInterfaceOrientationLandscapeLeft:
return @"landscapeLeft";
case UIInterfaceOrientationUnknown:
return @"auto";
}
}
#endif

#pragma mark Private

+ (BOOL)keyboardsPreference:(nonnull NSString *)key
Expand Down
44 changes: 31 additions & 13 deletions WebDriverAgentLib/Utilities/FBImageUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import "FBImageUtils.h"

#import "FBMacros.h"
#import "FBConfiguration.h"

static uint8_t JPEG_MAGIC[] = { 0xff, 0xd8 };
static const NSUInteger JPEG_MAGIC_LEN = 2;
Expand Down Expand Up @@ -67,21 +68,38 @@ BOOL FBIsPngImage(NSData *imageData)
NSData *FBAdjustScreenshotOrientationForApplication(NSData *screenshotData, UIInterfaceOrientation orientation)
{
UIImageOrientation imageOrientation;
if (SYSTEM_VERSION_LESS_THAN(@"11.0")) {
// In iOS < 11.0 screenshots are already adjusted properly
imageOrientation = UIImageOrientationUp;
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
imageOrientation = UIImageOrientationLeft;
} else if (orientation == UIInterfaceOrientationLandscapeLeft) {
imageOrientation = UIImageOrientationRight;
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
imageOrientation = UIImageOrientationDown;
if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationUnknown) {
if (SYSTEM_VERSION_LESS_THAN(@"11.0")) {
// In iOS < 11.0 screenshots are already adjusted properly
imageOrientation = UIImageOrientationUp;
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
imageOrientation = UIImageOrientationLeft;
} else if (orientation == UIInterfaceOrientationLandscapeLeft) {
imageOrientation = UIImageOrientationRight;
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
imageOrientation = UIImageOrientationDown;
} else {
if (FBIsPngImage(screenshotData)) {
return screenshotData;
}
UIImage *image = [UIImage imageWithData:screenshotData];
return (NSData *)UIImagePNGRepresentation(image);
}
} else {
if (FBIsPngImage(screenshotData)) {
return screenshotData;
switch (FBConfiguration.screenshotOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
imageOrientation = UIImageOrientationDown;
break;
case UIInterfaceOrientationLandscapeRight:
imageOrientation = UIImageOrientationLeft;
break;
case UIInterfaceOrientationLandscapeLeft:
imageOrientation = UIImageOrientationRight;
break;
default:
imageOrientation = UIImageOrientationUp;
break;
}
UIImage *image = [UIImage imageWithData:screenshotData];
return (NSData *)UIImagePNGRepresentation(image);
}

UIImage *image = [UIImage imageWithData:screenshotData];
Expand Down