-
Notifications
You must be signed in to change notification settings - Fork 26.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add native iOS screenshots to integration_test #84611
Add native iOS screenshots to integration_test #84611
Conversation
a80d1ed
to
bc4d3b8
Compare
@@ -0,0 +1,8 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> |
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.
This should have been checked in before.
@@ -475,21 +475,11 @@ | |||
baseConfigurationReference = 09505407E99803EF7AA92DE7 /* Pods-RunnerTests.debug.xcconfig */; | |||
buildSettings = { | |||
BUNDLE_LOADER = "$(TEST_HOST)"; | |||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; |
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.
Remove unnecessary build setting overrides. I can do this in a separate PR, if you prefer.
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
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 with nits. Shouldn't we have a test of this functionality that screenshots a dummy plugin and compares it to a golden image though?
- (BOOL)testIntegrationTest:(NSString **)testResult; | ||
- (instancetype)initWithScreenshotDelegate:(nullable id<FLTIntegrationTestScreenshotDelegate>)delegate NS_DESIGNATED_INITIALIZER; | ||
|
||
- (BOOL)testIntegrationTest:(NSString *_Nullable *_Nullable)testResult; |
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.
Could we get a comment on this weird API describing its behavior while you are touching it? (Or even better, could we make this an idiomatic ObjC method that returns either an NSString or nil?)
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.
This API is very weird (I just added the nullability), and the INTEGRATION_TEST_IOS_RUNNER
macro is downright Swift-hostile...
} else { | ||
result(FlutterMethodNotImplemented); | ||
} | ||
} | ||
|
||
- (UIImage *)capturePngScreenshot { | ||
UIWindow *window = [UIApplication.sharedApplication.windows filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"keyWindow = YES"]].firstObject; |
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.
Looks like we're not running clang-format in this directory on CI? This is way over the 100 char style guide length limit.
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 don't think there are any formatters (even dartfmt) running on flutter/flutter (plus I hate how clang formatter mangles Obj-C blocks). Let me shorten these up.
@@ -60,8 +61,8 @@ class IOCallbackManager implements CallbackManager { | |||
// comes up in the future. For example: `WebCallbackManager.cleanup`. | |||
} | |||
|
|||
// Whether the Flutter surface uses an Image. | |||
bool _usesFlutterImage = false; | |||
// Whether the Flutter surface uses an Image (Android only). |
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.
This sounds to me like using an image is Android-only, but the logic below is the reverse.
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.
@blasten What does Whether the Flutter surface uses an Image
mean in this context? I think that the surface is frozen, the screenshot taken, and then it's unfrozen on Android?
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.
oh - yes. Image really means that Flutter is using this class https://github.com/flutter/engine/blob/master/shell/platform/android/io/flutter/embedding/android/FlutterImageView.java. 👻
@@ -90,7 +91,7 @@ class IOCallbackManager implements CallbackManager { | |||
integrationTestChannel.setMethodCallHandler(_onMethodChannelCall); | |||
final List<int>? rawBytes = await integrationTestChannel.invokeMethod<List<int>>( | |||
'captureScreenshot', | |||
null, | |||
<String, dynamic>{'name': screenshot}, |
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 above !_usesFlutterImage
if statement could also check if Platform.isAndroid
// Whether the Flutter surface uses an Image. | ||
bool _usesFlutterImage = false; | ||
// Whether the Flutter surface uses an Image (Android only). | ||
bool _usesFlutterImage = false || !Platform.isAndroid; | ||
|
||
@override | ||
Future<void> convertFlutterSurfaceToImage() async { |
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.
it would need to noop if !Platform.isAndroid
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 meant to make it so it was never set to false on !Platform.isAndroid
, let me clean this up.
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 % nits
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 with nits. Shouldn't we have a test of this functionality that screenshots a dummy plugin and compares it to a golden image though?
I think the next step for @blasten after I commit this was to set up the screenshot integration tests. But I should also write some iOS native tests.
- (BOOL)testIntegrationTest:(NSString **)testResult; | ||
- (instancetype)initWithScreenshotDelegate:(nullable id<FLTIntegrationTestScreenshotDelegate>)delegate NS_DESIGNATED_INITIALIZER; | ||
|
||
- (BOOL)testIntegrationTest:(NSString *_Nullable *_Nullable)testResult; |
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.
This API is very weird (I just added the nullability), and the INTEGRATION_TEST_IOS_RUNNER
macro is downright Swift-hostile...
} else { | ||
result(FlutterMethodNotImplemented); | ||
} | ||
} | ||
|
||
- (UIImage *)capturePngScreenshot { | ||
UIWindow *window = [UIApplication.sharedApplication.windows filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"keyWindow = YES"]].firstObject; |
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 don't think there are any formatters (even dartfmt) running on flutter/flutter (plus I hate how clang formatter mangles Obj-C blocks). Let me shorten these up.
// Whether the Flutter surface uses an Image. | ||
bool _usesFlutterImage = false; | ||
// Whether the Flutter surface uses an Image (Android only). | ||
bool _usesFlutterImage = false || !Platform.isAndroid; | ||
|
||
@override | ||
Future<void> convertFlutterSurfaceToImage() async { |
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 meant to make it so it was never set to false on !Platform.isAndroid
, let me clean this up.
There will be some test harness work needed for the native side. Filed #87770. We'll get some unit tests for this going soon. |
7d9f321
to
89afca0
Compare
🎉 |
Implement the native iOS screenshot side of #84472. Added an optional "name" argument for the "captureScreenshot" method.
When run as a native Xcode test, the screenshots are saved to the Xcode test results bundle in addition to the bytes being passed back over the channel.
![Screen Shot 2021-07-22 at 4 32 46 PM](https://user-images.githubusercontent.com/682784/126721501-b85945a2-85ee-4398-80bc-786571f74e47.png)
Screenshot is the app window, not including the status bar, etc.
![public png_1_7EACEC54-4CF2-42E1-A6B3-D203D265DD1E](https://user-images.githubusercontent.com/682784/121979141-7f291f80-cd3e-11eb-8167-85eac5fb3368.png)
iOS screenshot prototype of #83856