Skip to content

Commit

Permalink
fix: Assert app is installed before launching or activating it (#704)
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach authored May 15, 2023
1 parent 656f250 commit 94e5c51
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 1 deletion.
10 changes: 10 additions & 0 deletions WebDriverAgentLib/FBApplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error;

/**
Returns the bundle indentifier of the system app (ususally Springboard)
*/
+ (NSString *)fb_systemApplicationBundleID;

/**
Checks if the app is installed on the device under test.
*/
- (BOOL)fb_isInstalled;

@end

NS_ASSUME_NONNULL_END
36 changes: 36 additions & 0 deletions WebDriverAgentLib/FBApplication.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@

#import "FBApplication.h"

#import "FBExceptions.h"
#import "FBXCAccessibilityElement.h"
#import "FBLogger.h"
#import "FBRunLoopSpinner.h"
#import "FBMacros.h"
#import "FBActiveAppDetectionPoint.h"
#import "FBXCodeCompatibility.h"
#import "FBXCTestDaemonsProxy.h"
#import "LSApplicationWorkspace.h"
#import "XCUIApplication.h"
#import "XCUIApplication+FBHelpers.h"
#import "XCUIApplicationImpl.h"
Expand Down Expand Up @@ -133,6 +135,16 @@ + (instancetype)fb_systemApplication
[[FBXCAXClientProxy.sharedClient systemApplication] processIdentifier]];
}

+ (NSString *)fb_systemApplicationBundleID
{
static dispatch_once_t onceToken;
static NSString *systemAppBundleID;
dispatch_once(&onceToken, ^{
systemAppBundleID = [[self.class fb_systemApplication] bundleID];
});
return systemAppBundleID;
}

+ (instancetype)applicationWithPID:(pid_t)processID
{
if ([NSProcessInfo processInfo].processIdentifier == processID) {
Expand All @@ -141,14 +153,33 @@ + (instancetype)applicationWithPID:(pid_t)processID
return (FBApplication *)[FBXCAXClientProxy.sharedClient monitoredApplicationWithProcessIdentifier:processID];
}

/**
https://github.com/appium/WebDriverAgent/issues/702
*/
- (void)fb_assertInstalledByAction:(NSString *)action
{
if (![self.bundleID isEqualToString:[self.class fb_systemApplicationBundleID]] && !self.fb_isInstalled) {
NSString *message = [NSString stringWithFormat:@"The application '%@' cannot be %@ because it is not installed on the device under test",
self.bundleID, action];
[[NSException exceptionWithName:FBApplicationMissingException reason:message userInfo:nil] raise];
}
}

- (void)launch
{
[self fb_assertInstalledByAction:@"launched"];
[super launch];
if (![self fb_waitForAppElement:APP_STATE_CHANGE_TIMEOUT]) {
[FBLogger logFmt:@"The application '%@' is not running in foreground after %.2f seconds", self.bundleID, APP_STATE_CHANGE_TIMEOUT];
}
}

- (void)activate
{
[self fb_assertInstalledByAction:@"activated"];
[super activate];
}

- (void)terminate
{
[super terminate];
Expand Down Expand Up @@ -181,4 +212,9 @@ + (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error
error:error];
}

- (BOOL)fb_isInstalled
{
return [[LSApplicationWorkspace defaultWorkspace] applicationIsInstalled:self.bundleID];
}

@end
3 changes: 2 additions & 1 deletion WebDriverAgentLib/Routing/FBExceptionHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ - (void)handleException:(NSException *)exception forResponse:(RouteResponse *)re
commandStatus = [FBCommandStatus noSuchDriverErrorWithMessage:exception.reason
traceback:traceback];
} else if ([exception.name isEqualToString:FBInvalidArgumentException]
|| [exception.name isEqualToString:FBElementAttributeUnknownException]) {
|| [exception.name isEqualToString:FBElementAttributeUnknownException]
|| [exception.name isEqualToString:FBApplicationMissingException]) {
commandStatus = [FBCommandStatus invalidArgumentErrorWithMessage:exception.reason
traceback:traceback];
} else if ([exception.name isEqualToString:FBApplicationCrashedException]
Expand Down
3 changes: 3 additions & 0 deletions WebDriverAgentLib/Routing/FBExceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ extern NSString *const FBClassChainQueryParseException;
/*! Exception used to notify about application crash */
extern NSString *const FBApplicationCrashedException;

/*! Exception used to notify about the application is not installed */
extern NSString *const FBApplicationMissingException;

NS_ASSUME_NONNULL_END
1 change: 1 addition & 0 deletions WebDriverAgentLib/Routing/FBExceptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
NSString *const FBXPathQueryEvaluationException = @"FBXPathQueryEvaluationException";
NSString *const FBClassChainQueryParseException = @"FBClassChainQueryParseException";
NSString *const FBApplicationCrashedException = @"FBApplicationCrashedException";
NSString *const FBApplicationMissingException = @"FBApplicationMissingException";
29 changes: 29 additions & 0 deletions WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#import "FBIntegrationTestCase.h"
#import "FBApplication.h"
#import "FBExceptions.h"
#import "FBMacros.h"
#import "FBSession.h"
#import "FBXCodeCompatibility.h"
Expand Down Expand Up @@ -100,6 +101,34 @@ - (void)testMainAppCanBeRestartedInScopeOfTheCurrentSession
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:testedApp.bundleID]);
}

- (void)testAppWithInvalidBundleIDCannotBeStarted
{
FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"];
@try {
[testedApp launch];
XCTFail(@"An exception is expected to be thrown");
} @catch (NSException *exception) {
XCTAssertEqualObjects(FBApplicationMissingException, exception.name);
}
}

- (void)testAppWithInvalidBundleIDCannotBeActivated
{
FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"];
@try {
[testedApp activate];
XCTFail(@"An exception is expected to be thrown");
} @catch (NSException *exception) {
XCTAssertEqualObjects(FBApplicationMissingException, exception.name);
}
}

- (void)testAppWithInvalidBundleIDCannotBeTerminated
{
FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"];
[testedApp terminate];
}

- (void)testLaunchUnattachedApp
{
[FBUnattachedAppLauncher launchAppWithBundleId:SETTINGS_BUNDLE_ID];
Expand Down

0 comments on commit 94e5c51

Please sign in to comment.