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 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
- CGRect anchorFrame = anchorElement.frame;
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
- CGPoint startPoint = CGPointMake((CGFloat)floor(scrollingFrame.origin.x + scrollingFrame.size.width * proportion.dx),
391
- (CGFloat)floor(scrollingFrame.origin.y + scrollingFrame.size.height * proportion.dy));
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.7</string>
18
+ <string>16.12.8</string>
19
19
  <key>CFBundleSignature</key>
20
20
  <string>????</string>
21
21
  <key>CFBundleVersion</key>
22
- <string>16.12.7</string>
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "16.12.7",
3
+ "version": "16.12.8",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "keywords": [
6
6
  "Appium",