Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 129 additions & 91 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
Original file line number Diff line number Diff line change
Expand Up @@ -621,15 +621,15 @@ - (void)testSetFlutterViewControllerAfterCreateCanStillDispatchTouchEvents {
}

// Before setting flutter view controller, events are not dispatched.
NSSet* touches1 = OCMClassMock([NSSet class]);
UIEvent* event1 = OCMClassMock([UIEvent class]);
UIViewController* mockFlutterViewContoller = OCMClassMock([UIViewController class]);
NSSet* touches1 = [[[NSSet alloc] init] autorelease];
id event1 = OCMClassMock([UIEvent class]);
id mockFlutterViewContoller = OCMClassMock([UIViewController class]);
[forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
OCMReject([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);

// Set flutter view controller allows events to be dispatched.
NSSet* touches2 = OCMClassMock([NSSet class]);
UIEvent* event2 = OCMClassMock([UIEvent class]);
NSSet* touches2 = [[[NSSet alloc] init] autorelease];
id event2 = OCMClassMock([UIEvent class]);
flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);
[forwardGectureRecognizer touchesBegan:touches2 withEvent:event2];
OCMVerify([mockFlutterViewContoller touchesBegan:touches2 withEvent:event2]);
Expand Down Expand Up @@ -681,39 +681,37 @@ - (void)testSetFlutterViewControllerInTheMiddleOfTouchEventShouldStillAllowGestu
break;
}
}
UIViewController* mockFlutterViewContoller = OCMClassMock([UIViewController class]);
id mockFlutterViewContoller = OCMClassMock([UIViewController class]);
{
// ***** Sequence 1, finishing touch event with touchEnded ***** //

flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);

NSSet* touches1 = OCMClassMock([NSSet class]);
UIEvent* event1 = OCMClassMock([UIEvent class]);
NSSet* touches1 = [[[NSSet alloc] init] autorelease];
id event1 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
OCMVerify([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);

flutterPlatformViewsController->SetFlutterViewController(nil);

// Allow the touch events to finish
NSSet* touches2 = OCMClassMock([NSSet class]);
UIEvent* event2 = OCMClassMock([UIEvent class]);
NSSet* touches2 = [[[NSSet alloc] init] autorelease];
id event2 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesMoved:touches2 withEvent:event2];
OCMVerify([mockFlutterViewContoller touchesMoved:touches2 withEvent:event2]);

NSSet* touches3 = OCMClassMock([NSSet class]);
UIEvent* event3 = OCMClassMock([UIEvent class]);
NSSet* touches3 = [[[NSSet alloc] init] autorelease];
id event3 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches3 withEvent:event3];
OCMVerify([mockFlutterViewContoller touchesEnded:touches3 withEvent:event3]);

// Now the 2nd touch sequence should not be allowed.
NSSet* touches4 = OCMClassMock([NSSet class]);
UIEvent* event4 = OCMClassMock([UIEvent class]);
mockFlutterViewContoller = OCMClassMock([UIViewController class]);
NSSet* touches4 = [[[NSSet alloc] init] autorelease];
id event4 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches4 withEvent:event4];
OCMReject([mockFlutterViewContoller touchesBegan:touches4 withEvent:event4]);

NSSet* touches5 = OCMClassMock([NSSet class]);
UIEvent* event5 = OCMClassMock([UIEvent class]);
NSSet* touches5 = [[[NSSet alloc] init] autorelease];
id event5 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
OCMReject([mockFlutterViewContoller touchesEnded:touches5 withEvent:event5]);
}
Expand All @@ -722,105 +720,145 @@ - (void)testSetFlutterViewControllerInTheMiddleOfTouchEventShouldStillAllowGestu
// ***** Sequence 2, finishing touch event with touchCancelled ***** //
flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);

NSSet* touches1 = OCMClassMock([NSSet class]);
UIEvent* event1 = OCMClassMock([UIEvent class]);
NSSet* touches1 = [[[NSSet alloc] init] autorelease];
id event1 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
OCMVerify([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);

flutterPlatformViewsController->SetFlutterViewController(nil);

// Allow the touch events to finish
NSSet* touches2 = OCMClassMock([NSSet class]);
UIEvent* event2 = OCMClassMock([UIEvent class]);
NSSet* touches2 = [[[NSSet alloc] init] autorelease];
id event2 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesMoved:touches2 withEvent:event2];
OCMVerify([mockFlutterViewContoller touchesMoved:touches2 withEvent:event2]);

NSSet* touches3 = OCMClassMock([NSSet class]);
UIEvent* event3 = OCMClassMock([UIEvent class]);
NSSet* touches3 = [[[NSSet alloc] init] autorelease];
id event3 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesCancelled:touches3 withEvent:event3];
OCMVerify([mockFlutterViewContoller touchesCancelled:touches3 withEvent:event3]);

// Now the 2nd touch sequence should not be allowed.
NSSet* touches4 = OCMClassMock([NSSet class]);
UIEvent* event4 = OCMClassMock([UIEvent class]);
mockFlutterViewContoller = OCMClassMock([UIViewController class]);
NSSet* touches4 = [[[NSSet alloc] init] autorelease];
id event4 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches4 withEvent:event4];
OCMReject([mockFlutterViewContoller touchesBegan:touches4 withEvent:event4]);

NSSet* touches5 = OCMClassMock([NSSet class]);
UIEvent* event5 = OCMClassMock([UIEvent class]);
NSSet* touches5 = [[[NSSet alloc] init] autorelease];
id event5 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
OCMReject([mockFlutterViewContoller touchesEnded:touches5 withEvent:event5]);
}

{
// ***** Sequence 3, multile touches in one sequence with setting flutter view controllers in
// between ***** //
flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);
flutterPlatformViewsController->Reset();
}

NSSet* touches1 = OCMClassMock([NSSet class]);
OCMStub([touches1 count]).andReturn(1);
UIEvent* event1 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
OCMVerify([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);
- (void)
testSetFlutterViewControllerInTheMiddleOfTouchEventAllowsTheNewControllerToHandleSecondTouchSequence {
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
/*platform=*/thread_task_runner,
/*raster=*/thread_task_runner,
/*ui=*/thread_task_runner,
/*io=*/thread_task_runner);
auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*delegate=*/mock_delegate,
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*platform_views_controller=*/flutterPlatformViewsController,
/*task_runners=*/runners);

UIViewController* mockFlutterViewContoller2 = OCMClassMock([UIViewController class]);
flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller2);

// Touch events should still send to the old FlutterViewController if FlutterViewController
// is updated in between.
NSSet* touches2 = OCMClassMock([NSSet class]);
OCMStub([touches2 count]).andReturn(1);
UIEvent* event2 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches2 withEvent:event2];
OCMVerify([mockFlutterViewContoller touchesBegan:touches2 withEvent:event2]);
OCMReject([mockFlutterViewContoller2 touchesBegan:touches2 withEvent:event2]);

NSSet* touches3 = OCMClassMock([NSSet class]);
OCMStub([touches3 count]).andReturn(1);
UIEvent* event3 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesMoved:touches3 withEvent:event3];
OCMVerify([mockFlutterViewContoller touchesMoved:touches3 withEvent:event3]);
OCMReject([mockFlutterViewContoller2 touchesMoved:touches3 withEvent:event3]);

NSSet* touches4 = OCMClassMock([NSSet class]);
OCMStub([touches4 count]).andReturn(1);
UIEvent* event4 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches4 withEvent:event4];
OCMVerify([mockFlutterViewContoller touchesEnded:touches4 withEvent:event4]);
OCMReject([mockFlutterViewContoller2 touchesEnded:touches4 withEvent:event4]);

NSSet* touches5 = OCMClassMock([NSSet class]);
OCMStub([touches5 count]).andReturn(1);
UIEvent* event5 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
OCMVerify([mockFlutterViewContoller touchesEnded:touches5 withEvent:event5]);
OCMReject([mockFlutterViewContoller2 touchesEnded:touches5 withEvent:event5]);
FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
[[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease];
flutterPlatformViewsController->RegisterViewFactory(
factory, @"MockFlutterPlatformView",
FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
FlutterResult result = ^(id result) {
};
flutterPlatformViewsController->OnMethodCall(
[FlutterMethodCall
methodCallWithMethodName:@"create"
arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
result);

// Now the 2nd touch sequence should go to the new FlutterViewController
XCTAssertNotNil(gMockPlatformView);

NSSet* touches6 = OCMClassMock([NSSet class]);
OCMStub([touches6 count]).andReturn(1);
UIEvent* event6 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches6 withEvent:event6];
OCMVerify([mockFlutterViewContoller2 touchesBegan:touches6 withEvent:event6]);
OCMReject([mockFlutterViewContoller touchesBegan:touches6 withEvent:event6]);
// Find touch inteceptor view
UIView* touchInteceptorView = gMockPlatformView;
while (touchInteceptorView != nil &&
![touchInteceptorView isKindOfClass:[FlutterTouchInterceptingView class]]) {
touchInteceptorView = touchInteceptorView.superview;
}
XCTAssertNotNil(touchInteceptorView);

// Allow the touch events to finish
NSSet* touches7 = OCMClassMock([NSSet class]);
OCMStub([touches7 count]).andReturn(1);
UIEvent* event7 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesMoved:touches7 withEvent:event7];
OCMVerify([mockFlutterViewContoller2 touchesMoved:touches7 withEvent:event7]);
OCMReject([mockFlutterViewContoller touchesMoved:touches7 withEvent:event7]);

NSSet* touches8 = OCMClassMock([NSSet class]);
OCMStub([touches8 count]).andReturn(1);
UIEvent* event8 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches8 withEvent:event8];
OCMVerify([mockFlutterViewContoller2 touchesEnded:touches8 withEvent:event8]);
OCMReject([mockFlutterViewContoller touchesEnded:touches8 withEvent:event8]);
// Find ForwardGestureRecognizer
UIGestureRecognizer* forwardGectureRecognizer = nil;
for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
forwardGectureRecognizer = gestureRecognizer;
break;
}
}
id mockFlutterViewContoller = OCMClassMock([UIViewController class]);

flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);

// The touches in this sequence requires 1 touch object, we always create the NSSet with one item.
NSSet* touches1 = [NSSet setWithObject:@1];
id event1 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
OCMVerify([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);

UIViewController* mockFlutterViewContoller2 = OCMClassMock([UIViewController class]);
flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller2);

// Touch events should still send to the old FlutterViewController if FlutterViewController
// is updated in between.
NSSet* touches2 = [NSSet setWithObject:@1];
id event2 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches2 withEvent:event2];
OCMVerify([mockFlutterViewContoller touchesBegan:touches2 withEvent:event2]);
OCMReject([mockFlutterViewContoller2 touchesBegan:touches2 withEvent:event2]);

NSSet* touches3 = [NSSet setWithObject:@1];
id event3 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesMoved:touches3 withEvent:event3];
OCMVerify([mockFlutterViewContoller touchesMoved:touches3 withEvent:event3]);
OCMReject([mockFlutterViewContoller2 touchesMoved:touches3 withEvent:event3]);

NSSet* touches4 = [NSSet setWithObject:@1];
id event4 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches4 withEvent:event4];
OCMVerify([mockFlutterViewContoller touchesEnded:touches4 withEvent:event4]);
OCMReject([mockFlutterViewContoller2 touchesEnded:touches4 withEvent:event4]);

NSSet* touches5 = [NSSet setWithObject:@1];
id event5 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches5 withEvent:event5];
OCMVerify([mockFlutterViewContoller touchesEnded:touches5 withEvent:event5]);
OCMReject([mockFlutterViewContoller2 touchesEnded:touches5 withEvent:event5]);

// Now the 2nd touch sequence should go to the new FlutterViewController

NSSet* touches6 = [NSSet setWithObject:@1];
id event6 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesBegan:touches6 withEvent:event6];
OCMVerify([mockFlutterViewContoller2 touchesBegan:touches6 withEvent:event6]);
OCMReject([mockFlutterViewContoller touchesBegan:touches6 withEvent:event6]);

// Allow the touch events to finish
NSSet* touches7 = [NSSet setWithObject:@1];
id event7 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesMoved:touches7 withEvent:event7];
OCMVerify([mockFlutterViewContoller2 touchesMoved:touches7 withEvent:event7]);
OCMReject([mockFlutterViewContoller touchesMoved:touches7 withEvent:event7]);

NSSet* touches8 = [NSSet setWithObject:@1];
id event8 = OCMClassMock([UIEvent class]);
[forwardGectureRecognizer touchesEnded:touches8 withEvent:event8];
OCMVerify([mockFlutterViewContoller2 touchesEnded:touches8 withEvent:event8]);
OCMReject([mockFlutterViewContoller touchesEnded:touches8 withEvent:event8]);

flutterPlatformViewsController->Reset();
}
Expand Down