Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
125 changes: 125 additions & 0 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
FLUTTER_ASSERT_NOT_ARC
@class FlutterPlatformViewsTestMockPlatformView;
static FlutterPlatformViewsTestMockPlatformView* gMockPlatformView = nil;
const float kFloatCompareEpsilon = 0.001;

@interface FlutterPlatformViewsTestMockPlatformView : UIView
@end
Expand Down Expand Up @@ -143,4 +144,128 @@ - (void)testCanCreatePlatformViewWithoutFlutterView {
flutterPlatformViewsController->Reset();
}

- (void)testChildClippingViewHitTests {
ChildClippingView *childCilppingView = [[[ChildClippingView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
UIView *childView = [[[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)] autorelease];
[childCilppingView addSubview:childView];

XCTAssertFalse([childCilppingView pointInside:CGPointMake(50, 50) withEvent:nil]);
XCTAssertTrue([childCilppingView pointInside:CGPointMake(150, 150) withEvent:nil]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you might want to check the edges as well. e.g. 100,100, 99,99, 100,99, 99,100.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same with the right, bottom edge

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

- (void)testCompositePlatformView {
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 platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*delegate=*/mock_delegate,
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*task_runners=*/runners);

auto flutterPlatformViewsController = std::make_unique<flutter::FlutterPlatformViewsController>();

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);

XCTAssertNotNil(gMockPlatformView);

UIView *mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
// Create embedded view params
flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack
SkMatrix screenScaleMatrix = SkMatrix::MakeScale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what [UIScreen mainScreen].scale would be when executed on LUCI. Maybe pick a constant value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to be screenScale because the CompositeEmbeddedView uses screenScale to add a reverse scale matrix to the final transform matrix.

stack.PushTransform(screenScaleMatrix);
// Push a translate matrix
SkMatrix translateMatrix = SkMatrix::MakeTrans(100, 100);
stack.PushTransform(translateMatrix);
SkMatrix finalMatrix;
finalMatrix.setConcat(screenScaleMatrix, translateMatrix);

auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);

flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
flutterPlatformViewsController->CompositeEmbeddedView(2);
CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds
toView:mockFlutterView];
XCTAssertTrue(CGRectEqualToRect(platformViewRectInFlutterView, CGRectMake(100, 100, 300, 300)));
flutterPlatformViewsController->Reset();
}

- (void)testChildClippingViewShouldBeTheBoundingRectOfPlatformView {
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 platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*delegate=*/mock_delegate,
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*task_runners=*/runners);

auto flutterPlatformViewsController = std::make_unique<flutter::FlutterPlatformViewsController>();

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);

XCTAssertNotNil(gMockPlatformView);

UIView *mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
// Create embedded view params
flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack
SkMatrix screenScaleMatrix = SkMatrix::MakeScale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

stack.PushTransform(screenScaleMatrix);
// Push a rotate matrix
SkMatrix rotateMatrix;
rotateMatrix.setRotate(10);
stack.PushTransform(rotateMatrix);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine, but what about PushClipPath?

void PushClipPath(const SkPath& path);

Should that be in a separate unit test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To test the clipping, we will probably have to render the view into an image, then check the pixels (sort like a screenshot). I think the scenario tests already covered all the clippings, it is kind of redundant.

SkMatrix finalMatrix;
finalMatrix.setConcat(screenScaleMatrix, rotateMatrix);

auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);

flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
flutterPlatformViewsController->CompositeEmbeddedView(2);
CGRect platformViewRectInFlutterView = [gMockPlatformView convertRect:gMockPlatformView.bounds
toView:mockFlutterView];
XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass: ChildClippingView.class]);
ChildClippingView *childClippingView = (ChildClippingView *)gMockPlatformView.superview.superview;
// The childclippingview's frame is set based on flow, but the platform view's frame is set based on quartz.
// Although they should be the same, but we should tolerate small floating point errors.
XCTAssertTrue(fabs(platformViewRectInFlutterView.origin.x - childClippingView.frame.origin.x) < kFloatCompareEpsilon);
XCTAssertTrue(fabs(platformViewRectInFlutterView.origin.y - childClippingView.frame.origin.y) < kFloatCompareEpsilon);
XCTAssertTrue(fabs(platformViewRectInFlutterView.size.width - childClippingView.frame.size.width) < kFloatCompareEpsilon);
XCTAssertTrue(fabs(platformViewRectInFlutterView.size.height - childClippingView.frame.size.height) < kFloatCompareEpsilon);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


flutterPlatformViewsController->Reset();
}

@end