appium-webdriveragent 16.12.7 → 16.12.8
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/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +5 -13
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/Utilities/FBMathUtils.h +25 -0
- package/WebDriverAgentLib/Utilities/FBMathUtils.m +21 -0
- package/WebDriverAgentTests/UnitTests/FBMathUtilsTests.m +38 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [16.12.8](https://github.com/appium/WebDriverAgent/compare/v16.12.7...v16.12.8) (2026-09-11)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* use wdFrame instead of raw frame for scroll gesture anchor ([#1256](https://github.com/appium/WebDriverAgent/issues/1256)) ([9ada9fd](https://github.com/appium/WebDriverAgent/commit/9ada9fd4077796b7c1002292c21ec9e45fab4d89))
|
|
6
|
+
|
|
1
7
|
## [16.12.7](https://github.com/appium/WebDriverAgent/compare/v16.12.6...v16.12.7) (2026-09-10)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
|
@@ -374,26 +374,18 @@ static XCUIElement *FBLiveElementForSnapshot(id<FBXCElementSnapshot> snapshot, X
|
|
|
374
374
|
error:(NSError **)error
|
|
375
375
|
{
|
|
376
376
|
CGRect scrollingFrame = self.scrollingFrame;
|
|
377
|
-
|
|
377
|
+
// wdFrame matches scrollingFrame's coordinate space; raw .frame can be pre-scaled or
|
|
378
|
+
// dimension-swapped and drift out of sync with it (appium/appium#16185).
|
|
379
|
+
CGRect anchorFrame = anchorElement.wdFrame;
|
|
378
380
|
if (CGRectIsEmpty(scrollingFrame) || CGRectIsEmpty(anchorFrame)) {
|
|
379
381
|
return [[[FBErrorBuilder builder]
|
|
380
382
|
withDescriptionFormat:@"Cannot compute a scroll gesture for '%@': its frame is empty", self.fb_description]
|
|
381
383
|
buildError:error];
|
|
382
384
|
}
|
|
383
385
|
|
|
384
|
-
// Compute the touch-down/up points within the (possibly clipped) scrolling frame as
|
|
385
|
-
// before, then express them as fractions of the anchor element's own frame instead of
|
|
386
|
-
// raw points, which XCTest never rescales for compatibility-mode windows
|
|
387
|
-
// (appium/appium#16185). When scrollingFrame == anchorFrame this resolves to the exact
|
|
388
|
-
// same absolute point as before; it only differs once XCTest itself rescales anchorFrame.
|
|
389
386
|
CGVector proportion = [self fb_normalizedHitPointOffsetForScrollingVector:vector];
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
CGPoint endPoint = CGPointMake((CGFloat)floor(startPoint.x + vector.dx), (CGFloat)floor(startPoint.y + vector.dy));
|
|
393
|
-
CGVector startOffset = CGVectorMake((startPoint.x - anchorFrame.origin.x) / anchorFrame.size.width,
|
|
394
|
-
(startPoint.y - anchorFrame.origin.y) / anchorFrame.size.height);
|
|
395
|
-
CGVector endOffset = CGVectorMake((endPoint.x - anchorFrame.origin.x) / anchorFrame.size.width,
|
|
396
|
-
(endPoint.y - anchorFrame.origin.y) / anchorFrame.size.height);
|
|
387
|
+
CGVector startOffset, endOffset;
|
|
388
|
+
FBScrollGestureOffsets(scrollingFrame, anchorFrame, proportion, vector, &startOffset, &endOffset);
|
|
397
389
|
XCUICoordinate *startCoordinate = [anchorElement coordinateWithNormalizedOffset:startOffset];
|
|
398
390
|
XCUICoordinate *endCoordinate = [anchorElement coordinateWithNormalizedOffset:endOffset];
|
|
399
391
|
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<key>CFBundlePackageType</key>
|
|
16
16
|
<string>FMWK</string>
|
|
17
17
|
<key>CFBundleShortVersionString</key>
|
|
18
|
-
<string>16.12.
|
|
18
|
+
<string>16.12.8</string>
|
|
19
19
|
<key>CFBundleSignature</key>
|
|
20
20
|
<string>????</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>16.12.
|
|
22
|
+
<string>16.12.8</string>
|
|
23
23
|
<key>NSPrincipalClass</key>
|
|
24
24
|
<string/>
|
|
25
25
|
</dict>
|
|
@@ -61,4 +61,29 @@ XCUICoordinate * _Nullable FBCoordinateWithAnchorOffset(XCUIElement *element,
|
|
|
61
61
|
NSError **error);
|
|
62
62
|
#endif
|
|
63
63
|
|
|
64
|
+
/*!
|
|
65
|
+
Computes the normalized (0.0-1.0) start/end offsets of a scroll drag gesture whose
|
|
66
|
+
touch-down/up points fall within scrollingFrame, expressed relative to anchorFrame -
|
|
67
|
+
the coordinate space the resulting offsets get resolved against (e.g. via
|
|
68
|
+
-[XCUIElement coordinateWithNormalizedOffset:]). scrollingFrame and anchorFrame are
|
|
69
|
+
usually the same rect, but scrollingFrame may be clipped to a visible sub-region, and/or
|
|
70
|
+
the two may come from frame sources XCTest doesn't keep in sync (see appium/appium#16185)
|
|
71
|
+
- passing mismatched frames here reproduces that bug rather than fixing it.
|
|
72
|
+
|
|
73
|
+
@param scrollingFrame the (possibly clipped) frame to compute the touch-down/up points within
|
|
74
|
+
@param anchorFrame the frame startOffset/endOffset get normalized against
|
|
75
|
+
@param proportion normalized touch-down position within scrollingFrame, e.g. from
|
|
76
|
+
-fb_normalizedHitPointOffsetForScrollingVector:
|
|
77
|
+
@param vector the scroll vector, in scrollingFrame's coordinate space
|
|
78
|
+
@param startOffset populated with the normalized start offset; untouched if NO is returned
|
|
79
|
+
@param endOffset populated with the normalized end offset; untouched if NO is returned
|
|
80
|
+
@return NO if either frame is empty
|
|
81
|
+
*/
|
|
82
|
+
BOOL FBScrollGestureOffsets(CGRect scrollingFrame,
|
|
83
|
+
CGRect anchorFrame,
|
|
84
|
+
CGVector proportion,
|
|
85
|
+
CGVector vector,
|
|
86
|
+
CGVector *startOffset,
|
|
87
|
+
CGVector *endOffset);
|
|
88
|
+
|
|
64
89
|
NS_ASSUME_NONNULL_END
|
|
@@ -86,3 +86,24 @@ XCUICoordinate *FBCoordinateWithAnchorOffset(XCUIElement *element,
|
|
|
86
86
|
return [element coordinateWithNormalizedOffset:normalizedOffset];
|
|
87
87
|
}
|
|
88
88
|
#endif
|
|
89
|
+
|
|
90
|
+
BOOL FBScrollGestureOffsets(CGRect scrollingFrame,
|
|
91
|
+
CGRect anchorFrame,
|
|
92
|
+
CGVector proportion,
|
|
93
|
+
CGVector vector,
|
|
94
|
+
CGVector *startOffset,
|
|
95
|
+
CGVector *endOffset)
|
|
96
|
+
{
|
|
97
|
+
if (CGRectIsEmpty(scrollingFrame) || CGRectIsEmpty(anchorFrame)) {
|
|
98
|
+
return NO;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
CGPoint startPoint = CGPointMake((CGFloat)floor(scrollingFrame.origin.x + scrollingFrame.size.width * proportion.dx),
|
|
102
|
+
(CGFloat)floor(scrollingFrame.origin.y + scrollingFrame.size.height * proportion.dy));
|
|
103
|
+
CGPoint endPoint = CGPointMake((CGFloat)floor(startPoint.x + vector.dx), (CGFloat)floor(startPoint.y + vector.dy));
|
|
104
|
+
*startOffset = CGVectorMake((startPoint.x - anchorFrame.origin.x) / anchorFrame.size.width,
|
|
105
|
+
(startPoint.y - anchorFrame.origin.y) / anchorFrame.size.height);
|
|
106
|
+
*endOffset = CGVectorMake((endPoint.x - anchorFrame.origin.x) / anchorFrame.size.width,
|
|
107
|
+
(endPoint.y - anchorFrame.origin.y) / anchorFrame.size.height);
|
|
108
|
+
return YES;
|
|
109
|
+
}
|
|
@@ -110,4 +110,42 @@
|
|
|
110
110
|
XCTAssertTrue(FBSizeFuzzyEqualToSize(screenSizeLandscape, FBAdjustDimensionsForApplication(screenSizeLandscape, UIInterfaceOrientationLandscapeRight), t));
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
- (void)testScrollGestureOffsetsWithMatchingFrames
|
|
114
|
+
{
|
|
115
|
+
CGRect frame = CGRectMake(20, 200, 300, 400);
|
|
116
|
+
CGVector proportion = CGVectorMake(0.5, 0.75);
|
|
117
|
+
CGVector vector = CGVectorMake(0, -200);
|
|
118
|
+
CGVector startOffset, endOffset;
|
|
119
|
+
XCTAssertTrue(FBScrollGestureOffsets(frame, frame, proportion, vector, &startOffset, &endOffset));
|
|
120
|
+
XCTAssertTrue(FBVectorFuzzyEqualToVector(startOffset, CGVectorMake(0.5, 0.75), 0.01));
|
|
121
|
+
XCTAssertTrue(FBVectorFuzzyEqualToVector(endOffset, CGVectorMake(0.5, 0.25), 0.01));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
- (void)testScrollGestureOffsetsWithRescaledAnchorFrame
|
|
125
|
+
{
|
|
126
|
+
// Simulates a compatibility-mode window: anchorFrame is scrollingFrame scaled by ~2.19x,
|
|
127
|
+
// same origin - offsets should still land within [0, 1] instead of drifting outside it.
|
|
128
|
+
CGRect scrollingFrame = CGRectMake(20, 202, 335, 420);
|
|
129
|
+
CGRect anchorFrame = CGRectMake(20, 202, 733, 920);
|
|
130
|
+
CGVector proportion = CGVectorMake(0.5, 0.75);
|
|
131
|
+
CGVector vector = CGVectorMake(0, -250);
|
|
132
|
+
CGVector startOffset, endOffset;
|
|
133
|
+
XCTAssertTrue(FBScrollGestureOffsets(scrollingFrame, anchorFrame, proportion, vector, &startOffset, &endOffset));
|
|
134
|
+
XCTAssertTrue(startOffset.dx >= 0 && startOffset.dx <= 1);
|
|
135
|
+
XCTAssertTrue(startOffset.dy >= 0 && startOffset.dy <= 1);
|
|
136
|
+
XCTAssertTrue(endOffset.dx >= 0 && endOffset.dx <= 1);
|
|
137
|
+
XCTAssertTrue(endOffset.dy >= 0 && endOffset.dy <= 1);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
- (void)testScrollGestureOffsetsWithEmptyFrame
|
|
141
|
+
{
|
|
142
|
+
CGVector startOffset = CGVectorMake(-1, -1);
|
|
143
|
+
CGVector endOffset = CGVectorMake(-1, -1);
|
|
144
|
+
XCTAssertFalse(FBScrollGestureOffsets(CGRectZero, CGRectMake(0, 0, 100, 100), CGVectorMake(0.5, 0.5), CGVectorMake(0, -50), &startOffset, &endOffset));
|
|
145
|
+
XCTAssertFalse(FBScrollGestureOffsets(CGRectMake(0, 0, 100, 100), CGRectZero, CGVectorMake(0.5, 0.5), CGVectorMake(0, -50), &startOffset, &endOffset));
|
|
146
|
+
// Untouched on failure
|
|
147
|
+
XCTAssertTrue(startOffset.dx == -1 && startOffset.dy == -1);
|
|
148
|
+
XCTAssertTrue(endOffset.dx == -1 && endOffset.dy == -1);
|
|
149
|
+
}
|
|
150
|
+
|
|
113
151
|
@end
|