appium-webdriveragent 16.4.0 → 16.5.0
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 +6 -0
- package/Scripts/build-webdriveragent.mjs +9 -9
- package/Scripts/build.sh +8 -1
- package/WebDriverAgent.xcodeproj/project.pbxproj +125 -107
- package/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/IntegrationTests_watchOS.xcscheme +4 -4
- package/WebDriverAgentLib/FBAlert.m +8 -6
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentTests/IntegrationTests_watchOS/IntegrationTests_watchOS-Bridging-Header.h +21 -0
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAAlertIntegrationTests.swift +11 -9
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAAppLifecycleIntegrationTests.swift +18 -38
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAClickIntegrationTests.swift +11 -17
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDADeviceIntegrationTests.swift +50 -71
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAElementAttributeIntegrationTests.swift +23 -41
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAFindIntegrationTests.swift +70 -95
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAScreenshotAndSourceIntegrationTests.swift +24 -22
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDATypingIntegrationTests.swift +44 -28
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAWatchInProcessTestCase.swift +51 -0
- package/build/lib/check-dependencies.d.ts.map +1 -1
- package/build/lib/check-dependencies.js +21 -7
- package/build/lib/check-dependencies.js.map +1 -1
- package/build/lib/constants.d.ts +1 -2
- package/build/lib/constants.d.ts.map +1 -1
- package/build/lib/constants.js +1 -2
- package/build/lib/constants.js.map +1 -1
- package/build/lib/types.d.ts +2 -2
- package/build/lib/types.d.ts.map +1 -1
- package/build/lib/utils/index.d.ts +1 -1
- package/build/lib/utils/index.d.ts.map +1 -1
- package/build/lib/utils/index.js +1 -1
- package/build/lib/utils/index.js.map +1 -1
- package/build/lib/utils/platform.d.ts +12 -0
- package/build/lib/utils/platform.d.ts.map +1 -1
- package/build/lib/utils/platform.js +23 -1
- package/build/lib/utils/platform.js.map +1 -1
- package/build/lib/utils/xctestrun.js +27 -3
- package/build/lib/utils/xctestrun.js.map +1 -1
- package/build/lib/webdriveragent.d.ts.map +1 -1
- package/build/lib/webdriveragent.js +4 -1
- package/build/lib/webdriveragent.js.map +1 -1
- package/build/lib/xcodebuild.d.ts.map +1 -1
- package/build/lib/xcodebuild.js +19 -9
- package/build/lib/xcodebuild.js.map +1 -1
- package/lib/check-dependencies.ts +23 -7
- package/lib/constants.ts +1 -2
- package/lib/types.ts +4 -2
- package/lib/utils/index.ts +1 -1
- package/lib/utils/platform.ts +25 -1
- package/lib/utils/xctestrun.ts +29 -3
- package/lib/webdriveragent.ts +5 -1
- package/lib/xcodebuild.ts +27 -12
- package/package.json +3 -2
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDASessionIntegrationTests.swift +0 -72
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAUnknownCommandIntegrationTests.swift +0 -24
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAWatchHTTPClient.swift +0 -95
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAWatchIntegrationTestCase.swift +0 -61
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
buildForAnalyzing = "NO">
|
|
15
15
|
<BuildableReference
|
|
16
16
|
BuildableIdentifier = "primary"
|
|
17
|
-
BlueprintIdentifier = "
|
|
17
|
+
BlueprintIdentifier = "5D9539D7055B5E6EED56D100"
|
|
18
18
|
BuildableName = "IntegrationTests_watchOS.xctest"
|
|
19
19
|
BlueprintName = "IntegrationTests_watchOS"
|
|
20
20
|
ReferencedContainer = "container:WebDriverAgent.xcodeproj">
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
skipped = "NO">
|
|
33
33
|
<BuildableReference
|
|
34
34
|
BuildableIdentifier = "primary"
|
|
35
|
-
BlueprintIdentifier = "
|
|
35
|
+
BlueprintIdentifier = "5D9539D7055B5E6EED56D100"
|
|
36
36
|
BuildableName = "IntegrationTests_watchOS.xctest"
|
|
37
37
|
BlueprintName = "IntegrationTests_watchOS"
|
|
38
38
|
ReferencedContainer = "container:WebDriverAgent.xcodeproj">
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<MacroExpansion>
|
|
54
54
|
<BuildableReference
|
|
55
55
|
BuildableIdentifier = "primary"
|
|
56
|
-
BlueprintIdentifier = "
|
|
56
|
+
BlueprintIdentifier = "5D9539D7055B5E6EED56D100"
|
|
57
57
|
BuildableName = "IntegrationTests_watchOS.xctest"
|
|
58
58
|
BlueprintName = "IntegrationTests_watchOS"
|
|
59
59
|
ReferencedContainer = "container:WebDriverAgent.xcodeproj">
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
<MacroExpansion>
|
|
70
70
|
<BuildableReference
|
|
71
71
|
BuildableIdentifier = "primary"
|
|
72
|
-
BlueprintIdentifier = "
|
|
72
|
+
BlueprintIdentifier = "5D9539D7055B5E6EED56D100"
|
|
73
73
|
BuildableName = "IntegrationTests_watchOS.xctest"
|
|
74
74
|
BlueprintName = "IntegrationTests_watchOS"
|
|
75
75
|
ReferencedContainer = "container:WebDriverAgent.xcodeproj">
|
|
@@ -236,17 +236,18 @@
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
XCUIElement *acceptButton = nil;
|
|
239
|
-
|
|
239
|
+
NSString *acceptAlertButtonSelector = FBConfiguration.sharedInstance.acceptAlertButtonSelector ?: @"";
|
|
240
|
+
if (acceptAlertButtonSelector.length) {
|
|
240
241
|
NSString *errorReason = nil;
|
|
241
242
|
@try {
|
|
242
|
-
acceptButton = [[alertElement fb_descendantsMatchingClassChain:
|
|
243
|
+
acceptButton = [[alertElement fb_descendantsMatchingClassChain:acceptAlertButtonSelector
|
|
243
244
|
shouldReturnAfterFirstMatch:YES] firstObject];
|
|
244
245
|
} @catch (NSException *ex) {
|
|
245
246
|
errorReason = ex.reason;
|
|
246
247
|
}
|
|
247
248
|
if (nil == acceptButton) {
|
|
248
249
|
[FBLogger logFmt:@"Cannot find any match for Accept alert button using the class chain selector '%@'",
|
|
249
|
-
|
|
250
|
+
acceptAlertButtonSelector];
|
|
250
251
|
if (nil != errorReason) {
|
|
251
252
|
[FBLogger logFmt:@"Original error: %@", errorReason];
|
|
252
253
|
}
|
|
@@ -293,17 +294,18 @@
|
|
|
293
294
|
}
|
|
294
295
|
|
|
295
296
|
XCUIElement *dismissButton = nil;
|
|
296
|
-
|
|
297
|
+
NSString *dismissAlertButtonSelector = FBConfiguration.sharedInstance.dismissAlertButtonSelector ?: @"";
|
|
298
|
+
if (dismissAlertButtonSelector.length) {
|
|
297
299
|
NSString *errorReason = nil;
|
|
298
300
|
@try {
|
|
299
|
-
dismissButton = [[alertElement fb_descendantsMatchingClassChain:
|
|
301
|
+
dismissButton = [[alertElement fb_descendantsMatchingClassChain:dismissAlertButtonSelector
|
|
300
302
|
shouldReturnAfterFirstMatch:YES] firstObject];
|
|
301
303
|
} @catch (NSException *ex) {
|
|
302
304
|
errorReason = ex.reason;
|
|
303
305
|
}
|
|
304
306
|
if (nil == dismissButton) {
|
|
305
307
|
[FBLogger logFmt:@"Cannot find any match for Dismiss alert button using the class chain selector '%@'",
|
|
306
|
-
|
|
308
|
+
dismissAlertButtonSelector];
|
|
307
309
|
if (nil != errorReason) {
|
|
308
310
|
[FBLogger logFmt:@"Original error: %@", errorReason];
|
|
309
311
|
}
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<key>CFBundlePackageType</key>
|
|
16
16
|
<string>FMWK</string>
|
|
17
17
|
<key>CFBundleShortVersionString</key>
|
|
18
|
-
<string>16.
|
|
18
|
+
<string>16.5.0</string>
|
|
19
19
|
<key>CFBundleSignature</key>
|
|
20
20
|
<string>????</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>16.
|
|
22
|
+
<string>16.5.0</string>
|
|
23
23
|
<key>NSPrincipalClass</key>
|
|
24
24
|
<string/>
|
|
25
25
|
</dict>
|
package/WebDriverAgentTests/IntegrationTests_watchOS/IntegrationTests_watchOS-Bridging-Header.h
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
// Exposes the WebDriverAgentLib_watchOS categories these tests call directly, in-process,
|
|
10
|
+
// instead of going through the HTTP server.
|
|
11
|
+
|
|
12
|
+
#import "XCUIElement+FBFind.h"
|
|
13
|
+
#import "XCUIElement+FBClassChain.h"
|
|
14
|
+
#import "XCUIElement+FBIsVisible.h"
|
|
15
|
+
#import "XCUIElement+FBUtilities.h"
|
|
16
|
+
#import "XCUIElement+FBWebDriverAttributes.h"
|
|
17
|
+
#import "XCUIElement+FBTyping.h"
|
|
18
|
+
#import "XCUIApplication+FBHelpers.h"
|
|
19
|
+
#import "XCUIDevice+FBHelpers.h"
|
|
20
|
+
#import "FBAlert.h"
|
|
21
|
+
#import "FBElement.h"
|
|
@@ -8,16 +8,18 @@
|
|
|
8
8
|
|
|
9
9
|
import XCTest
|
|
10
10
|
|
|
11
|
-
/// Covers
|
|
12
|
-
/// so this only exercises the "no alert open"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
/// Covers FBAlert's no-alert-present behavior directly, in-process. IntegrationApp_watchOS never
|
|
12
|
+
/// presents a real alert, so this only exercises the "no alert open" path (`text`/`buttonLabels`
|
|
13
|
+
/// both just return nil - no HTTP-error-style throw at this layer), not the success path.
|
|
14
|
+
final class WDAAlertIntegrationTests: WDAWatchInProcessTestCase {
|
|
15
|
+
// All reads, no taps/typing - reuse the same running app across the whole class.
|
|
16
|
+
override class var relaunchForEachTest: Bool { false }
|
|
17
|
+
|
|
18
|
+
func testAlertTextWithNoAlertPresentReturnsNil() {
|
|
19
|
+
XCTAssertNil(FBAlert(application: app).text())
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
func
|
|
20
|
-
|
|
21
|
-
XCTAssertNotEqual(response.statusCode, 200)
|
|
22
|
+
func testAlertButtonsWithNoAlertPresentReturnsNil() {
|
|
23
|
+
XCTAssertNil(FBAlert(application: app).buttonLabels())
|
|
22
24
|
}
|
|
23
25
|
}
|
|
@@ -8,50 +8,30 @@
|
|
|
8
8
|
|
|
9
9
|
import XCTest
|
|
10
10
|
|
|
11
|
-
/// Covers the app lifecycle routes (launch/activate/terminate/state/list).
|
|
12
|
-
///
|
|
13
|
-
///
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
let response = try client.get("/session/\(sessionId!)/wda/apps/list")
|
|
21
|
-
XCTAssertEqual(response.statusCode, 200)
|
|
22
|
-
guard let apps = response.value as? [[String: Any]] else {
|
|
23
|
-
return XCTFail("Expected an array of active apps: \(String(describing: response.json))")
|
|
24
|
-
}
|
|
25
|
-
XCTAssertTrue(apps.contains { $0["bundleId"] as? String == Self.integrationAppBundleId })
|
|
11
|
+
/// Covers the app lifecycle routes (launch/activate/terminate/state/list). FBSession's
|
|
12
|
+
/// implementations of these are themselves thin wrappers over plain XCTest XCUIApplication
|
|
13
|
+
/// APIs (see FBSession.m), so this calls `.launch()`/`.activate()`/`.terminate()`/`.state`
|
|
14
|
+
/// directly instead of going through the HTTP server; only the apps-list route has a real WDA
|
|
15
|
+
/// category behind it (`+fb_activeAppsInfo`).
|
|
16
|
+
final class WDAAppLifecycleIntegrationTests: WDAWatchInProcessTestCase {
|
|
17
|
+
func testAppsListIncludesTheAppUnderTest() {
|
|
18
|
+
let apps = XCUIApplication.fb_activeAppsInfo()
|
|
19
|
+
XCTAssertTrue(apps.contains { $0["bundleId"] as? String == WDAWatchInProcessTestCase.integrationAppBundleId })
|
|
26
20
|
}
|
|
27
21
|
|
|
28
|
-
func testTerminateThenRelaunchLifecycle()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
let terminateResponse = try client.post("/session/\(sessionId!)/wda/apps/terminate", body: ["bundleId": bundleId])
|
|
32
|
-
XCTAssertEqual(terminateResponse.statusCode, 200)
|
|
33
|
-
XCTAssertEqual(terminateResponse.value as? Bool, true)
|
|
34
|
-
|
|
35
|
-
let stateAfterTerminate = try client.post("/session/\(sessionId!)/wda/apps/state", body: ["bundleId": bundleId])
|
|
36
|
-
XCTAssertEqual(stateAfterTerminate.value as? Int, Self.notRunningState)
|
|
22
|
+
func testTerminateThenRelaunchLifecycle() {
|
|
23
|
+
app.terminate()
|
|
24
|
+
XCTAssertEqual(app.state, .notRunning)
|
|
37
25
|
|
|
38
|
-
|
|
39
|
-
XCTAssertEqual(
|
|
40
|
-
Thread.sleep(forTimeInterval: 1)
|
|
41
|
-
|
|
42
|
-
let stateAfterLaunch = try client.post("/session/\(sessionId!)/wda/apps/state", body: ["bundleId": bundleId])
|
|
43
|
-
XCTAssertEqual(stateAfterLaunch.value as? Int, Self.runningForegroundState)
|
|
26
|
+
app.launch()
|
|
27
|
+
XCTAssertEqual(app.state, .runningForeground)
|
|
44
28
|
|
|
45
29
|
// The app relaunched fresh, so its accessibility tree should be back too.
|
|
46
|
-
|
|
30
|
+
XCTAssertTrue(app.buttons["tapMeButton"].waitForExistence(timeout: 15))
|
|
47
31
|
}
|
|
48
32
|
|
|
49
|
-
func testActivateBringsTheAppToTheForeground()
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
XCTAssertEqual(activateResponse.statusCode, 200)
|
|
53
|
-
|
|
54
|
-
let stateResponse = try client.post("/session/\(sessionId!)/wda/apps/state", body: ["bundleId": bundleId])
|
|
55
|
-
XCTAssertEqual(stateResponse.value as? Int, Self.runningForegroundState)
|
|
33
|
+
func testActivateBringsTheAppToTheForeground() {
|
|
34
|
+
app.activate()
|
|
35
|
+
XCTAssertEqual(app.state, .runningForeground)
|
|
56
36
|
}
|
|
57
37
|
}
|
|
@@ -8,24 +8,18 @@
|
|
|
8
8
|
|
|
9
9
|
import XCTest
|
|
10
10
|
|
|
11
|
-
/// Covers /element/:uuid/click
|
|
12
|
-
/// (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
/// Covers /element/:uuid/click, which on watchOS (like iOS) is just standard XCTest `-tap`
|
|
12
|
+
/// (see FBElementCommands.handleClick:) - so this just calls `.tap()` directly, the same way
|
|
13
|
+
/// the iOS/tvOS integration tests do. The "click a nonexistent element UUID" case isn't a `tap`
|
|
14
|
+
/// behavior at all (it's FBElementCache's UUID-lookup failure), so it's covered by the HTTP
|
|
15
|
+
/// end-to-end tests instead, where there's an actual UUID/route layer to miss against.
|
|
16
|
+
final class WDAClickIntegrationTests: WDAWatchInProcessTestCase {
|
|
17
|
+
func testClickingButtonUpdatesTheResultLabel() {
|
|
18
|
+
let label = app.staticTexts["resultLabel"]
|
|
19
|
+
XCTAssertEqual(label.wdValue ?? label.wdLabel, "Idle")
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
let clickResponse = try client.post("/session/\(sessionId!)/element/\(buttonId)/click")
|
|
20
|
-
XCTAssertEqual(clickResponse.statusCode, 200)
|
|
21
|
+
app.buttons["tapMeButton"].tap()
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
let updatedLabelId = try findElement(byAccessibilityId: "resultLabel")
|
|
24
|
-
XCTAssertEqual(try attributeValue(updatedLabelId, "label"), "Tapped")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
func testClickingAnElementThatDoesNotExistReturnsAnError() throws {
|
|
28
|
-
let response = try client.post("/session/\(sessionId!)/element/00000000-0000-0000-0000-000000000000/click")
|
|
29
|
-
XCTAssertNotEqual(response.statusCode, 200)
|
|
23
|
+
XCTAssertEqual(label.wdValue ?? label.wdLabel, "Tapped")
|
|
30
24
|
}
|
|
31
25
|
}
|
|
@@ -6,46 +6,37 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import CoreLocation
|
|
10
|
+
import WatchKit
|
|
9
11
|
import XCTest
|
|
10
12
|
|
|
11
|
-
/// Covers device-info
|
|
12
|
-
///
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
XCTAssertFalse((
|
|
13
|
+
/// Covers device-info, active-app-info, simulated location, digital crown rotation, and hand
|
|
14
|
+
/// gesture, calling the same underlying APIs FBCustomCommands/XCUIDevice+FBHelpers use directly
|
|
15
|
+
/// in-process. The real (non-simulated) GPS location route and the two pure argument-validation
|
|
16
|
+
/// cases (missing delta/gesture name, rejected before any category method is even called) aren't
|
|
17
|
+
/// WDA category behavior, so they're not covered here.
|
|
18
|
+
final class WDADeviceIntegrationTests: WDAWatchInProcessTestCase {
|
|
19
|
+
func testDeviceInfo() {
|
|
20
|
+
XCTAssertFalse(WKInterfaceDevice.current().name.isEmpty)
|
|
21
|
+
XCTAssertFalse(WKInterfaceDevice.current().model.isEmpty)
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
func testActiveAppInfo()
|
|
22
|
-
let
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
XCTAssertGreaterThan(
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
func testDeviceLocation() throws {
|
|
29
|
-
let response = try client.get("/session/\(sessionId!)/wda/device/location")
|
|
30
|
-
XCTAssertEqual(response.statusCode, 200)
|
|
31
|
-
XCTAssertNotNil(response.valueDict?["latitude"])
|
|
32
|
-
XCTAssertNotNil(response.valueDict?["authorizationStatus"])
|
|
24
|
+
func testActiveAppInfo() {
|
|
25
|
+
let apps = XCUIApplication.fb_activeAppsInfo()
|
|
26
|
+
let ourApp = apps.first { $0["bundleId"] as? String == WDAWatchInProcessTestCase.integrationAppBundleId }
|
|
27
|
+
XCTAssertNotNil(ourApp)
|
|
28
|
+
XCTAssertGreaterThan(ourApp?["pid"] as? Int ?? 0, 0)
|
|
33
29
|
}
|
|
34
30
|
|
|
35
31
|
func testSimulatedLocationRoundTrip() throws {
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
"longitude": -122.0322,
|
|
39
|
-
])
|
|
40
|
-
XCTAssertEqual(setResponse.statusCode, 200)
|
|
32
|
+
let location = CLLocation(latitude: 37.3230, longitude: -122.0322)
|
|
33
|
+
try XCUIDevice.shared.fb_setSimulatedLocation(location)
|
|
41
34
|
|
|
42
|
-
let
|
|
43
|
-
XCTAssertEqual(
|
|
44
|
-
XCTAssertEqual(
|
|
45
|
-
XCTAssertEqual(getResponse.valueDict?["longitude"] as? Double ?? 0, -122.0322, accuracy: 0.001)
|
|
35
|
+
let fetched = try XCUIDevice.shared.fb_getSimulatedLocation()
|
|
36
|
+
XCTAssertEqual(fetched.coordinate.latitude, 37.3230, accuracy: 0.001)
|
|
37
|
+
XCTAssertEqual(fetched.coordinate.longitude, -122.0322, accuracy: 0.001)
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
XCTAssertEqual(clearResponse.statusCode, 200)
|
|
39
|
+
try XCUIDevice.shared.fb_clearSimulatedLocation()
|
|
49
40
|
}
|
|
50
41
|
|
|
51
42
|
/// rotateDigitalCrownByDelta:/performHandGesture: were only added to the SDK in Xcode 16.3 - WDA calls
|
|
@@ -53,61 +44,49 @@ final class WDADeviceIntegrationTests: WDAWatchIntegrationTestCase {
|
|
|
53
44
|
/// when the toolchain that built this very test bundle (same build as the runner) is new enough. Checked
|
|
54
45
|
/// the same way WDA itself does, via responds(to:), rather than hardcoding an Xcode/OS version number here.
|
|
55
46
|
private var supportsDigitalCrownAndHandGesture: Bool {
|
|
56
|
-
XCUIDevice.shared.responds(to:
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
func testRotateDigitalCrown() throws {
|
|
60
|
-
let response = try client.post("/session/\(sessionId!)/wda/rotateDigitalCrown", body: [
|
|
61
|
-
"delta": 0.2,
|
|
62
|
-
"velocity": 1.0,
|
|
63
|
-
])
|
|
64
|
-
XCTAssertEqual(response.statusCode, supportsDigitalCrownAndHandGesture ? 200 : 500)
|
|
47
|
+
XCUIDevice.shared.responds(to: NSSelectorFromString("rotateDigitalCrownByDelta:"))
|
|
65
48
|
}
|
|
66
49
|
|
|
67
|
-
func
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
50
|
+
private func assertSucceeds(_ expectedToSucceed: Bool, file: StaticString = #filePath, line: UInt = #line, _ body: () throws -> Void) {
|
|
51
|
+
do {
|
|
52
|
+
try body()
|
|
53
|
+
XCTAssertTrue(expectedToSucceed, "expected this to throw, but it didn't", file: file, line: line)
|
|
54
|
+
} catch {
|
|
55
|
+
XCTAssertFalse(expectedToSucceed, "expected this to succeed, but it threw \(error)", file: file, line: line)
|
|
56
|
+
}
|
|
72
57
|
}
|
|
73
58
|
|
|
74
|
-
func
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
59
|
+
func testRotateDigitalCrown() {
|
|
60
|
+
assertSucceeds(supportsDigitalCrownAndHandGesture) {
|
|
61
|
+
try XCUIDevice.shared.fb_rotateDigitalCrown(0.2, velocity: 1.0)
|
|
62
|
+
}
|
|
78
63
|
}
|
|
79
64
|
|
|
80
|
-
func testPerformHandGestureDoubleTap()
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
XCTAssertEqual(response.statusCode, supportsDigitalCrownAndHandGesture ? 200 : 500)
|
|
65
|
+
func testPerformHandGestureDoubleTap() {
|
|
66
|
+
assertSucceeds(supportsDigitalCrownAndHandGesture) {
|
|
67
|
+
try XCUIDevice.shared.fb_performHandGesture("doubleTap")
|
|
68
|
+
}
|
|
85
69
|
}
|
|
86
70
|
|
|
87
|
-
func testPerformHandGestureFlick()
|
|
88
|
-
let response = try client.post("/session/\(sessionId!)/wda/performHandGesture", body: [
|
|
89
|
-
"name": "flick",
|
|
90
|
-
])
|
|
71
|
+
func testPerformHandGestureFlick() {
|
|
91
72
|
// flick additionally needs watchOS 26+ (still internally versioned 12.0 pre-rename) on top of the
|
|
92
73
|
// Xcode 16.3+ toolchain floor - below that OS version it isn't even advertised as a supported name,
|
|
93
74
|
// so the server rejects it the same way it would reject any other unknown gesture name.
|
|
94
|
-
|
|
95
|
-
|
|
75
|
+
let shouldSucceed: Bool
|
|
76
|
+
if #available(watchOS 12.0, *) {
|
|
77
|
+
shouldSucceed = supportsDigitalCrownAndHandGesture
|
|
96
78
|
} else {
|
|
97
|
-
|
|
79
|
+
shouldSucceed = false
|
|
80
|
+
}
|
|
81
|
+
assertSucceeds(shouldSucceed) {
|
|
82
|
+
try XCUIDevice.shared.fb_performHandGesture("flick")
|
|
98
83
|
}
|
|
99
84
|
}
|
|
100
85
|
|
|
101
|
-
func testPerformHandGestureUnsupportedName()
|
|
86
|
+
func testPerformHandGestureUnsupportedName() {
|
|
102
87
|
// Not a real gesture name in any environment, so always rejected regardless of toolchain/OS version.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
XCTAssertEqual(response.statusCode, 500)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
func testPerformHandGestureMissingName() throws {
|
|
110
|
-
let response = try client.post("/session/\(sessionId!)/wda/performHandGesture")
|
|
111
|
-
XCTAssertEqual(response.statusCode, 400)
|
|
88
|
+
assertSucceeds(false) {
|
|
89
|
+
try XCUIDevice.shared.fb_performHandGesture("clench")
|
|
90
|
+
}
|
|
112
91
|
}
|
|
113
92
|
}
|
package/WebDriverAgentTests/IntegrationTests_watchOS/WDAElementAttributeIntegrationTests.swift
CHANGED
|
@@ -8,50 +8,32 @@
|
|
|
8
8
|
|
|
9
9
|
import XCTest
|
|
10
10
|
|
|
11
|
-
/// Covers
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
XCTAssertGreaterThan(rectResponse.valueDict?["width"] as? Double ?? 0, 0)
|
|
11
|
+
/// Covers the FBElement attribute properties (wdEnabled/wdVisible/wdRect/wdType/wdLabel/
|
|
12
|
+
/// wdSelected/wdAccessible/fb_valueForWDAttributeName:) directly, in-process - the same
|
|
13
|
+
/// properties FBElementCommands' attribute routes read from.
|
|
14
|
+
final class WDAElementAttributeIntegrationTests: WDAWatchInProcessTestCase {
|
|
15
|
+
// All reads, no taps/typing - reuse the same running app across the whole class.
|
|
16
|
+
override class var relaunchForEachTest: Bool { false }
|
|
17
|
+
|
|
18
|
+
func testWindowSizeAndRect() {
|
|
19
|
+
XCTAssertGreaterThan(app.wdFrame.width, 0)
|
|
20
|
+
XCTAssertGreaterThan(app.wdFrame.height, 0)
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
func testButtonAttributes()
|
|
25
|
-
let
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
XCTAssertEqual(
|
|
32
|
-
|
|
33
|
-
let rectResponse = try client.get("/session/\(sessionId!)/element/\(buttonId)/rect")
|
|
34
|
-
XCTAssertEqual(rectResponse.statusCode, 200)
|
|
35
|
-
XCTAssertGreaterThan(rectResponse.valueDict?["width"] as? Double ?? 0, 0)
|
|
36
|
-
|
|
37
|
-
let nameResponse = try client.get("/session/\(sessionId!)/element/\(buttonId)/name")
|
|
38
|
-
XCTAssertEqual(nameResponse.valueString, "XCUIElementTypeButton")
|
|
39
|
-
|
|
40
|
-
let labelResponse = try client.get("/session/\(sessionId!)/element/\(buttonId)/attribute/label")
|
|
41
|
-
XCTAssertEqual(labelResponse.valueString, "Tap Me")
|
|
42
|
-
|
|
43
|
-
let accessibleResponse = try client.get("/session/\(sessionId!)/wda/element/\(buttonId)/accessible")
|
|
44
|
-
XCTAssertEqual(accessibleResponse.statusCode, 200)
|
|
23
|
+
func testButtonAttributes() {
|
|
24
|
+
let button = app.buttons["tapMeButton"]
|
|
25
|
+
XCTAssertTrue(button.isWDEnabled)
|
|
26
|
+
XCTAssertTrue(button.isWDVisible)
|
|
27
|
+
XCTAssertGreaterThan(button.wdRect["width"] as? Double ?? 0, 0)
|
|
28
|
+
XCTAssertEqual(button.wdType, "XCUIElementTypeButton")
|
|
29
|
+
XCTAssertEqual(button.wdLabel, "Tap Me")
|
|
30
|
+
XCTAssertEqual(button.fb_value(forWDAttributeName: "label") as? String, "Tap Me")
|
|
31
|
+
XCTAssertTrue(button.isWDAccessible)
|
|
45
32
|
}
|
|
46
33
|
|
|
47
|
-
func testResultLabelTextAndSelectedState()
|
|
48
|
-
let
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
XCTAssertEqual(textResponse.valueString, "Idle")
|
|
52
|
-
|
|
53
|
-
let selectedResponse = try client.get("/session/\(sessionId!)/element/\(labelId)/selected")
|
|
54
|
-
XCTAssertEqual(selectedResponse.statusCode, 200)
|
|
55
|
-
XCTAssertEqual(selectedResponse.value as? Bool, false)
|
|
34
|
+
func testResultLabelTextAndSelectedState() {
|
|
35
|
+
let label = app.staticTexts["resultLabel"]
|
|
36
|
+
XCTAssertEqual(label.wdValue ?? label.wdLabel, "Idle")
|
|
37
|
+
XCTAssertFalse(label.isWDSelected)
|
|
56
38
|
}
|
|
57
39
|
}
|