From 165b15cf21da3da08b436e5e42055f263bff625a Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 12 Oct 2021 11:07:04 +0200 Subject: [PATCH 1/5] Refactored unit test to prevent usage of XCUIDevice. Refactored the unit test so it no longer relies on the XCUIDevice class which can only be used by UI tests starting from Xcode 13 and higher. --- .../ios/RunnerTests/CameraOrientationTests.m | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m index 6c29ef7b2866..f5be69bbef4e 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m @@ -2,31 +2,34 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@import camera; @import XCTest; - +#import #import +@interface CameraPlugin : NSObject +- (instancetype)initWithRegistry:(NSObject *)registry + messenger:(NSObject *)messenger; + +- (void)orientationChanged:(NSNotification *)note; +@end + @interface CameraOrientationTests : XCTestCase -@property(strong, nonatomic) id mockRegistrar; @property(strong, nonatomic) id mockMessenger; +@property(strong, nonatomic) CameraPlugin *cameraPlugin; @end @implementation CameraOrientationTests - (void)setUp { [super setUp]; - self.mockRegistrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); + self.mockMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); - OCMStub([self.mockRegistrar messenger]).andReturn(self.mockMessenger); + self.cameraPlugin = [[CameraPlugin alloc] initWithRegistry:nil messenger:_mockMessenger]; } - (void)testOrientationNotifications { id mockMessenger = self.mockMessenger; [mockMessenger setExpectationOrderMatters:YES]; - XCUIDevice.sharedDevice.orientation = UIDeviceOrientationPortrait; - - [CameraPlugin registerWithRegistrar:self.mockRegistrar]; [self rotate:UIDeviceOrientationPortraitUpsideDown expectedChannelOrientation:@"portraitDown"]; [self rotate:UIDeviceOrientationPortrait expectedChannelOrientation:@"portraitUp"]; @@ -34,34 +37,43 @@ - (void)testOrientationNotifications { [self rotate:UIDeviceOrientationLandscapeLeft expectedChannelOrientation:@"landscapeRight"]; OCMReject([mockMessenger sendOnChannel:[OCMArg any] message:[OCMArg any]]); - // No notification when orientation doesn't change. - XCUIDevice.sharedDevice.orientation = UIDeviceOrientationLandscapeLeft; + // No notification when flat. - XCUIDevice.sharedDevice.orientation = UIDeviceOrientationFaceUp; + [self.cameraPlugin + orientationChanged:[self createMockNotificationForOrientation:UIDeviceOrientationFaceUp]]; // No notification when facedown. - XCUIDevice.sharedDevice.orientation = UIDeviceOrientationFaceDown; + [self.cameraPlugin + orientationChanged:[self createMockNotificationForOrientation:UIDeviceOrientationFaceDown]]; OCMVerifyAll(mockMessenger); } - (void)rotate:(UIDeviceOrientation)deviceOrientation - expectedChannelOrientation:(NSString*)channelOrientation { + expectedChannelOrientation:(NSString *)channelOrientation { id mockMessenger = self.mockMessenger; - XCTestExpectation* orientationExpectation = [self expectationWithDescription:channelOrientation]; + XCTestExpectation *orientationExpectation = [self expectationWithDescription:channelOrientation]; OCMExpect([mockMessenger sendOnChannel:[OCMArg any] - message:[OCMArg checkWithBlock:^BOOL(NSData* data) { - NSObject* codec = [FlutterStandardMethodCodec sharedInstance]; - FlutterMethodCall* methodCall = [codec decodeMethodCall:data]; + message:[OCMArg checkWithBlock:^BOOL(NSData *data) { + NSObject *codec = [FlutterStandardMethodCodec sharedInstance]; + FlutterMethodCall *methodCall = [codec decodeMethodCall:data]; [orientationExpectation fulfill]; return [methodCall.method isEqualToString:@"orientation_changed"] && [methodCall.arguments isEqualToDictionary:@{@"orientation" : channelOrientation}]; }]]); - XCUIDevice.sharedDevice.orientation = deviceOrientation; + [self.cameraPlugin + orientationChanged:[self createMockNotificationForOrientation:deviceOrientation]]; [self waitForExpectationsWithTimeout:30.0 handler:nil]; } +- (NSNotification *)createMockNotificationForOrientation:(UIDeviceOrientation)deviceOrientation { + UIDevice *mockDevice = OCMClassMock([UIDevice class]); + OCMStub([mockDevice orientation]).andReturn(deviceOrientation); + + return [[NSNotification alloc] initWithName:@"orientation_test" object:mockDevice userInfo:nil]; +} + @end From d9292ba30290c3629e62b22c7d7783bbdedf4688 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 12 Oct 2021 11:11:49 +0200 Subject: [PATCH 2/5] Add changelog description --- packages/camera/camera/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index c9dfc63eb46c..98744d627f7f 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT -* Updated package description. +* Updated package description; +* Refactor unit test on iOS to make it compatible with new restrictions in Xcode 13 which only supports the use of the `XCUIDevice` in Xcode UI tests. ## 0.9.4+1 From 6083b9300e7ac11b0d118551cd3918bf41a82bdc Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 12 Oct 2021 21:35:18 +0200 Subject: [PATCH 3/5] Replace use of ivar with synthesized property --- .../camera/example/ios/RunnerTests/CameraOrientationTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m index f5be69bbef4e..47f1b9071f18 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m @@ -24,7 +24,7 @@ - (void)setUp { [super setUp]; self.mockMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); - self.cameraPlugin = [[CameraPlugin alloc] initWithRegistry:nil messenger:_mockMessenger]; + self.cameraPlugin = [[CameraPlugin alloc] initWithRegistry:nil messenger:self.mockMessenger]; } - (void)testOrientationNotifications { From 8af03a650bf5092dc7149bb08211711d1fe13e2d Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Tue, 12 Oct 2021 19:03:35 -0700 Subject: [PATCH 4/5] [camera] Add camera test module map --- .../ios/RunnerTests/CameraOrientationTests.m | 9 ++------- .../camera/camera/ios/Classes/CameraPlugin.m | 2 ++ .../camera/ios/Classes/CameraPlugin.modulemap | 10 ++++++++++ .../camera/ios/Classes/CameraPlugin_Test.h | 19 +++++++++++++++++++ .../camera/ios/Classes/camera-umbrella.h | 9 +++++++++ packages/camera/camera/ios/camera.podspec | 3 ++- 6 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 packages/camera/camera/ios/Classes/CameraPlugin.modulemap create mode 100644 packages/camera/camera/ios/Classes/CameraPlugin_Test.h create mode 100644 packages/camera/camera/ios/Classes/camera-umbrella.h diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m index 47f1b9071f18..a3dd4267b888 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m @@ -2,17 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +@import camera; +@import camera.Test; @import XCTest; #import #import -@interface CameraPlugin : NSObject -- (instancetype)initWithRegistry:(NSObject *)registry - messenger:(NSObject *)messenger; - -- (void)orientationChanged:(NSNotification *)note; -@end - @interface CameraOrientationTests : XCTestCase @property(strong, nonatomic) id mockMessenger; @property(strong, nonatomic) CameraPlugin *cameraPlugin; diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.m b/packages/camera/camera/ios/Classes/CameraPlugin.m index da560d6c4df7..78c5a34ab05a 100644 --- a/packages/camera/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera/ios/Classes/CameraPlugin.m @@ -3,6 +3,8 @@ // found in the LICENSE file. #import "CameraPlugin.h" +#import "CameraPlugin_Test.h" + #import #import #import diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.modulemap b/packages/camera/camera/ios/Classes/CameraPlugin.modulemap new file mode 100644 index 000000000000..30afa91bdda2 --- /dev/null +++ b/packages/camera/camera/ios/Classes/CameraPlugin.modulemap @@ -0,0 +1,10 @@ +framework module camera { + umbrella header "camera-umbrella.h" + + export * + module * { export * } + + explicit module Test { + header "CameraPlugin_Test.h" + } +} diff --git a/packages/camera/camera/ios/Classes/CameraPlugin_Test.h b/packages/camera/camera/ios/Classes/CameraPlugin_Test.h new file mode 100644 index 000000000000..6952ae0a4aaa --- /dev/null +++ b/packages/camera/camera/ios/Classes/CameraPlugin_Test.h @@ -0,0 +1,19 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This header is available in the Test module. Import via "@import camera.Test;" + +#import + +/// Methods exposed for unit testing. +@interface CameraPlugin () + +- (instancetype)initWithRegistry:(NSObject *)registry + messenger:(NSObject *)messenger + NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; + +- (void)orientationChanged:(NSNotification *)notification; + +@end diff --git a/packages/camera/camera/ios/Classes/camera-umbrella.h b/packages/camera/camera/ios/Classes/camera-umbrella.h new file mode 100644 index 000000000000..5c39401e6261 --- /dev/null +++ b/packages/camera/camera/ios/Classes/camera-umbrella.h @@ -0,0 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import +#import + +FOUNDATION_EXPORT double cameraVersionNumber; +FOUNDATION_EXPORT const unsigned char cameraVersionString[]; diff --git a/packages/camera/camera/ios/camera.podspec b/packages/camera/camera/ios/camera.podspec index 4a142bd4589a..5906bf98af45 100644 --- a/packages/camera/camera/ios/camera.podspec +++ b/packages/camera/camera/ios/camera.podspec @@ -13,8 +13,9 @@ A Flutter plugin to use the camera from your Flutter app. s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.source = { :http => 'https://github.com/flutter/plugins/tree/master/packages/camera' } s.documentation_url = 'https://pub.dev/packages/camera' - s.source_files = 'Classes/**/*' + s.source_files = 'Classes/**/*.{h,m}' s.public_header_files = 'Classes/**/*.h' + s.module_map = 'Classes/CameraPlugin.modulemap' s.dependency 'Flutter' s.platform = :ios, '9.0' From 30f7c8d68942c4277aa0fc71642dc37d88df7aff Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Wed, 13 Oct 2021 19:24:36 +0200 Subject: [PATCH 5/5] Fixed nits from PR and bump patch number. --- packages/camera/camera/CHANGELOG.md | 2 +- .../camera/example/ios/RunnerTests/CameraOrientationTests.m | 5 +++-- packages/camera/camera/pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 98744d627f7f..dc83a4fabca2 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,4 +1,4 @@ -## NEXT +## 0.9.4+2 * Updated package description; * Refactor unit test on iOS to make it compatible with new restrictions in Xcode 13 which only supports the use of the `XCUIDevice` in Xcode UI tests. diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m index a3dd4267b888..246eab90a919 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraOrientationTests.m @@ -5,7 +5,8 @@ @import camera; @import camera.Test; @import XCTest; -#import +@import Flutter; + #import @interface CameraOrientationTests : XCTestCase @@ -68,7 +69,7 @@ - (NSNotification *)createMockNotificationForOrientation:(UIDeviceOrientation)de UIDevice *mockDevice = OCMClassMock([UIDevice class]); OCMStub([mockDevice orientation]).andReturn(deviceOrientation); - return [[NSNotification alloc] initWithName:@"orientation_test" object:mockDevice userInfo:nil]; + return [NSNotification notificationWithName:@"orientation_test" object:mockDevice]; } @end diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 21892b213781..f68d026b206c 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing Dart. repository: https://github.com/flutter/plugins/tree/master/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.4+1 +version: 0.9.4+2 environment: sdk: ">=2.14.0 <3.0.0"