@@ -15,6 +15,8 @@ @interface CameraPermissionTests : XCTestCase
1515
1616@implementation CameraPermissionTests
1717
18+ #pragma mark - camera permissions
19+
1820- (void )testRequestCameraPermission_completeWithoutErrorIfPrevoiuslyAuthorized {
1921 XCTestExpectation *expectation =
2022 [self expectationWithDescription:
@@ -24,7 +26,7 @@ - (void)testRequestCameraPermission_completeWithoutErrorIfPrevoiuslyAuthorized {
2426 OCMStub ([mockDevice authorizationStatusForMediaType: AVMediaTypeVideo])
2527 .andReturn (AVAuthorizationStatusAuthorized);
2628
27- FLTRequestCameraPermissionWithCompletionHandler ( ^(FlutterError *error) {
29+ FLTRequestCameraPermission ( /* forAudio */ false , ^(FlutterError *error) {
2830 if (error == nil ) {
2931 [expectation fulfill ];
3032 }
@@ -44,7 +46,7 @@ - (void)testRequestCameraPermission_completeWithErrorIfPreviouslyDenied {
4446 id mockDevice = OCMClassMock ([AVCaptureDevice class ]);
4547 OCMStub ([mockDevice authorizationStatusForMediaType: AVMediaTypeVideo])
4648 .andReturn (AVAuthorizationStatusDenied);
47- FLTRequestCameraPermissionWithCompletionHandler ( ^(FlutterError *error) {
49+ FLTRequestCameraPermission ( /* forAudio */ false , ^(FlutterError *error) {
4850 if ([error isEqual: expectedError]) {
4951 [expectation fulfill ];
5052 }
@@ -63,7 +65,7 @@ - (void)testRequestCameraPermission_completeWithErrorIfRestricted {
6365 OCMStub ([mockDevice authorizationStatusForMediaType: AVMediaTypeVideo])
6466 .andReturn (AVAuthorizationStatusRestricted);
6567
66- FLTRequestCameraPermissionWithCompletionHandler ( ^(FlutterError *error) {
68+ FLTRequestCameraPermission ( /* forAudio */ false , ^(FlutterError *error) {
6769 if ([error isEqual: expectedError]) {
6870 [expectation fulfill ];
6971 }
@@ -85,7 +87,7 @@ - (void)testRequestCameraPermission_completeWithoutErrorIfUserGrantAccess {
8587 return YES ;
8688 }]]);
8789
88- FLTRequestCameraPermissionWithCompletionHandler ( ^(FlutterError *error) {
90+ FLTRequestCameraPermission ( /* forAudio */ false , ^(FlutterError *error) {
8991 if (error == nil ) {
9092 [grantedExpectation fulfill ];
9193 }
@@ -111,7 +113,113 @@ - (void)testRequestCameraPermission_completeWithErrorIfUserDenyAccess {
111113 block (NO );
112114 return YES ;
113115 }]]);
114- FLTRequestCameraPermissionWithCompletionHandler (^(FlutterError *error) {
116+ FLTRequestCameraPermission (/* forAudio*/ false , ^(FlutterError *error) {
117+ if ([error isEqual: expectedError]) {
118+ [expectation fulfill ];
119+ }
120+ });
121+
122+ [self waitForExpectationsWithTimeout: 1 handler: nil ];
123+ }
124+
125+ #pragma mark - audio permissions
126+
127+ - (void )testRequestAudioPermission_completeWithoutErrorIfPrevoiuslyAuthorized {
128+ XCTestExpectation *expectation =
129+ [self expectationWithDescription:
130+ @" Must copmlete without error if audio access was previously authorized." ];
131+
132+ id mockDevice = OCMClassMock ([AVCaptureDevice class ]);
133+ OCMStub ([mockDevice authorizationStatusForMediaType: AVMediaTypeAudio])
134+ .andReturn (AVAuthorizationStatusAuthorized);
135+
136+ FLTRequestCameraPermission (/* forAudio*/ true , ^(FlutterError *error) {
137+ if (error == nil ) {
138+ [expectation fulfill ];
139+ }
140+ });
141+ [self waitForExpectationsWithTimeout: 1 handler: nil ];
142+ }
143+ - (void )testRequestAudioPermission_completeWithErrorIfPreviouslyDenied {
144+ XCTestExpectation *expectation =
145+ [self expectationWithDescription:
146+ @" Must complete with error if audio access was previously denied." ];
147+ FlutterError *expectedError =
148+ [FlutterError errorWithCode: @" AudioAccessDeniedWithoutPrompt"
149+ message: @" User has previously denied the audio access request. Go to "
150+ @" Settings to enable audio access."
151+ details: nil ];
152+
153+ id mockDevice = OCMClassMock ([AVCaptureDevice class ]);
154+ OCMStub ([mockDevice authorizationStatusForMediaType: AVMediaTypeAudio])
155+ .andReturn (AVAuthorizationStatusDenied);
156+ FLTRequestCameraPermission (/* forAudio*/ true , ^(FlutterError *error) {
157+ if ([error isEqual: expectedError]) {
158+ [expectation fulfill ];
159+ }
160+ });
161+ [self waitForExpectationsWithTimeout: 1 handler: nil ];
162+ }
163+
164+ - (void )testRequestAudioPermission_completeWithErrorIfRestricted {
165+ XCTestExpectation *expectation =
166+ [self expectationWithDescription: @" Must complete with error if audio access is restricted." ];
167+ FlutterError *expectedError = [FlutterError errorWithCode: @" AudioAccessRestricted"
168+ message: @" Audio access is restricted. "
169+ details: nil ];
170+
171+ id mockDevice = OCMClassMock ([AVCaptureDevice class ]);
172+ OCMStub ([mockDevice authorizationStatusForMediaType: AVMediaTypeAudio])
173+ .andReturn (AVAuthorizationStatusRestricted);
174+
175+ FLTRequestCameraPermission (/* forAudio*/ true , ^(FlutterError *error) {
176+ if ([error isEqual: expectedError]) {
177+ [expectation fulfill ];
178+ }
179+ });
180+ [self waitForExpectationsWithTimeout: 1 handler: nil ];
181+ }
182+
183+ - (void )testRequestAudioPermission_completeWithoutErrorIfUserGrantAccess {
184+ XCTestExpectation *grantedExpectation = [self
185+ expectationWithDescription: @" Must complete without error if user choose to grant access" ];
186+
187+ id mockDevice = OCMClassMock ([AVCaptureDevice class ]);
188+ OCMStub ([mockDevice authorizationStatusForMediaType: AVMediaTypeAudio])
189+ .andReturn (AVAuthorizationStatusNotDetermined);
190+ // Mimic user choosing "allow" in permission dialog.
191+ OCMStub ([mockDevice requestAccessForMediaType: AVMediaTypeAudio
192+ completionHandler: [OCMArg checkWithBlock: ^BOOL (void (^block)(BOOL )) {
193+ block (YES );
194+ return YES ;
195+ }]]);
196+
197+ FLTRequestCameraPermission (/* forAudio*/ true , ^(FlutterError *error) {
198+ if (error == nil ) {
199+ [grantedExpectation fulfill ];
200+ }
201+ });
202+ [self waitForExpectationsWithTimeout: 1 handler: nil ];
203+ }
204+
205+ - (void )testRequestAudioPermission_completeWithErrorIfUserDenyAccess {
206+ XCTestExpectation *expectation =
207+ [self expectationWithDescription: @" Must complete with error if user choose to deny access" ];
208+ FlutterError *expectedError = [FlutterError errorWithCode: @" AudioAccessDenied"
209+ message: @" User denied the audio access request."
210+ details: nil ];
211+
212+ id mockDevice = OCMClassMock ([AVCaptureDevice class ]);
213+ OCMStub ([mockDevice authorizationStatusForMediaType: AVMediaTypeAudio])
214+ .andReturn (AVAuthorizationStatusNotDetermined);
215+
216+ // Mimic user choosing "deny" in permission dialog.
217+ OCMStub ([mockDevice requestAccessForMediaType: AVMediaTypeAudio
218+ completionHandler: [OCMArg checkWithBlock: ^BOOL (void (^block)(BOOL )) {
219+ block (NO );
220+ return YES ;
221+ }]]);
222+ FLTRequestCameraPermission (/* forAudio*/ true , ^(FlutterError *error) {
115223 if ([error isEqual: expectedError]) {
116224 [expectation fulfill ];
117225 }
0 commit comments