-
Notifications
You must be signed in to change notification settings - Fork 6k
Conversation
Reviewers: Any idea how to test this? I made some attempts that didn't work and left them commented out with some questions. Let me know if you have any ideas. Edit: I also tried creating a new FlutterPlatformPluginTest.mm file, but I couldn't get run_tests.py to pick it up. |
Another question for reviewers: How do we usually expose APIs that only exist on certain platforms (in this case iOS)? Is it alright that the framework needs to know to only call this for iOS devices? Another option is to implement this for the other platforms as well, but re-implement the behavior of hasStrings for them by reading the full clipboard text and returning whether or not it's a pasteable string. Then the framework could call it for any platform. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation LGTM, @jmagman for guidance on iOS testing (not too familiar myself)
/* | ||
- (void)testHasStrings { | ||
id project = OCMClassMock([FlutterDartProject class]); | ||
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a way to create a mock clipboard, and pass it into the mock engine/plugin, though not clear on implementation details
@@ -143,4 +144,25 @@ - (void)testCanCreatePlatformViewWithoutFlutterView { | |||
flutterPlatformViewsController->Reset(); | |||
} | |||
|
|||
// TODO(justinmc): I wrote this test before realizing handleMethodCall is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might be able to extend the class and expose a public version in the test class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to make the channel with the same identifier and send a message to it and wait for a reply. There should be an example of this somewhere in our tests but I can't find one. Did you look at this test for ideas? https://github.com/gaaclarke/engine/blob/linting-warning/shell/platform/darwin/common/framework/Source/FlutterChannelsTest.m
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this:
- (void)testClipboard {
id project = OCMClassMock([FlutterDartProject class]);
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project];
FlutterMethodChannel* channel =
[FlutterMethodChannel methodChannelWithName:@"flutter/platform"
binaryMessenger:engine.binaryMessenger
codec:[FlutterJSONMethodCodec sharedInstance]];
[engine run];
XCTestExpectation* didCallReply = [self expectationWithDescription:@"didCallReply"];
[channel invokeMethod:@"Clipboard.getData"
arguments:nil
result:^(id _Nullable result){
[didCallReply fulfill];
}];
[self waitForExpectationsWithTimeout:1.0 handler:nil];
}
But it crashes because it tries to run on a fake project. Channels don't work unless an engine is running and the engine doesn't run unless there is a project and in unit tests the engine doesn't have a project... I'll look into this a bit more this afternoon to see what the best approach will be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks I appreciate the help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I looked at a few options and this appears to be more complicated than I had hoped. handleMethodCall
isn't private so you can just call it directly for the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I forgot I could just call it with square brackets in objective c. That seems to work. Thanks for the help!
cc @Hixie for advice on this? |
The API might not exist in literal form on other platforms but surely we can implement it ourselves based on the APIs they do expose, no? After all, we're going to want to use the same logic to enable/disable paste on all platforms. |
The behavior may be slightly different on different native platforms, but yes I agree. I'll implement this method for our other platforms as well (in separate PRs I think). |
according to the README file:
|
Thanks for the pointer @LongCatIsLooong! It's working in its own file now. |
@gaaclarke @GaryQian @LongCatIsLooong Ready for a final review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation LGTM. Is the idea optionally sending the "hasStrings" message based on what defaultTargetPlatform
says in the framework, instead of implementing such API for every platform?
[plugin handleMethodCall:methodCall result:result]; | ||
|
||
XCTAssertEqual(called, true); | ||
XCTAssertEqual(value, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the generalPasteboard
always guaranteed to hasStrings
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point, I'm not sure. I'm going to add a call to setClipboardData right before to guarantee that it's true.
value = result[@"value"]; | ||
}; | ||
FlutterMethodCall* methodCall = | ||
[FlutterMethodCall methodCallWithMethodName:@"Clipboard.hasStrings" arguments:@{}]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: is the arguments
supposed to be nil
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@LongCatIsLooong Yes that's right. I plan to implement hasStrings on all platforms and have the framework call it without caring what device it's running on. The alternative would be to implement it only on iOS and have the framework only call it for iOS and use other things like getData for other platforms. |
The Fuchsia test failure is a flake. Landing on red to kick the tree. |
Description
hasStrings is needed on iOS to allow us to check for clipboard contents without triggering the new iOS14 clipboard access notification.
Related Issues
flutter/flutter#60145
Tests
I'm desperately struggling to test this, as no other platform channel handlers seem to be tested at all for reference. See the TODOs in my code.