appium-webdriveragent 5.15.5 → 5.15.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/PrivateHeaders/XCTest/XCSynthesizedEventRecord.h +1 -0
- package/PrivateHeaders/XCTest/XCUIApplication.h +0 -1
- package/WebDriverAgent.xcodeproj/project.pbxproj +6 -18
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +38 -0
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +148 -5
- package/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +1 -1
- package/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h +0 -1
- package/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m +5 -3
- package/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m +2 -2
- package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h +10 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +31 -15
- package/WebDriverAgentLib/Commands/FBAlertViewCommands.m +4 -4
- package/WebDriverAgentLib/Commands/FBCustomCommands.m +2 -2
- package/WebDriverAgentLib/Commands/FBDebugCommands.m +2 -3
- package/WebDriverAgentLib/Commands/FBElementCommands.m +3 -5
- package/WebDriverAgentLib/Commands/FBFindElementCommands.m +0 -1
- package/WebDriverAgentLib/Commands/FBOrientationCommands.m +9 -8
- package/WebDriverAgentLib/Commands/FBSessionCommands.m +7 -9
- package/WebDriverAgentLib/Commands/FBTouchActionCommands.m +0 -1
- package/WebDriverAgentLib/FBAlert.m +3 -3
- package/WebDriverAgentLib/Routing/FBSession.h +13 -14
- package/WebDriverAgentLib/Routing/FBSession.m +49 -46
- package/WebDriverAgentLib/Utilities/FBAlertsMonitor.m +3 -3
- package/WebDriverAgentLib/Utilities/FBConfiguration.h +1 -0
- package/WebDriverAgentLib/Utilities/FBConfiguration.m +16 -4
- package/WebDriverAgentLib/Utilities/FBKeyboard.h +0 -27
- package/WebDriverAgentLib/Utilities/FBKeyboard.m +6 -30
- package/WebDriverAgentLib/Utilities/FBMjpegServer.m +0 -1
- package/WebDriverAgentLib/Utilities/FBPasteboard.m +2 -2
- package/WebDriverAgentLib/Utilities/FBScreen.m +1 -2
- package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +1 -2
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +0 -33
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +2 -40
- package/WebDriverAgentLib/WebDriverAgentLib.h +0 -1
- package/WebDriverAgentTests/IntegrationTests/FBAlertTests.m +5 -1
- package/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m +3 -0
- package/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m +2 -3
- package/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m +6 -0
- package/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m +0 -1
- package/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.h +1 -3
- package/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m +5 -5
- package/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m +0 -22
- package/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m +1 -2
- package/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m +11 -10
- package/WebDriverAgentTests/IntegrationTests/FBTapTest.m +10 -6
- package/WebDriverAgentTests/IntegrationTests/FBTypingTest.m +4 -0
- package/WebDriverAgentTests/IntegrationTests/FBW3CMultiTouchActionsIntegrationTests.m +0 -1
- package/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +3 -0
- package/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +8 -8
- package/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m +5 -4
- package/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +0 -1
- package/WebDriverAgentTests/UnitTests/Doubles/{FBApplicationDouble.h → XCUIApplicationDouble.h} +1 -1
- package/WebDriverAgentTests/UnitTests/Doubles/{FBApplicationDouble.m → XCUIApplicationDouble.m} +3 -3
- package/WebDriverAgentTests/UnitTests/FBSessionTests.m +3 -3
- package/package.json +2 -2
- package/WebDriverAgentLib/FBApplication.h +0 -49
- package/WebDriverAgentLib/FBApplication.m +0 -185
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
#import "FBDebugCommands.h"
|
|
11
11
|
|
|
12
|
-
#import "FBApplication.h"
|
|
13
12
|
#import "FBRouteRequest.h"
|
|
14
13
|
#import "FBSession.h"
|
|
15
14
|
#import "FBXMLGenerationOptions.h"
|
|
@@ -42,7 +41,7 @@ static NSString *const SOURCE_FORMAT_DESCRIPTION = @"description";
|
|
|
42
41
|
+ (id<FBResponsePayload>)handleGetSourceCommand:(FBRouteRequest *)request
|
|
43
42
|
{
|
|
44
43
|
// This method might be called without session
|
|
45
|
-
|
|
44
|
+
XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication;
|
|
46
45
|
NSString *sourceType = request.parameters[@"format"] ?: SOURCE_FORMAT_XML;
|
|
47
46
|
NSString *sourceScope = request.parameters[@"scope"];
|
|
48
47
|
id result;
|
|
@@ -71,7 +70,7 @@ static NSString *const SOURCE_FORMAT_DESCRIPTION = @"description";
|
|
|
71
70
|
+ (id<FBResponsePayload>)handleGetAccessibleSourceCommand:(FBRouteRequest *)request
|
|
72
71
|
{
|
|
73
72
|
// This method might be called without session
|
|
74
|
-
|
|
73
|
+
XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication;
|
|
75
74
|
return FBResponseWithObject(application.fb_accessibilityTree ?: @{});
|
|
76
75
|
}
|
|
77
76
|
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
#import "FBElementCommands.h"
|
|
11
11
|
|
|
12
|
-
#import "FBApplication.h"
|
|
13
12
|
#import "FBConfiguration.h"
|
|
14
13
|
#import "FBKeyboard.h"
|
|
15
14
|
#import "FBRoute.h"
|
|
@@ -18,7 +17,6 @@
|
|
|
18
17
|
#import "FBElementCache.h"
|
|
19
18
|
#import "FBErrorBuilder.h"
|
|
20
19
|
#import "FBSession.h"
|
|
21
|
-
#import "FBApplication.h"
|
|
22
20
|
#import "FBElementUtils.h"
|
|
23
21
|
#import "FBMacros.h"
|
|
24
22
|
#import "FBMathUtils.h"
|
|
@@ -529,7 +527,7 @@
|
|
|
529
527
|
{
|
|
530
528
|
XCUIElement *element = nil;
|
|
531
529
|
if (nil == request.parameters[@"uuid"]) {
|
|
532
|
-
element =
|
|
530
|
+
element = XCUIApplication.fb_activeApplication;
|
|
533
531
|
} else {
|
|
534
532
|
FBElementCache *elementCache = request.session.elementCache;
|
|
535
533
|
element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
|
|
@@ -558,7 +556,7 @@
|
|
|
558
556
|
NSString *textToType = [request.arguments[@"value"] componentsJoinedByString:@""];
|
|
559
557
|
NSUInteger frequency = [request.arguments[@"frequency"] unsignedIntegerValue] ?: [FBConfiguration maxTypingFrequency];
|
|
560
558
|
NSError *error;
|
|
561
|
-
if (!
|
|
559
|
+
if (!FBTypeText(textToType, frequency, &error)) {
|
|
562
560
|
return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description
|
|
563
561
|
traceback:nil]);
|
|
564
562
|
}
|
|
@@ -567,7 +565,7 @@
|
|
|
567
565
|
|
|
568
566
|
+ (id<FBResponsePayload>)handleGetWindowSize:(FBRouteRequest *)request
|
|
569
567
|
{
|
|
570
|
-
XCUIApplication *app = request.session.activeApplication ?:
|
|
568
|
+
XCUIApplication *app = request.session.activeApplication ?: XCUIApplication.fb_activeApplication;
|
|
571
569
|
|
|
572
570
|
#if TARGET_OS_TV
|
|
573
571
|
CGSize screenSize = app.frame.size;
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
#import "FBRouteRequest.h"
|
|
13
13
|
#import "FBMacros.h"
|
|
14
14
|
#import "FBSession.h"
|
|
15
|
-
#import "
|
|
15
|
+
#import "XCUIApplication.h"
|
|
16
|
+
#import "XCUIApplication+FBHelpers.h"
|
|
16
17
|
#import "XCUIDevice.h"
|
|
17
18
|
|
|
18
19
|
extern const struct FBWDOrientationValues {
|
|
@@ -55,14 +56,14 @@ const struct FBWDOrientationValues FBWDOrientationValues = {
|
|
|
55
56
|
|
|
56
57
|
+ (id<FBResponsePayload>)handleGetOrientation:(FBRouteRequest *)request
|
|
57
58
|
{
|
|
58
|
-
|
|
59
|
+
XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication;
|
|
59
60
|
NSString *orientation = [self.class interfaceOrientationForApplication:application];
|
|
60
61
|
return FBResponseWithObject([[self _wdOrientationsMapping] objectForKey:orientation]);
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
+ (id<FBResponsePayload>)handleSetOrientation:(FBRouteRequest *)request
|
|
64
65
|
{
|
|
65
|
-
|
|
66
|
+
XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication;
|
|
66
67
|
if ([self.class setDeviceOrientation:request.arguments[@"orientation"] forApplication:application]) {
|
|
67
68
|
return FBResponseWithOK();
|
|
68
69
|
}
|
|
@@ -73,7 +74,7 @@ const struct FBWDOrientationValues FBWDOrientationValues = {
|
|
|
73
74
|
+ (id<FBResponsePayload>)handleGetRotation:(FBRouteRequest *)request
|
|
74
75
|
{
|
|
75
76
|
XCUIDevice *device = [XCUIDevice sharedDevice];
|
|
76
|
-
|
|
77
|
+
XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication;
|
|
77
78
|
UIInterfaceOrientation orientation = application.interfaceOrientation;
|
|
78
79
|
return FBResponseWithObject(device.fb_rotationMapping[@(orientation)]);
|
|
79
80
|
}
|
|
@@ -101,7 +102,7 @@ const struct FBWDOrientationValues FBWDOrientationValues = {
|
|
|
101
102
|
traceback:nil]);
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication;
|
|
105
106
|
if (![self.class setDeviceRotation:request.arguments forApplication:application]) {
|
|
106
107
|
NSString *errMessage = [
|
|
107
108
|
NSString stringWithFormat:@"The current rotation cannot be set to %@. Make sure the %@ application supports it",
|
|
@@ -116,7 +117,7 @@ const struct FBWDOrientationValues FBWDOrientationValues = {
|
|
|
116
117
|
|
|
117
118
|
#pragma mark - Helpers
|
|
118
119
|
|
|
119
|
-
+ (NSString *)interfaceOrientationForApplication:(
|
|
120
|
+
+ (NSString *)interfaceOrientationForApplication:(XCUIApplication *)application
|
|
120
121
|
{
|
|
121
122
|
NSNumber *orientation = @(application.interfaceOrientation);
|
|
122
123
|
NSSet *keys = [[self _orientationsMapping] keysOfEntriesPassingTest:^BOOL(id key, NSNumber *obj, BOOL *stop) {
|
|
@@ -128,12 +129,12 @@ const struct FBWDOrientationValues FBWDOrientationValues = {
|
|
|
128
129
|
return keys.anyObject;
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
+ (BOOL)setDeviceRotation:(NSDictionary *)rotationObj forApplication:(
|
|
132
|
+
+ (BOOL)setDeviceRotation:(NSDictionary *)rotationObj forApplication:(XCUIApplication *)application
|
|
132
133
|
{
|
|
133
134
|
return [[XCUIDevice sharedDevice] fb_setDeviceRotation:rotationObj];
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
+ (BOOL)setDeviceOrientation:(NSString *)orientation forApplication:(
|
|
137
|
+
+ (BOOL)setDeviceOrientation:(NSString *)orientation forApplication:(XCUIApplication *)application
|
|
137
138
|
{
|
|
138
139
|
NSNumber *orientationValue = [[self _orientationsMapping] objectForKey:[orientation uppercaseString]];
|
|
139
140
|
if (orientationValue == nil) {
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
#import "FBSessionCommands.h"
|
|
11
11
|
|
|
12
|
-
#import "FBApplication.h"
|
|
13
12
|
#import "FBCapabilities.h"
|
|
14
13
|
#import "FBConfiguration.h"
|
|
15
14
|
#import "FBLogger.h"
|
|
@@ -17,7 +16,6 @@
|
|
|
17
16
|
#import "FBRouteRequest.h"
|
|
18
17
|
#import "FBSession.h"
|
|
19
18
|
#import "FBSettings.h"
|
|
20
|
-
#import "FBApplication.h"
|
|
21
19
|
#import "FBRuntimeUtils.h"
|
|
22
20
|
#import "FBActiveAppDetectionPoint.h"
|
|
23
21
|
#import "FBXCodeCompatibility.h"
|
|
@@ -138,15 +136,15 @@
|
|
|
138
136
|
}
|
|
139
137
|
|
|
140
138
|
NSString *bundleID = capabilities[FB_CAP_BUNDLE_ID];
|
|
141
|
-
|
|
139
|
+
XCUIApplication *app = nil;
|
|
142
140
|
if (bundleID != nil) {
|
|
143
|
-
app = [[
|
|
141
|
+
app = [[XCUIApplication alloc] initWithBundleIdentifier:bundleID];
|
|
144
142
|
BOOL forceAppLaunch = YES;
|
|
145
143
|
if (nil != capabilities[FB_CAP_FORCE_APP_LAUNCH]) {
|
|
146
144
|
forceAppLaunch = [capabilities[FB_CAP_FORCE_APP_LAUNCH] boolValue];
|
|
147
145
|
}
|
|
148
|
-
|
|
149
|
-
BOOL isAppRunning = appState >=
|
|
146
|
+
XCUIApplicationState appState = app.state;
|
|
147
|
+
BOOL isAppRunning = appState >= XCUIApplicationStateRunningBackground;
|
|
150
148
|
if (!isAppRunning || (isAppRunning && forceAppLaunch)) {
|
|
151
149
|
app.fb_shouldWaitForQuiescence = nil == capabilities[FB_CAP_SHOULD_WAIT_FOR_QUIESCENCE]
|
|
152
150
|
|| [capabilities[FB_CAP_SHOULD_WAIT_FOR_QUIESCENCE] boolValue];
|
|
@@ -158,8 +156,8 @@
|
|
|
158
156
|
return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg
|
|
159
157
|
traceback:nil]);
|
|
160
158
|
}
|
|
161
|
-
} else if (appState
|
|
162
|
-
[app
|
|
159
|
+
} else if (appState == XCUIApplicationStateRunningBackground && !forceAppLaunch) {
|
|
160
|
+
[app activate];
|
|
163
161
|
}
|
|
164
162
|
}
|
|
165
163
|
|
|
@@ -265,7 +263,7 @@
|
|
|
265
263
|
|
|
266
264
|
+ (id<FBResponsePayload>)handleGetHealthCheck:(FBRouteRequest *)request
|
|
267
265
|
{
|
|
268
|
-
if (![[XCUIDevice sharedDevice] fb_healthCheckWithApplication:[
|
|
266
|
+
if (![[XCUIDevice sharedDevice] fb_healthCheckWithApplication:[XCUIApplication fb_activeApplication]]) {
|
|
269
267
|
return FBResponseWithUnknownErrorFormat(@"Health check failed");
|
|
270
268
|
}
|
|
271
269
|
return FBResponseWithOK();
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
|
|
10
10
|
#import "FBAlert.h"
|
|
11
11
|
|
|
12
|
-
#import "FBApplication.h"
|
|
13
12
|
#import "FBConfiguration.h"
|
|
14
13
|
#import "FBErrorBuilder.h"
|
|
15
14
|
#import "FBLogger.h"
|
|
16
15
|
#import "FBXCElementSnapshotWrapper+Helpers.h"
|
|
17
16
|
#import "FBXCodeCompatibility.h"
|
|
17
|
+
#import "XCUIApplication.h"
|
|
18
18
|
#import "XCUIApplication+FBAlert.h"
|
|
19
19
|
#import "XCUIElement+FBClassChain.h"
|
|
20
20
|
#import "XCUIElement+FBTyping.h"
|
|
@@ -263,8 +263,8 @@
|
|
|
263
263
|
if (nil == self.element) {
|
|
264
264
|
self.element = self.application.fb_alertElement;
|
|
265
265
|
if (nil == self.element) {
|
|
266
|
-
|
|
267
|
-
for (
|
|
266
|
+
XCUIApplication *systemApp = XCUIApplication.fb_systemApplication;
|
|
267
|
+
for (XCUIApplication *activeApp in XCUIApplication.fb_activeApplications) {
|
|
268
268
|
if (systemApp.processID == activeApp.processID) {
|
|
269
269
|
self.element = activeApp.fb_alertElement;
|
|
270
270
|
break;
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
#import <Foundation/Foundation.h>
|
|
11
11
|
|
|
12
|
-
@class FBApplication;
|
|
13
12
|
@class FBElementCache;
|
|
13
|
+
@class XCUIApplication;
|
|
14
14
|
|
|
15
15
|
NS_ASSUME_NONNULL_BEGIN
|
|
16
16
|
|
|
@@ -20,16 +20,16 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
20
20
|
@interface FBSession : NSObject
|
|
21
21
|
|
|
22
22
|
/*! Application tested during that session */
|
|
23
|
-
@property (nonatomic,
|
|
23
|
+
@property (nonatomic, readonly) XCUIApplication *activeApplication;
|
|
24
24
|
|
|
25
25
|
/*! Session's identifier */
|
|
26
|
-
@property (nonatomic,
|
|
26
|
+
@property (nonatomic, readonly) NSString *identifier;
|
|
27
27
|
|
|
28
28
|
/*! Element cache related to that session */
|
|
29
|
-
@property (nonatomic,
|
|
29
|
+
@property (nonatomic, readonly) FBElementCache *elementCache;
|
|
30
30
|
|
|
31
31
|
/*! The identifier of the active application */
|
|
32
|
-
@property (nonatomic
|
|
32
|
+
@property (nonatomic) NSString *defaultActiveApplication;
|
|
33
33
|
|
|
34
34
|
/*! The action to apply to unexpected alerts. Either "accept"/"dismiss" or nil/empty string (by default) to do nothing */
|
|
35
35
|
@property (nonatomic, nullable) NSString *defaultAlertAction;
|
|
@@ -57,7 +57,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
57
57
|
@param application The application that we want to create session for
|
|
58
58
|
@return new session
|
|
59
59
|
*/
|
|
60
|
-
+ (instancetype)initWithApplication:(nullable
|
|
60
|
+
+ (instancetype)initWithApplication:(nullable XCUIApplication *)application;
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
Creates and saves new session for application with default alert handling behaviour
|
|
@@ -66,7 +66,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
66
66
|
@param defaultAlertAction The default reaction to on-screen alert. Either 'accept' or 'dismiss'
|
|
67
67
|
@return new session
|
|
68
68
|
*/
|
|
69
|
-
+ (instancetype)initWithApplication:(nullable
|
|
69
|
+
+ (instancetype)initWithApplication:(nullable XCUIApplication *)application
|
|
70
|
+
defaultAlertAction:(NSString *)defaultAlertAction;
|
|
70
71
|
|
|
71
72
|
/**
|
|
72
73
|
Kills application associated with that session and removes session
|
|
@@ -82,12 +83,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
82
83
|
@param arguments The optional array of application command line arguments. The arguments are going to be applied if the application was not running before.
|
|
83
84
|
@param environment The optional dictionary of environment variables for the application, which is going to be executed. The environment variables are going to be applied if the application was not running before.
|
|
84
85
|
@return The application instance
|
|
85
|
-
@throws FBApplicationMethodNotSupportedException if the method is not supported with the current XCTest SDK
|
|
86
86
|
*/
|
|
87
|
-
- (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
- (XCUIApplication *)launchApplicationWithBundleId:(NSString *)bundleIdentifier
|
|
88
|
+
shouldWaitForQuiescence:(nullable NSNumber *)shouldWaitForQuiescence
|
|
89
|
+
arguments:(nullable NSArray<NSString *> *)arguments
|
|
90
|
+
environment:(nullable NSDictionary <NSString *, NSString *> *)environment;
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
93
|
Activate an application with given bundle identifier in scope of current session.
|
|
@@ -95,9 +95,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
95
95
|
|
|
96
96
|
@param bundleIdentifier Valid bundle identifier of the application to be activated
|
|
97
97
|
@return The application instance
|
|
98
|
-
@throws FBApplicationMethodNotSupportedException if the method is not supported with the current XCTest SDK
|
|
99
98
|
*/
|
|
100
|
-
- (
|
|
99
|
+
- (XCUIApplication *)activateApplicationWithBundleId:(NSString *)bundleIdentifier;
|
|
101
100
|
|
|
102
101
|
/**
|
|
103
102
|
Terminate an application with the given bundle id. The application should be previously
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
#import "FBXCAccessibilityElement.h"
|
|
16
16
|
#import "FBAlertsMonitor.h"
|
|
17
|
-
#import "FBApplication.h"
|
|
18
17
|
#import "FBConfiguration.h"
|
|
19
18
|
#import "FBElementCache.h"
|
|
20
19
|
#import "FBExceptions.h"
|
|
@@ -31,7 +30,7 @@
|
|
|
31
30
|
NSString *const FBDefaultApplicationAuto = @"auto";
|
|
32
31
|
|
|
33
32
|
@interface FBSession ()
|
|
34
|
-
@property (nonatomic)
|
|
33
|
+
@property (nullable, nonatomic) XCUIApplication *testedApplication;
|
|
35
34
|
@property (nonatomic) BOOL isTestedApplicationExpectedToRun;
|
|
36
35
|
@property (nonatomic) BOOL shouldAppsWaitForQuiescence;
|
|
37
36
|
@property (nonatomic, nullable) FBAlertsMonitor *alertsMonitor;
|
|
@@ -96,7 +95,7 @@ static FBSession *_activeSession = nil;
|
|
|
96
95
|
return _activeSession;
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
+ (instancetype)initWithApplication:(
|
|
98
|
+
+ (instancetype)initWithApplication:(XCUIApplication *)application
|
|
100
99
|
{
|
|
101
100
|
FBSession *session = [FBSession new];
|
|
102
101
|
session.useNativeCachingStrategy = YES;
|
|
@@ -105,10 +104,10 @@ static FBSession *_activeSession = nil;
|
|
|
105
104
|
session.elementsVisibilityCache = [NSMutableDictionary dictionary];
|
|
106
105
|
session.identifier = [[NSUUID UUID] UUIDString];
|
|
107
106
|
session.defaultActiveApplication = FBDefaultApplicationAuto;
|
|
108
|
-
session.
|
|
107
|
+
session.testedApplication = nil;
|
|
109
108
|
session.isTestedApplicationExpectedToRun = nil != application && application.running;
|
|
110
109
|
if (application) {
|
|
111
|
-
session.
|
|
110
|
+
session.testedApplication = application;
|
|
112
111
|
session.shouldAppsWaitForQuiescence = application.fb_shouldWaitForQuiescence;
|
|
113
112
|
}
|
|
114
113
|
session.elementCache = [FBElementCache new];
|
|
@@ -116,7 +115,7 @@ static FBSession *_activeSession = nil;
|
|
|
116
115
|
return session;
|
|
117
116
|
}
|
|
118
117
|
|
|
119
|
-
+ (instancetype)initWithApplication:(nullable
|
|
118
|
+
+ (instancetype)initWithApplication:(nullable XCUIApplication *)application
|
|
120
119
|
defaultAlertAction:(NSString *)defaultAlertAction
|
|
121
120
|
{
|
|
122
121
|
FBSession *session = [self.class initWithApplication:application];
|
|
@@ -138,81 +137,78 @@ static FBSession *_activeSession = nil;
|
|
|
138
137
|
self.alertsMonitor = nil;
|
|
139
138
|
}
|
|
140
139
|
|
|
141
|
-
if (self.
|
|
142
|
-
&&
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
140
|
+
if (nil != self.testedApplication
|
|
141
|
+
&& FBConfiguration.shouldTerminateApp
|
|
142
|
+
&& self.testedApplication.running
|
|
143
|
+
&& ![self.testedApplication fb_isSameAppAs:XCUIApplication.fb_systemApplication]) {
|
|
144
|
+
@try {
|
|
145
|
+
[self.testedApplication terminate];
|
|
146
|
+
} @catch (NSException *e) {
|
|
147
|
+
[FBLogger logFmt:@"%@", e.description];
|
|
150
148
|
}
|
|
151
149
|
}
|
|
152
150
|
|
|
153
151
|
_activeSession = nil;
|
|
154
152
|
}
|
|
155
153
|
|
|
156
|
-
- (
|
|
154
|
+
- (XCUIApplication *)activeApplication
|
|
157
155
|
{
|
|
156
|
+
if (nil != self.testedApplication) {
|
|
157
|
+
XCUIApplicationState testedAppState = self.testedApplication.state;
|
|
158
|
+
if (testedAppState >= XCUIApplicationStateRunningForeground) {
|
|
159
|
+
return (XCUIApplication *)self.testedApplication;
|
|
160
|
+
}
|
|
161
|
+
if (self.isTestedApplicationExpectedToRun && testedAppState <= XCUIApplicationStateNotRunning) {
|
|
162
|
+
NSString *description = [NSString stringWithFormat:@"The application under test with bundle id '%@' is not running, possibly crashed", self.testedApplication.bundleID];
|
|
163
|
+
@throw [NSException exceptionWithName:FBApplicationCrashedException reason:description userInfo:nil];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
158
167
|
NSString *defaultBundleId = [self.defaultActiveApplication isEqualToString:FBDefaultApplicationAuto]
|
|
159
168
|
? nil
|
|
160
169
|
: self.defaultActiveApplication;
|
|
161
|
-
|
|
162
|
-
FBApplication *testedApplication = nil;
|
|
163
|
-
if (self.testedApplicationBundleId && self.isTestedApplicationExpectedToRun) {
|
|
164
|
-
testedApplication = nil != application.bundleID && [application.bundleID isEqualToString:self.testedApplicationBundleId]
|
|
165
|
-
? application
|
|
166
|
-
: [[FBApplication alloc] initWithBundleIdentifier:self.testedApplicationBundleId];
|
|
167
|
-
}
|
|
168
|
-
if (testedApplication && !testedApplication.running) {
|
|
169
|
-
NSString *description = [NSString stringWithFormat:@"The application under test with bundle id '%@' is not running, possibly crashed", self.testedApplicationBundleId];
|
|
170
|
-
[[NSException exceptionWithName:FBApplicationCrashedException reason:description userInfo:nil] raise];
|
|
171
|
-
}
|
|
172
|
-
return application;
|
|
170
|
+
return [XCUIApplication fb_activeApplicationWithDefaultBundleId:defaultBundleId];
|
|
173
171
|
}
|
|
174
172
|
|
|
175
|
-
- (
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
173
|
+
- (XCUIApplication *)launchApplicationWithBundleId:(NSString *)bundleIdentifier
|
|
174
|
+
shouldWaitForQuiescence:(nullable NSNumber *)shouldWaitForQuiescence
|
|
175
|
+
arguments:(nullable NSArray<NSString *> *)arguments
|
|
176
|
+
environment:(nullable NSDictionary <NSString *, NSString *> *)environment
|
|
179
177
|
{
|
|
180
|
-
|
|
178
|
+
XCUIApplication *app = [self makeApplicationWithBundleId:bundleIdentifier];
|
|
181
179
|
if (nil == shouldWaitForQuiescence) {
|
|
182
180
|
// Iherit the quiescence check setting from the main app under test by default
|
|
183
|
-
app.fb_shouldWaitForQuiescence = nil != self.
|
|
181
|
+
app.fb_shouldWaitForQuiescence = nil != self.testedApplication && self.shouldAppsWaitForQuiescence;
|
|
184
182
|
} else {
|
|
185
183
|
app.fb_shouldWaitForQuiescence = [shouldWaitForQuiescence boolValue];
|
|
186
184
|
}
|
|
187
|
-
if (app.
|
|
185
|
+
if (!app.running) {
|
|
188
186
|
app.launchArguments = arguments ?: @[];
|
|
189
187
|
app.launchEnvironment = environment ?: @{};
|
|
190
188
|
[app launch];
|
|
191
189
|
} else {
|
|
192
|
-
[app
|
|
190
|
+
[app activate];
|
|
193
191
|
}
|
|
194
|
-
if (
|
|
195
|
-
&& [bundleIdentifier isEqualToString:(NSString *)self.testedApplicationBundleId]) {
|
|
192
|
+
if ([app fb_isSameAppAs:self.testedApplication]) {
|
|
196
193
|
self.isTestedApplicationExpectedToRun = YES;
|
|
197
194
|
}
|
|
198
195
|
return app;
|
|
199
196
|
}
|
|
200
197
|
|
|
201
|
-
- (
|
|
198
|
+
- (XCUIApplication *)activateApplicationWithBundleId:(NSString *)bundleIdentifier
|
|
202
199
|
{
|
|
203
|
-
|
|
204
|
-
[app
|
|
200
|
+
XCUIApplication *app = [self makeApplicationWithBundleId:bundleIdentifier];
|
|
201
|
+
[app activate];
|
|
205
202
|
return app;
|
|
206
203
|
}
|
|
207
204
|
|
|
208
205
|
- (BOOL)terminateApplicationWithBundleId:(NSString *)bundleIdentifier
|
|
209
206
|
{
|
|
210
|
-
|
|
211
|
-
if (
|
|
212
|
-
&& [bundleIdentifier isEqualToString:(NSString *)self.testedApplicationBundleId]) {
|
|
207
|
+
XCUIApplication *app = [self makeApplicationWithBundleId:bundleIdentifier];
|
|
208
|
+
if ([app fb_isSameAppAs:self.testedApplication]) {
|
|
213
209
|
self.isTestedApplicationExpectedToRun = NO;
|
|
214
210
|
}
|
|
215
|
-
if (app.
|
|
211
|
+
if (app.running) {
|
|
216
212
|
[app terminate];
|
|
217
213
|
return YES;
|
|
218
214
|
}
|
|
@@ -221,7 +217,14 @@ static FBSession *_activeSession = nil;
|
|
|
221
217
|
|
|
222
218
|
- (NSUInteger)applicationStateWithBundleId:(NSString *)bundleIdentifier
|
|
223
219
|
{
|
|
224
|
-
return [
|
|
220
|
+
return [self makeApplicationWithBundleId:bundleIdentifier].state;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
- (XCUIApplication *)makeApplicationWithBundleId:(NSString *)bundleIdentifier
|
|
224
|
+
{
|
|
225
|
+
return nil != self.testedApplication && [bundleIdentifier isEqualToString:(NSString *)self.testedApplication.bundleID]
|
|
226
|
+
? self.testedApplication
|
|
227
|
+
: [[XCUIApplication alloc] initWithBundleIdentifier:bundleIdentifier];
|
|
225
228
|
}
|
|
226
229
|
|
|
227
230
|
@end
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
#import "FBAlertsMonitor.h"
|
|
11
11
|
|
|
12
12
|
#import "FBAlert.h"
|
|
13
|
-
#import "FBApplication.h"
|
|
14
13
|
#import "FBLogger.h"
|
|
15
14
|
#import "XCUIApplication+FBAlert.h"
|
|
15
|
+
#import "XCUIApplication+FBHelpers.h"
|
|
16
16
|
|
|
17
17
|
static const NSTimeInterval FB_MONTORING_INTERVAL = 2.0;
|
|
18
18
|
|
|
@@ -49,8 +49,8 @@ static const NSTimeInterval FB_MONTORING_INTERVAL = 2.0;
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
52
|
-
NSArray<
|
|
53
|
-
for (
|
|
52
|
+
NSArray<XCUIApplication *> *activeApps = XCUIApplication.fb_activeApplications;
|
|
53
|
+
for (XCUIApplication *activeApp in activeApps) {
|
|
54
54
|
XCUIElement *alertElement = nil;
|
|
55
55
|
@try {
|
|
56
56
|
alertElement = activeApp.fb_alertElement;
|
|
@@ -60,6 +60,7 @@ extern NSString *const FBSnapshotMaxDepthKey;
|
|
|
60
60
|
/* The maximum typing frequency for all typing activities */
|
|
61
61
|
+ (void)setMaxTypingFrequency:(NSUInteger)value;
|
|
62
62
|
+ (NSUInteger)maxTypingFrequency;
|
|
63
|
+
+ (NSUInteger)defaultTypingFrequency;
|
|
63
64
|
|
|
64
65
|
/* Use singleton test manager proxy */
|
|
65
66
|
+ (void)setShouldUseSingletonTestManager:(BOOL)value;
|
|
@@ -39,7 +39,7 @@ static NSUInteger FBMjpegServerFramerate = 10;
|
|
|
39
39
|
|
|
40
40
|
// Session-specific settings
|
|
41
41
|
static BOOL FBShouldTerminateApp;
|
|
42
|
-
static
|
|
42
|
+
static NSNumber* FBMaxTypingFrequency;
|
|
43
43
|
static NSUInteger FBScreenshotQuality;
|
|
44
44
|
static NSTimeInterval FBCustomSnapshotTimeout;
|
|
45
45
|
static BOOL FBShouldUseFirstMatch;
|
|
@@ -57,6 +57,13 @@ static UIInterfaceOrientation FBScreenshotOrientation;
|
|
|
57
57
|
|
|
58
58
|
@implementation FBConfiguration
|
|
59
59
|
|
|
60
|
+
+ (NSUInteger)defaultTypingFrequency
|
|
61
|
+
{
|
|
62
|
+
NSInteger defaultFreq = [[NSUserDefaults standardUserDefaults]
|
|
63
|
+
integerForKey:@"com.apple.xctest.iOSMaximumTypingFrequency"];
|
|
64
|
+
return defaultFreq > 0 ? defaultFreq : 60;
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
+ (void)initialize
|
|
61
68
|
{
|
|
62
69
|
[FBConfiguration resetSessionSettings];
|
|
@@ -200,12 +207,17 @@ static UIInterfaceOrientation FBScreenshotOrientation;
|
|
|
200
207
|
|
|
201
208
|
+ (void)setMaxTypingFrequency:(NSUInteger)value
|
|
202
209
|
{
|
|
203
|
-
FBMaxTypingFrequency = value;
|
|
210
|
+
FBMaxTypingFrequency = @(value);
|
|
204
211
|
}
|
|
205
212
|
|
|
206
213
|
+ (NSUInteger)maxTypingFrequency
|
|
207
214
|
{
|
|
208
|
-
|
|
215
|
+
if (nil == FBMaxTypingFrequency) {
|
|
216
|
+
return [self defaultTypingFrequency];
|
|
217
|
+
}
|
|
218
|
+
return FBMaxTypingFrequency.integerValue <= 0
|
|
219
|
+
? [self defaultTypingFrequency]
|
|
220
|
+
: FBMaxTypingFrequency.integerValue;
|
|
209
221
|
}
|
|
210
222
|
|
|
211
223
|
+ (void)setShouldUseSingletonTestManager:(BOOL)value
|
|
@@ -462,7 +474,7 @@ static UIInterfaceOrientation FBScreenshotOrientation;
|
|
|
462
474
|
FBShouldTerminateApp = YES;
|
|
463
475
|
FBShouldUseCompactResponses = YES;
|
|
464
476
|
FBElementResponseAttributes = @"type,label";
|
|
465
|
-
FBMaxTypingFrequency =
|
|
477
|
+
FBMaxTypingFrequency = @([self defaultTypingFrequency]);
|
|
466
478
|
FBScreenshotQuality = 3;
|
|
467
479
|
FBCustomSnapshotTimeout = 15.;
|
|
468
480
|
FBShouldUseFirstMatch = NO;
|
|
@@ -23,19 +23,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
23
23
|
+ (nullable NSString *)keyValueForName:(NSString *)name;
|
|
24
24
|
#endif
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
Types a string into active element. There must be element with keyboard focus; otherwise an
|
|
28
|
-
error is raised.
|
|
29
|
-
|
|
30
|
-
This API discards any modifiers set in the current context by +performWithKeyModifiers:block: so that
|
|
31
|
-
it strictly interprets the provided text. To input keys with modifier flags, use -typeKey:modifierFlags:.
|
|
32
|
-
|
|
33
|
-
@param text that should be typed
|
|
34
|
-
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
35
|
-
@return YES if the operation succeeds, otherwise NO.
|
|
36
|
-
*/
|
|
37
|
-
+ (BOOL)typeText:(NSString *)text error:(NSError **)error;
|
|
38
|
-
|
|
39
26
|
/**
|
|
40
27
|
Waits until the keyboard is visible on the screen or a timeout happens
|
|
41
28
|
|
|
@@ -46,20 +33,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
46
33
|
*/
|
|
47
34
|
+ (BOOL)waitUntilVisibleForApplication:(XCUIApplication *)app timeout:(NSTimeInterval)timeout error:(NSError **)error;
|
|
48
35
|
|
|
49
|
-
/**
|
|
50
|
-
Types a string into active element. There must be element with keyboard focus; otherwise an
|
|
51
|
-
error is raised.
|
|
52
|
-
|
|
53
|
-
This API discards any modifiers set in the current context by +performWithKeyModifiers:block: so that
|
|
54
|
-
it strictly interprets the provided text. To input keys with modifier flags, use -typeKey:modifierFlags:.
|
|
55
|
-
|
|
56
|
-
@param text that should be typed
|
|
57
|
-
@param frequency Frequency of typing (letters per sec)
|
|
58
|
-
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
59
|
-
@return YES if the operation succeeds, otherwise NO.
|
|
60
|
-
*/
|
|
61
|
-
+ (BOOL)typeText:(NSString *)text frequency:(NSUInteger)frequency error:(NSError **)error;
|
|
62
|
-
|
|
63
36
|
@end
|
|
64
37
|
|
|
65
38
|
NS_ASSUME_NONNULL_END
|