Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 03505f6

Browse files
committed
Add test of gesture scroll on iPad
1 parent 243bc7f commit 03505f6

File tree

3 files changed

+102
-6
lines changed

3 files changed

+102
-6
lines changed

shell/platform/windows/direct_manipulation.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ HRESULT DirectManipulationEventHandler::OnViewportStatusChanged(
3333
if (!resetting_) {
3434
if (owner_->binding_handler_delegate) {
3535
owner_->binding_handler_delegate->OnPointerPanZoomStart(
36-
(int32_t)reinterpret_cast<int64_t>(this));
36+
(int32_t) reinterpret_cast<int64_t>(this));
3737
}
3838
}
3939
} else if (previous == DIRECTMANIPULATION_RUNNING) {
@@ -42,7 +42,7 @@ HRESULT DirectManipulationEventHandler::OnViewportStatusChanged(
4242
} else {
4343
if (owner_->binding_handler_delegate) {
4444
owner_->binding_handler_delegate->OnPointerPanZoomEnd(
45-
(int32_t)reinterpret_cast<int64_t>(this));
45+
(int32_t) reinterpret_cast<int64_t>(this));
4646
}
4747
// Need to reset the content transform
4848
// Use resetting_ flag to prevent sending reset also to the framework
@@ -91,7 +91,7 @@ HRESULT DirectManipulationEventHandler::OnContentUpdated(
9191
float pan_y = transform[5];
9292
if (owner_->binding_handler_delegate) {
9393
owner_->binding_handler_delegate->OnPointerPanZoomUpdate(
94-
(int32_t)reinterpret_cast<int64_t>(this), pan_x, pan_y, scale, 0);
94+
(int32_t) reinterpret_cast<int64_t>(this), pan_x, pan_y, scale, 0);
9595
}
9696
}
9797
return S_OK;

shell/platform/windows/direct_manipulation_unittests.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ TEST(DirectManipulationTest, TestGesture) {
155155
owner->SetBindingHandlerDelegate(&delegate);
156156
auto handler =
157157
fml::MakeRefCounted<DirectManipulationEventHandler>(nullptr, owner.get());
158-
int32_t device_id = (int32_t)reinterpret_cast<int64_t>(handler.get());
158+
int32_t device_id = (int32_t) reinterpret_cast<int64_t>(handler.get());
159159
EXPECT_CALL(delegate, OnPointerPanZoomStart(device_id));
160160
handler->OnViewportStatusChanged((IDirectManipulationViewport*)&viewport,
161161
DIRECTMANIPULATION_RUNNING,

testing/scenario_app/ios/Scenarios/ScenariosUITests/iPadGestureTests.m

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,16 @@ - (void)testPointerButtons {
7575
XCTAssertTrue(
7676
[app.textFields[@"2,PointerChange.up,device=0,buttons=0"] waitForExistenceWithTimeout:1],
7777
@"PointerChange.up event did not occur for a normal tap");
78+
XCTAssertTrue(
79+
[app.textFields[@"3,PointerChange.remove,device=0,buttons=0"] waitForExistenceWithTimeout:1],
80+
@"PointerChange.remove event did not occur for a normal tap");
7881
SEL rightClick = @selector(rightClick);
7982
XCTAssertTrue([flutterView respondsToSelector:rightClick],
8083
@"If supportsPointerInteraction is true, this should be true too.");
8184
[flutterView performSelector:rightClick];
8285
// On simulated right click, a hover also occurs, so the hover pointer is added
8386
XCTAssertTrue(
84-
[app.textFields[@"3,PointerChange.add,device=1,buttons=0"] waitForExistenceWithTimeout:1],
87+
[app.textFields[@"4,PointerChange.add,device=1,buttons=0"] waitForExistenceWithTimeout:1],
8588
@"PointerChange.add event did not occur for a right-click's hover pointer");
8689

8790
// The hover pointer is removed after ~3.5 seconds, this ensures that all events are received
@@ -137,7 +140,7 @@ - (void)testPointerButtons {
137140
@"Right-click pointer was pressed before it was added");
138141
XCTAssertGreaterThan(rightClickUpSequenceNumber, rightClickDownSequenceNumber,
139142
@"Right-click pointer was released before it was pressed");
140-
XCTAssertGreaterThan([[hoverSequenceNumbers firstObject] intValue], 3,
143+
XCTAssertGreaterThan([[hoverSequenceNumbers firstObject] intValue], 4,
141144
@"Hover occured before hover pointer was added");
142145
XCTAssertGreaterThan(hoverRemovedSequenceNumber, [[hoverSequenceNumbers lastObject] intValue],
143146
@"Hover occured after hover pointer was removed");
@@ -196,6 +199,99 @@ - (void)testPointerHover {
196199
XCTAssertTrue([app.textFields[removeMessage] waitForExistenceWithTimeout:1],
197200
@"PointerChange.remove event did not occur for a hover");
198201
}
202+
203+
- (void)testPointerScroll {
204+
BOOL supportsPointerInteraction = NO;
205+
SEL supportsPointerInteractionSelector = @selector(supportsPointerInteraction);
206+
if ([XCUIDevice.sharedDevice respondsToSelector:supportsPointerInteractionSelector]) {
207+
supportsPointerInteraction =
208+
performBoolSelector(XCUIDevice.sharedDevice, supportsPointerInteractionSelector);
209+
}
210+
XCTSkipUnless(supportsPointerInteraction, "Device does not support pointer interaction.");
211+
XCUIApplication* app = [[XCUIApplication alloc] init];
212+
app.launchArguments = @[ @"--pointer-events" ];
213+
[app launch];
214+
215+
NSPredicate* predicateToFindFlutterView =
216+
[NSPredicate predicateWithFormat:@"identifier BEGINSWITH 'flutter_view'"];
217+
XCUIElement* flutterView = [[app descendantsMatchingType:XCUIElementTypeAny]
218+
elementMatchingPredicate:predicateToFindFlutterView];
219+
if (![flutterView waitForExistenceWithTimeout:kSecondsToWaitForFlutterView]) {
220+
NSLog(@"%@", app.debugDescription);
221+
XCTFail(@"Failed due to not able to find any flutterView with %@ seconds",
222+
@(kSecondsToWaitForFlutterView));
223+
}
224+
225+
XCTAssertNotNil(flutterView);
226+
227+
SEL scroll = @selector(scrollByDeltaX:deltaY:);
228+
XCTAssertTrue([flutterView respondsToSelector:scroll],
229+
@"If supportsPointerInteraction is true, this should be true too.");
230+
// Need to use NSInvocation in order to send primitive arguments to selector
231+
NSInvocation* invocation = [NSInvocation
232+
invocationWithMethodSignature:[XCUIElement instanceMethodSignatureForSelector:scroll]];
233+
[invocation setSelector:scroll];
234+
CGFloat deltaX = 0.0;
235+
CGFloat deltaY = 1000.0;
236+
[invocation setArgument:&deltaX atIndex:2];
237+
[invocation setArgument:&deltaY atIndex:3];
238+
[invocation invokeWithTarget:flutterView];
239+
240+
// The hover pointer is removed after ~3.5 seconds, this ensures that all events are received
241+
XCTestExpectation* sleepExpectation = [self expectationWithDescription:@"never fires"];
242+
sleepExpectation.inverted = true;
243+
[self waitForExpectations:@[ sleepExpectation ] timeout:5.0];
244+
245+
// There are hover events interspersed with the scroll events in a varying order
246+
// Ensure the individual orderings are respected without hardcoding the absolute sequence
247+
NSMutableDictionary<NSString*, NSMutableArray<NSNumber*>*>* messages =
248+
[[NSMutableDictionary alloc] init];
249+
for (XCUIElement* element in [app.textFields allElementsBoundByIndex]) {
250+
NSString* rawMessage = element.value;
251+
// Parse out the sequence number
252+
NSUInteger commaIndex = [rawMessage rangeOfString:@","].location;
253+
NSInteger messageSequenceNumber =
254+
[rawMessage substringWithRange:NSMakeRange(0, commaIndex)].integerValue;
255+
// Parse out the rest of the message
256+
NSString* message = [rawMessage
257+
substringWithRange:NSMakeRange(commaIndex + 1, rawMessage.length - (commaIndex + 1))];
258+
NSMutableArray<NSNumber*>* messageSequenceNumberList = messages[message];
259+
if (messageSequenceNumberList == nil) {
260+
messageSequenceNumberList = [[NSMutableArray alloc] init];
261+
messages[message] = messageSequenceNumberList;
262+
}
263+
[messageSequenceNumberList addObject:@(messageSequenceNumber)];
264+
}
265+
// The number of hover events is not consistent, there could be one or many
266+
int hoverAddedSequenceNumber =
267+
assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.add,device=0,buttons=0");
268+
NSMutableArray<NSNumber*>* hoverSequenceNumbers =
269+
messages[@"PointerChange.hover,device=0,buttons=0"];
270+
int hoverRemovedSequenceNumber =
271+
assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.remove,device=0,buttons=0");
272+
int panZoomAddedSequenceNumber =
273+
assertOneMessageAndGetSequenceNumber(messages, @"PointerChange.add,device=1,buttons=0");
274+
int panZoomStartSequenceNumber = assertOneMessageAndGetSequenceNumber(
275+
messages, @"PointerChange.panZoomStart,device=1,buttons=0");
276+
// The number of pan/zoom update events is not consistent, there could be one or many
277+
NSMutableArray<NSNumber*>* panZoomUpdateSequenceNumbers =
278+
messages[@"PointerChange.panZoomUpdate,device=1,buttons=0"];
279+
int panZoomEndSequenceNumber = assertOneMessageAndGetSequenceNumber(
280+
messages, @"PointerChange.panZoomEnd,device=1,buttons=0");
281+
282+
XCTAssertGreaterThan(panZoomStartSequenceNumber, panZoomAddedSequenceNumber,
283+
@"PanZoomStart occured before pointer was added");
284+
XCTAssertGreaterThan([[panZoomUpdateSequenceNumbers firstObject] intValue],
285+
panZoomStartSequenceNumber, @"PanZoomUpdate occured before PanZoomStart");
286+
XCTAssertGreaterThan(panZoomEndSequenceNumber,
287+
[[panZoomUpdateSequenceNumbers lastObject] intValue],
288+
@"PanZoomUpdate occured after PanZoomUpdate");
289+
290+
XCTAssertGreaterThan([[hoverSequenceNumbers firstObject] intValue], hoverAddedSequenceNumber,
291+
@"Hover occured before pointer was added");
292+
XCTAssertGreaterThan(hoverRemovedSequenceNumber, [[hoverSequenceNumbers lastObject] intValue],
293+
@"Hover occured after pointer was removed");
294+
}
199295
#pragma clang diagnostic pop
200296

201297
@end

0 commit comments

Comments
 (0)