appium-webdriveragent 16.1.2 → 16.1.4
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 +13 -0
- package/WebDriverAgent.xcodeproj/project.pbxproj +297 -0
- package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationApp_tvOS.xcscheme +78 -0
- package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationTests_tvOS.xcscheme +86 -0
- package/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.h +20 -8
- package/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +116 -60
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +15 -0
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +16 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m +4 -4
- package/WebDriverAgentLib/Commands/FBAlertViewCommands.m +10 -36
- package/WebDriverAgentLib/Commands/FBElementCommands.m +3 -3
- package/WebDriverAgentLib/FBAlert.h +43 -30
- package/WebDriverAgentLib/FBAlert.m +257 -91
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/Routing/FBExceptionHandler.m +8 -1
- package/WebDriverAgentLib/Routing/FBExceptions.h +9 -0
- package/WebDriverAgentLib/Routing/FBExceptions.m +3 -0
- package/WebDriverAgentLib/Routing/FBSession.m +11 -13
- package/WebDriverAgentLib/Utilities/FBAlertsMonitor.m +11 -9
- package/WebDriverAgentLib/Utilities/FBPasteboard.m +8 -4
- package/WebDriverAgentLib/Utilities/FBTVNavigationTracker-Private.h +10 -0
- package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.h +29 -4
- package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +62 -27
- package/WebDriverAgentTests/IntegrationApp_tvOS/AppDelegate.h +13 -0
- package/WebDriverAgentTests/IntegrationApp_tvOS/AppDelegate.m +26 -0
- package/WebDriverAgentTests/IntegrationApp_tvOS/Info.plist +41 -0
- package/WebDriverAgentTests/IntegrationApp_tvOS/SceneDelegate.h +15 -0
- package/WebDriverAgentTests/IntegrationApp_tvOS/SceneDelegate.m +22 -0
- package/WebDriverAgentTests/IntegrationApp_tvOS/ViewController.h +13 -0
- package/WebDriverAgentTests/IntegrationApp_tvOS/ViewController.m +79 -0
- package/WebDriverAgentTests/IntegrationApp_tvOS/main.m +17 -0
- package/WebDriverAgentTests/IntegrationTests/FBAlertTests.m +32 -51
- package/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m +9 -1
- package/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m +1 -1
- package/WebDriverAgentTests/IntegrationTests_tvOS/FBTVFocusIntegrationTests.m +84 -0
- package/WebDriverAgentTests/IntegrationTests_tvOS/Info.plist +24 -0
- package/WebDriverAgentTests/UnitTests_tvOS/Doubles/FBXCAccessibilityElementDouble.h +27 -0
- package/WebDriverAgentTests/UnitTests_tvOS/Doubles/FBXCAccessibilityElementDouble.m +23 -0
- package/WebDriverAgentTests/UnitTests_tvOS/Doubles/FBXCElementSnapshotDouble.h +43 -0
- package/WebDriverAgentTests/UnitTests_tvOS/Doubles/FBXCElementSnapshotDouble.m +24 -0
- package/WebDriverAgentTests/UnitTests_tvOS/FBTVNavigationTrackerTests.m +48 -0
- package/package.json +1 -1
|
@@ -69,60 +69,54 @@
|
|
|
69
69
|
|
|
70
70
|
- (void)testAlertPresence
|
|
71
71
|
{
|
|
72
|
-
|
|
73
|
-
XCTAssertFalse(alert.isPresent);
|
|
72
|
+
XCTAssertFalse([FBAlert alertWithApplication:self.testedApplication].isPresent);
|
|
74
73
|
[self showApplicationAlert];
|
|
75
|
-
XCTAssertTrue(
|
|
74
|
+
XCTAssertTrue([FBAlert alertWithApplication:self.testedApplication].isPresent);
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
- (void)testAlertText
|
|
79
78
|
{
|
|
80
|
-
|
|
81
|
-
XCTAssertNil(alert.text);
|
|
79
|
+
XCTAssertNil([FBAlert alertWithApplication:self.testedApplication].text);
|
|
82
80
|
[self showApplicationAlert];
|
|
83
|
-
|
|
84
|
-
XCTAssertTrue([
|
|
81
|
+
NSString *text = [FBAlert alertWithApplication:self.testedApplication].text;
|
|
82
|
+
XCTAssertTrue([text containsString:@"Magic"]);
|
|
83
|
+
XCTAssertTrue([text containsString:@"Should read"]);
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
- (void)testAlertLabels
|
|
88
87
|
{
|
|
89
|
-
|
|
90
|
-
XCTAssertNil(alert.buttonLabels);
|
|
88
|
+
XCTAssertNil([FBAlert alertWithApplication:self.testedApplication].buttonLabels);
|
|
91
89
|
[self showApplicationAlert];
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
NSArray *labels = [FBAlert alertWithApplication:self.testedApplication].buttonLabels;
|
|
91
|
+
XCTAssertNotNil(labels);
|
|
92
|
+
XCTAssertEqual(1, labels.count);
|
|
93
|
+
XCTAssertEqualObjects(@"Will do", labels[0]);
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
- (void)testClickAlertButton
|
|
98
97
|
{
|
|
99
|
-
|
|
100
|
-
XCTAssertFalse([alert clickAlertButton:@"Invalid" error:nil]);
|
|
98
|
+
XCTAssertThrows([[FBAlert alertWithApplication:self.testedApplication] clickAlertButton:@"Invalid"]);
|
|
101
99
|
[self showApplicationAlert];
|
|
102
|
-
|
|
103
|
-
FBAssertWaitTillBecomesTrue(
|
|
104
|
-
|
|
105
|
-
FBAssertWaitTillBecomesTrue(!
|
|
100
|
+
XCTAssertThrows([[FBAlert alertWithApplication:self.testedApplication] clickAlertButton:@"Invalid"]);
|
|
101
|
+
FBAssertWaitTillBecomesTrue([FBAlert alertWithApplication:self.testedApplication].isPresent);
|
|
102
|
+
XCTAssertNoThrow([[FBAlert alertWithApplication:self.testedApplication] clickAlertButton:@"Will do"]);
|
|
103
|
+
FBAssertWaitTillBecomesTrue(![FBAlert alertWithApplication:self.testedApplication].isPresent);
|
|
106
104
|
}
|
|
107
105
|
|
|
108
106
|
- (void)testAcceptingAlert
|
|
109
107
|
{
|
|
110
|
-
NSError *error;
|
|
111
108
|
[self showApplicationAlert];
|
|
112
|
-
|
|
109
|
+
XCTAssertNoThrow([[FBAlert alertWithApplication:self.testedApplication] accept]);
|
|
113
110
|
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
|
|
114
|
-
XCTAssertNil(error);
|
|
115
111
|
}
|
|
116
112
|
|
|
117
113
|
- (void)testAcceptingAlertWithCustomLocator
|
|
118
114
|
{
|
|
119
|
-
NSError *error;
|
|
120
115
|
[self showApplicationAlert];
|
|
121
116
|
[FBConfiguration setAcceptAlertButtonSelector:@"**/XCUIElementTypeButton[-1]"];
|
|
122
117
|
@try {
|
|
123
|
-
|
|
118
|
+
XCTAssertNoThrow([[FBAlert alertWithApplication:self.testedApplication] accept]);
|
|
124
119
|
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
|
|
125
|
-
XCTAssertNil(error);
|
|
126
120
|
} @finally {
|
|
127
121
|
[FBConfiguration setAcceptAlertButtonSelector:@""];
|
|
128
122
|
}
|
|
@@ -130,65 +124,52 @@
|
|
|
130
124
|
|
|
131
125
|
- (void)testDismissingAlert
|
|
132
126
|
{
|
|
133
|
-
NSError *error;
|
|
134
127
|
[self showApplicationAlert];
|
|
135
|
-
|
|
128
|
+
XCTAssertNoThrow([[FBAlert alertWithApplication:self.testedApplication] dismiss]);
|
|
136
129
|
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
|
|
137
|
-
XCTAssertNil(error);
|
|
138
130
|
}
|
|
139
131
|
|
|
140
132
|
- (void)testDismissingAlertWithCustomLocator
|
|
141
133
|
{
|
|
142
|
-
NSError *error;
|
|
143
134
|
[self showApplicationAlert];
|
|
144
135
|
[FBConfiguration setDismissAlertButtonSelector:@"**/XCUIElementTypeButton[-1]"];
|
|
145
136
|
@try {
|
|
146
|
-
|
|
137
|
+
XCTAssertNoThrow([[FBAlert alertWithApplication:self.testedApplication] dismiss]);
|
|
147
138
|
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
|
|
148
|
-
XCTAssertNil(error);
|
|
149
139
|
} @finally {
|
|
150
140
|
[FBConfiguration setDismissAlertButtonSelector:@""];
|
|
151
141
|
}
|
|
152
142
|
}
|
|
153
143
|
|
|
154
|
-
- (void)testAlertElement
|
|
155
|
-
{
|
|
156
|
-
[self showApplicationAlert];
|
|
157
|
-
XCUIElement *alertElement = [FBAlert alertWithApplication:self.testedApplication].alertElement;
|
|
158
|
-
XCTAssertTrue(alertElement.exists);
|
|
159
|
-
XCTAssertTrue(alertElement.elementType == XCUIElementTypeAlert);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
144
|
- (void)testNotificationAlert
|
|
163
145
|
{
|
|
164
|
-
|
|
165
|
-
XCTAssertNil(alert.text);
|
|
146
|
+
XCTAssertNil([FBAlert alertWithApplication:self.testedApplication].text);
|
|
166
147
|
[self.testedApplication.buttons[@"Create Notification Alert"] tap];
|
|
167
|
-
FBAssertWaitTillBecomesTrue(
|
|
148
|
+
FBAssertWaitTillBecomesTrue([FBAlert alertWithApplication:self.testedApplication].isPresent);
|
|
168
149
|
|
|
169
|
-
|
|
170
|
-
XCTAssertTrue([
|
|
150
|
+
NSString *text = [FBAlert alertWithApplication:self.testedApplication].text;
|
|
151
|
+
XCTAssertTrue([text containsString:@"Would Like to Send You Notifications"]);
|
|
152
|
+
XCTAssertTrue([text containsString:@"Notifications may include"]);
|
|
171
153
|
}
|
|
172
154
|
|
|
173
155
|
- (void)testCameraRollAlert
|
|
174
156
|
{
|
|
175
|
-
|
|
176
|
-
XCTAssertNil(alert.text);
|
|
157
|
+
XCTAssertNil([FBAlert alertWithApplication:self.testedApplication].text);
|
|
177
158
|
|
|
178
159
|
[self.testedApplication.buttons[@"Create Camera Roll Alert"] tap];
|
|
179
|
-
FBAssertWaitTillBecomesTrue(
|
|
160
|
+
FBAssertWaitTillBecomesTrue([FBAlert alertWithApplication:self.testedApplication].isPresent);
|
|
180
161
|
}
|
|
181
162
|
|
|
182
163
|
- (void)testGPSAccessAlert
|
|
183
164
|
{
|
|
184
|
-
|
|
185
|
-
XCTAssertNil(alert.text);
|
|
165
|
+
XCTAssertNil([FBAlert alertWithApplication:self.testedApplication].text);
|
|
186
166
|
|
|
187
167
|
[self.testedApplication.buttons[@"Create GPS access Alert"] tap];
|
|
188
|
-
FBAssertWaitTillBecomesTrue(
|
|
168
|
+
FBAssertWaitTillBecomesTrue([FBAlert alertWithApplication:self.testedApplication].isPresent);
|
|
189
169
|
|
|
190
|
-
|
|
191
|
-
XCTAssertTrue([
|
|
170
|
+
NSString *text = [FBAlert alertWithApplication:self.testedApplication].text;
|
|
171
|
+
XCTAssertTrue([text containsString:@"location"]);
|
|
172
|
+
XCTAssertTrue([text containsString:@"Yo Yo"]);
|
|
192
173
|
}
|
|
193
174
|
|
|
194
175
|
@end
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
#import "FBAlert.h"
|
|
12
12
|
#import "FBTestMacros.h"
|
|
13
|
+
#import "FBExceptions.h"
|
|
13
14
|
#import "FBIntegrationTestCase.h"
|
|
14
15
|
#import "FBConfiguration.h"
|
|
15
16
|
#import "FBMacros.h"
|
|
@@ -151,7 +152,14 @@ NSArray<NSString *> *const FBMainViewButtonLabels = @[
|
|
|
151
152
|
- (void)clearAlert
|
|
152
153
|
{
|
|
153
154
|
[self.testedApplication fb_waitUntilStable];
|
|
154
|
-
|
|
155
|
+
@try {
|
|
156
|
+
[[FBAlert alertWithApplication:self.testedApplication] dismiss];
|
|
157
|
+
} @catch (NSException *e) {
|
|
158
|
+
if (![e.name isEqualToString:FBAlertNotPresentException]) {
|
|
159
|
+
@throw e;
|
|
160
|
+
}
|
|
161
|
+
// No alert is present, nothing to clear
|
|
162
|
+
}
|
|
155
163
|
[self.testedApplication fb_waitUntilStable];
|
|
156
164
|
FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0);
|
|
157
165
|
}
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
XCTAssertEqualObjects(buttonLabels.firstObject, @"Close");
|
|
68
68
|
XCTAssertNotNil([self.safariApp fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@label='Close']"
|
|
69
69
|
shouldReturnAfterFirstMatch:YES].firstObject);
|
|
70
|
-
|
|
70
|
+
XCTAssertNoThrow([alert accept]);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
@end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import <XCTest/XCTest.h>
|
|
10
|
+
|
|
11
|
+
#if TARGET_OS_TV
|
|
12
|
+
|
|
13
|
+
// `XCUIElement+FBTVFocuse` is a project-internal category (not exposed as a
|
|
14
|
+
// Public framework header), so its two entry points are forward-declared
|
|
15
|
+
// here rather than imported. The real implementation - the one this suite
|
|
16
|
+
// exercises end to end against a live tvOS Simulator - is still the one
|
|
17
|
+
// linked in from WebDriverAgentLib_tvOS.framework.
|
|
18
|
+
@interface XCUIElement (FBTVFocuseForTesting)
|
|
19
|
+
- (BOOL)fb_setFocusWithError:(NSError **)error;
|
|
20
|
+
- (BOOL)fb_selectWithError:(NSError **)error;
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
@interface FBTVFocusIntegrationTests : XCTestCase
|
|
24
|
+
@property (nonatomic, strong) XCUIApplication *app;
|
|
25
|
+
@end
|
|
26
|
+
|
|
27
|
+
@implementation FBTVFocusIntegrationTests
|
|
28
|
+
|
|
29
|
+
- (void)setUp
|
|
30
|
+
{
|
|
31
|
+
[super setUp];
|
|
32
|
+
self.continueAfterFailure = NO;
|
|
33
|
+
self.app = [XCUIApplication new];
|
|
34
|
+
[self.app launch];
|
|
35
|
+
XCTAssertTrue([self.app.buttons[@"cell_0_0"] waitForExistenceWithTimeout:15]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
- (void)testSetFocusMovesFocusToADistantElement
|
|
39
|
+
{
|
|
40
|
+
XCUIElement *target = self.app.buttons[@"cell_2_2"];
|
|
41
|
+
XCTAssertTrue(target.exists);
|
|
42
|
+
XCTAssertFalse(target.hasFocus);
|
|
43
|
+
|
|
44
|
+
NSError *error;
|
|
45
|
+
BOOL result = [target fb_setFocusWithError:&error];
|
|
46
|
+
|
|
47
|
+
XCTAssertTrue(result);
|
|
48
|
+
XCTAssertNil(error);
|
|
49
|
+
XCTAssertTrue(target.hasFocus);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
- (void)testSelectMovesFocusAndTriggersTheElementsAction
|
|
53
|
+
{
|
|
54
|
+
XCUIElement *target = self.app.buttons[@"cell_1_2"];
|
|
55
|
+
XCUIElement *statusLabel = self.app.staticTexts[@"lastSelectedLabel"];
|
|
56
|
+
|
|
57
|
+
NSError *error;
|
|
58
|
+
BOOL result = [target fb_selectWithError:&error];
|
|
59
|
+
|
|
60
|
+
XCTAssertTrue(result);
|
|
61
|
+
XCTAssertNil(error);
|
|
62
|
+
XCTAssertTrue(target.hasFocus);
|
|
63
|
+
|
|
64
|
+
NSPredicate *labelUpdated = [NSPredicate predicateWithFormat:@"label == %@", @"cell_1_2"];
|
|
65
|
+
XCTNSPredicateExpectation *expectation = [[XCTNSPredicateExpectation alloc] initWithPredicate:labelUpdated object:statusLabel];
|
|
66
|
+
[self waitForExpectations:@[expectation] timeout:5];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
- (void)testSetFocusOnADisabledElementFails
|
|
70
|
+
{
|
|
71
|
+
XCUIElement *disabled = self.app.buttons[@"disabledButton"];
|
|
72
|
+
XCTAssertTrue(disabled.exists);
|
|
73
|
+
|
|
74
|
+
NSError *error;
|
|
75
|
+
BOOL result = [disabled fb_setFocusWithError:&error];
|
|
76
|
+
|
|
77
|
+
XCTAssertFalse(result);
|
|
78
|
+
XCTAssertNotNil(error);
|
|
79
|
+
XCTAssertFalse(disabled.hasFocus);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@end
|
|
83
|
+
|
|
84
|
+
#endif
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>en</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>com.facebook.wda.integrationTests.tvOS</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleName</key>
|
|
14
|
+
<string>$(PRODUCT_NAME)</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>BNDL</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>1.0</string>
|
|
19
|
+
<key>CFBundleSignature</key>
|
|
20
|
+
<string>????</string>
|
|
21
|
+
<key>CFBundleVersion</key>
|
|
22
|
+
<string>1</string>
|
|
23
|
+
</dict>
|
|
24
|
+
</plist>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import <Foundation/Foundation.h>
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
Minimal fake of the private `id<FBXCAccessibilityElement>` handle every
|
|
15
|
+
real snapshot carries, just enough for `FBElementUtils uidWithAccessibilityElement:`
|
|
16
|
+
to derive a stable, distinct `wdUID` per fake element id.
|
|
17
|
+
*/
|
|
18
|
+
@interface FBXCAccessibilityElementDouble : NSObject
|
|
19
|
+
|
|
20
|
+
@property (nonatomic, readonly) id payload;
|
|
21
|
+
@property (nonatomic, readonly) int processIdentifier;
|
|
22
|
+
|
|
23
|
+
- (instancetype)initWithElementId:(unsigned long long)elementId;
|
|
24
|
+
|
|
25
|
+
@end
|
|
26
|
+
|
|
27
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import "FBXCAccessibilityElementDouble.h"
|
|
10
|
+
|
|
11
|
+
@implementation FBXCAccessibilityElementDouble
|
|
12
|
+
|
|
13
|
+
- (instancetype)initWithElementId:(unsigned long long)elementId
|
|
14
|
+
{
|
|
15
|
+
self = [super init];
|
|
16
|
+
if (self) {
|
|
17
|
+
_payload = @{@"uid.elementID": @(elementId)};
|
|
18
|
+
_processIdentifier = 1;
|
|
19
|
+
}
|
|
20
|
+
return self;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import <Foundation/Foundation.h>
|
|
10
|
+
|
|
11
|
+
#import "FBXCAccessibilityElementDouble.h"
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
Fake `id<FBXCElementSnapshot>` leaf node. Deliberately does NOT declare
|
|
17
|
+
formal conformance to the (large, mostly-unrelated) `FBXCElementSnapshot`
|
|
18
|
+
protocol - it only implements the selectors
|
|
19
|
+
`FBTVNavigationTracker`'s `-directionTowardsTargetFromFocusedElementSnapshot:`
|
|
20
|
+
actually reads: `frame`, `hasFocus` and `accessibilityElement` (the latter
|
|
21
|
+
indirectly, via `FBXCElementSnapshotWrapper.wdUID`). Cast to
|
|
22
|
+
`id<FBXCElementSnapshot>` at the call site. Lets tests supply a fake focused
|
|
23
|
+
element snapshot without a live app/device.
|
|
24
|
+
*/
|
|
25
|
+
@interface FBXCElementSnapshotDouble : NSObject
|
|
26
|
+
|
|
27
|
+
@property (nonatomic, assign) CGRect frame;
|
|
28
|
+
@property (nonatomic, assign) BOOL hasFocus;
|
|
29
|
+
@property (nonatomic, strong, nullable) FBXCAccessibilityElementDouble *accessibilityElement;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
@param elementId Fake AX element id, used to derive a distinct `wdUID`
|
|
33
|
+
@param frame The snapshot's frame
|
|
34
|
+
@param hasFocus Whether this node should report `hasFocus == YES`
|
|
35
|
+
@return A snapshot double
|
|
36
|
+
*/
|
|
37
|
+
+ (instancetype)snapshotWithElementId:(unsigned long long)elementId
|
|
38
|
+
frame:(CGRect)frame
|
|
39
|
+
hasFocus:(BOOL)hasFocus;
|
|
40
|
+
|
|
41
|
+
@end
|
|
42
|
+
|
|
43
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import "FBXCElementSnapshotDouble.h"
|
|
10
|
+
|
|
11
|
+
@implementation FBXCElementSnapshotDouble
|
|
12
|
+
|
|
13
|
+
+ (instancetype)snapshotWithElementId:(unsigned long long)elementId
|
|
14
|
+
frame:(CGRect)frame
|
|
15
|
+
hasFocus:(BOOL)hasFocus
|
|
16
|
+
{
|
|
17
|
+
FBXCElementSnapshotDouble *snapshot = [self new];
|
|
18
|
+
snapshot.accessibilityElement = [[FBXCAccessibilityElementDouble alloc] initWithElementId:elementId];
|
|
19
|
+
snapshot.frame = frame;
|
|
20
|
+
snapshot.hasFocus = hasFocus;
|
|
21
|
+
return snapshot;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@end
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
#import <XCTest/XCTest.h>
|
|
10
|
+
#import <WebDriverAgentLib/FBXCElementSnapshot.h>
|
|
10
11
|
|
|
11
12
|
#import "XCUIElementDouble.h"
|
|
13
|
+
#import "FBXCElementSnapshotDouble.h"
|
|
12
14
|
#import "FBTVNavigationTracker.h"
|
|
13
15
|
#import "FBTVNavigationTracker-Private.h"
|
|
14
16
|
|
|
@@ -83,4 +85,50 @@
|
|
|
83
85
|
XCTAssertEqual(FBTVDirectionNone, direction);
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
#pragma mark - directionTowardsTargetFromFocusedElementSnapshot:
|
|
89
|
+
|
|
90
|
+
- (FBTVNavigationTracker *)trackerWithTargetFrame:(CGRect)targetFrame
|
|
91
|
+
{
|
|
92
|
+
XCUIElementDouble *targetElement = XCUIElementDouble.new;
|
|
93
|
+
targetElement.wdFrame = targetFrame;
|
|
94
|
+
return [FBTVNavigationTracker trackerWithTargetElement:(XCUIElement *)targetElement];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
- (void)testDirectionTowardsTargetFromFocusedElementSnapshotShouldPointRight
|
|
98
|
+
{
|
|
99
|
+
// Target sits to the right of the currently focused element.
|
|
100
|
+
FBTVNavigationTracker *tracker = [self trackerWithTargetFrame:CGRectMake(100, 0, 0, 0)];
|
|
101
|
+
FBXCElementSnapshotDouble *focusedSnapshot = [FBXCElementSnapshotDouble snapshotWithElementId:1 frame:CGRectMake(0, 0, 0, 0) hasFocus:YES];
|
|
102
|
+
|
|
103
|
+
FBTVDirection direction = [tracker directionTowardsTargetFromFocusedElementSnapshot:(id<FBXCElementSnapshot>)focusedSnapshot];
|
|
104
|
+
|
|
105
|
+
XCTAssertEqual(FBTVDirectionRight, direction);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
- (void)testDirectionTowardsTargetFromFocusedElementSnapshotShouldPointUp
|
|
109
|
+
{
|
|
110
|
+
// Target sits above the currently focused element.
|
|
111
|
+
FBTVNavigationTracker *tracker = [self trackerWithTargetFrame:CGRectMake(0, -100, 0, 0)];
|
|
112
|
+
FBXCElementSnapshotDouble *focusedSnapshot = [FBXCElementSnapshotDouble snapshotWithElementId:1 frame:CGRectMake(0, 0, 0, 0) hasFocus:YES];
|
|
113
|
+
|
|
114
|
+
FBTVDirection direction = [tracker directionTowardsTargetFromFocusedElementSnapshot:(id<FBXCElementSnapshot>)focusedSnapshot];
|
|
115
|
+
|
|
116
|
+
XCTAssertEqual(FBTVDirectionUp, direction);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
- (void)testDirectionTowardsTargetFromFocusedElementSnapshotShouldNotSuggestTheSameDirectionTwiceInARow
|
|
120
|
+
{
|
|
121
|
+
// Same (unmoved) focused snapshot polled twice: the horizontal move gets
|
|
122
|
+
// suggested once, then withheld on the next call, per the "don't repeat a
|
|
123
|
+
// direction" bookkeeping in -directionWithItem:delta:positiveDirection:negativeDirection:.
|
|
124
|
+
FBTVNavigationTracker *tracker = [self trackerWithTargetFrame:CGRectMake(100, 0, 0, 0)];
|
|
125
|
+
FBXCElementSnapshotDouble *focusedSnapshot = [FBXCElementSnapshotDouble snapshotWithElementId:1 frame:CGRectMake(0, 0, 0, 0) hasFocus:YES];
|
|
126
|
+
|
|
127
|
+
FBTVDirection firstDirection = [tracker directionTowardsTargetFromFocusedElementSnapshot:(id<FBXCElementSnapshot>)focusedSnapshot];
|
|
128
|
+
XCTAssertEqual(FBTVDirectionRight, firstDirection);
|
|
129
|
+
|
|
130
|
+
FBTVDirection secondDirection = [tracker directionTowardsTargetFromFocusedElementSnapshot:(id<FBXCElementSnapshot>)focusedSnapshot];
|
|
131
|
+
XCTAssertEqual(FBTVDirectionNone, secondDirection);
|
|
132
|
+
}
|
|
133
|
+
|
|
86
134
|
@end
|