203 {
204 BOOL supportsPointerInteraction = NO;
205 SEL supportsPointerInteractionSelector = @selector(supportsPointerInteraction);
206 if ([XCUIDevice.sharedDevice respondsToSelector:supportsPointerInteractionSelector]) {
207 supportsPointerInteraction =
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];
220 XCTFail(@"Failed due to not able to find any flutterView with %@ seconds",
222 }
223
224 XCTAssertNotNil(flutterView);
225
226 SEL scroll = @selector(scrollByDeltaX:deltaY:);
227 XCTAssertTrue([flutterView respondsToSelector:scroll],
228 @"If supportsPointerInteraction is true, this should be true too.");
229
230 NSInvocation* invocation = [NSInvocation
231 invocationWithMethodSignature:[XCUIElement instanceMethodSignatureForSelector:scroll]];
232 [invocation setSelector:scroll];
233 CGFloat deltaX = 0.0;
234 CGFloat deltaY = 1000.0;
235 [invocation setArgument:&deltaX atIndex:2];
236 [invocation setArgument:&deltaY atIndex:3];
237 [invocation invokeWithTarget:flutterView];
238
239
240 SEL hover = @selector(hover:);
241 XCTAssertTrue([flutterView respondsToSelector:hover],
242 @"If supportsPointerInteraction is true, this should be true too.");
243 [flutterView performSelector:hover];
244
245
246
247
248
249 XCTestExpectation* sleepExpectation = [self expectationWithDescription:@"never fires"];
250 sleepExpectation.inverted = true;
251 [self waitForExpectations:@[ sleepExpectation ] timeout:5.0];
252
253
254
255 NSMutableDictionary<NSString*, NSMutableArray<NSNumber*>*>* messages =
256 [[NSMutableDictionary alloc] init];
257 for (XCUIElement* element in [
app.textFields allElementsBoundByIndex]) {
258 NSString* rawMessage = element.value;
259
260 NSUInteger commaIndex = [rawMessage rangeOfString:@","].location;
261 NSInteger messageSequenceNumber =
262 [rawMessage substringWithRange:NSMakeRange(0, commaIndex)].integerValue;
263
264 NSString*
message = [rawMessage
265 substringWithRange:NSMakeRange(commaIndex + 1, rawMessage.length - (commaIndex + 1))];
266 NSMutableArray<NSNumber*>* messageSequenceNumberList = messages[message];
267 if (messageSequenceNumberList == nil) {
268 messageSequenceNumberList = [[NSMutableArray alloc] init];
269 messages[message] = messageSequenceNumberList;
270 }
271 [messageSequenceNumberList addObject:@(messageSequenceNumber)];
272 }
273
275 messages, @"PointerChange.add,device=0,buttons=0,signalKind=PointerSignalKind.none");
276 NSMutableArray<NSNumber*>* hoverSequenceNumbers =
277 messages[@"PointerChange.hover,device=0,buttons=0,signalKind=PointerSignalKind.none"];
279 messages, @"PointerChange.remove,device=0,buttons=0,signalKind=PointerSignalKind.none");
281 messages, @"PointerChange.add,device=1,buttons=0,signalKind=PointerSignalKind.none");
283 messages, @"PointerChange.panZoomStart,device=1,buttons=0,signalKind=PointerSignalKind.none");
284
285 NSMutableArray<NSNumber*>* panZoomUpdateSequenceNumbers =
286 messages[@"PointerChange.panZoomUpdate,device=1,buttons=0,signalKind=PointerSignalKind.none"];
288 messages, @"PointerChange.panZoomEnd,device=1,buttons=0,signalKind=PointerSignalKind.none");
290 messages,
291 @"PointerChange.cancel,device=2,buttons=0,signalKind=PointerSignalKind.scrollInertiaCancel");
292
293 XCTAssertGreaterThan(panZoomStartSequenceNumber, panZoomAddedSequenceNumber,
294 @"PanZoomStart occured before pointer was added");
295 XCTAssertGreaterThan([[panZoomUpdateSequenceNumbers firstObject] intValue],
296 panZoomStartSequenceNumber, @"PanZoomUpdate occured before PanZoomStart");
297 XCTAssertGreaterThan(panZoomEndSequenceNumber,
298 [[panZoomUpdateSequenceNumbers lastObject] intValue],
299 @"PanZoomUpdate occured after PanZoomEnd");
300 XCTAssertGreaterThan(inertiaCancelSequenceNumber, panZoomEndSequenceNumber,
301 @"ScrollInertiaCancel occured before PanZoomEnd");
302
303 XCTAssertGreaterThan([[hoverSequenceNumbers firstObject] intValue], hoverAddedSequenceNumber,
304 @"Hover occured before pointer was added");
305 XCTAssertGreaterThan(hoverRemovedSequenceNumber, [[hoverSequenceNumbers lastObject] intValue],
306 @"Hover occured after pointer was removed");
307}