237 lines
8.3 KiB
Swift
237 lines
8.3 KiB
Swift
// Copyright 2013 The Flutter Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import AVFoundation
|
|
import Flutter
|
|
import XCTest
|
|
|
|
@testable import camera_avfoundation
|
|
|
|
private final class MockPermissionService: NSObject, PermissionServicing {
|
|
var authorizationStatusStub: ((AVMediaType) -> AVAuthorizationStatus)?
|
|
var requestAccessStub: ((AVMediaType, @escaping @Sendable (Bool) -> Void) -> Void)?
|
|
|
|
func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus {
|
|
return authorizationStatusStub?(mediaType) ?? .notDetermined
|
|
}
|
|
|
|
func requestAccess(for mediaType: AVMediaType, completion: @escaping @Sendable (Bool) -> Void) {
|
|
requestAccessStub?(mediaType, completion)
|
|
}
|
|
}
|
|
|
|
final class CameraPermissionManagerTests: XCTestCase {
|
|
private func createSutAndMocks() -> (CameraPermissionManager, MockPermissionService) {
|
|
let mockPermissionService = MockPermissionService()
|
|
let permissionManager = CameraPermissionManager(permissionService: mockPermissionService)
|
|
|
|
return (permissionManager, mockPermissionService)
|
|
}
|
|
|
|
// MARK: - Camera permissions
|
|
|
|
func testRequestCameraPermission_completeWithoutErrorIfPreviouslyAuthorized() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete without error if camera access was previously authorized.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .video)
|
|
return .authorized
|
|
}
|
|
permissionManager.requestCameraPermission { error in
|
|
XCTAssertNil(error)
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
func testRequestCameraPermission_completeWithErrorIfPreviouslyDenied() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete with error if camera access was previously denied.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .video)
|
|
return .denied
|
|
}
|
|
permissionManager.requestCameraPermission { error in
|
|
XCTAssertEqual(error?.code, "CameraAccessDeniedWithoutPrompt")
|
|
XCTAssertEqual(
|
|
error?.message,
|
|
"User has previously denied the camera access request. Go to Settings to enable camera access."
|
|
)
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
func testRequestCameraPermission_completeWithErrorIfRestricted() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete with error if camera access is restricted.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .video)
|
|
return .restricted
|
|
}
|
|
permissionManager.requestCameraPermission { error in
|
|
XCTAssertEqual(error?.code, "CameraAccessRestricted")
|
|
XCTAssertEqual(error?.message, "Camera access is restricted.")
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
func testRequestCameraPermission_completeWithoutErrorIfUserGrantAccess() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete without error if user granted access.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .video)
|
|
return .notDetermined
|
|
}
|
|
mockPermissionService.requestAccessStub = { mediaType, handler in
|
|
XCTAssertEqual(mediaType, .video)
|
|
// Grant access.
|
|
handler(true)
|
|
}
|
|
permissionManager.requestCameraPermission { error in
|
|
XCTAssertNil(error)
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
func testRequestCameraPermission_completeWithErrorIfUserDenyAccess() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete with error if user denied access.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .video)
|
|
return .notDetermined
|
|
}
|
|
mockPermissionService.requestAccessStub = { mediaType, handler in
|
|
XCTAssertEqual(mediaType, .video)
|
|
// Deny access.
|
|
handler(false)
|
|
}
|
|
permissionManager.requestCameraPermission { error in
|
|
XCTAssertEqual(error?.code, "CameraAccessDenied")
|
|
XCTAssertEqual(error?.message, "User denied the camera access request.")
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
// MARK: - Audio permissions
|
|
|
|
func testRequestAudioPermission_completeWithoutErrorIfPreviouslyAuthorized() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete without error if audio access was previously authorized.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .audio)
|
|
return .authorized
|
|
}
|
|
permissionManager.requestAudioPermission { error in
|
|
XCTAssertNil(error)
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
func testRequestAudioPermission_completeWithErrorIfPreviouslyDenied() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete with error if audio access was previously denied.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .audio)
|
|
return .denied
|
|
}
|
|
permissionManager.requestAudioPermission { error in
|
|
XCTAssertEqual(error?.code, "AudioAccessDeniedWithoutPrompt")
|
|
XCTAssertEqual(
|
|
error?.message,
|
|
"User has previously denied the audio access request. Go to Settings to enable audio access."
|
|
)
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
func testRequestAudioPermission_completeWithErrorIfRestricted() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete with error if audio access is restricted.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .audio)
|
|
return .restricted
|
|
}
|
|
permissionManager.requestAudioPermission { error in
|
|
XCTAssertEqual(error?.code, "AudioAccessRestricted")
|
|
XCTAssertEqual(error?.message, "Audio access is restricted.")
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
func testRequestAudioPermission_completeWithoutErrorIfUserGrantAccess() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete without error if user granted access.")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .audio)
|
|
return .notDetermined
|
|
}
|
|
mockPermissionService.requestAccessStub = { mediaType, handler in
|
|
XCTAssertEqual(mediaType, .audio)
|
|
// Grant access.
|
|
handler(true)
|
|
}
|
|
permissionManager.requestAudioPermission { error in
|
|
XCTAssertNil(error)
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
|
|
func testRequestAudioPermission_completeWithErrorIfUserDenyAccess() {
|
|
let (permissionManager, mockPermissionService) = createSutAndMocks()
|
|
let expectation = self.expectation(
|
|
description: "Must complete with error if user denied access")
|
|
|
|
mockPermissionService.authorizationStatusStub = { mediaType in
|
|
XCTAssertEqual(mediaType, .audio)
|
|
return .notDetermined
|
|
}
|
|
mockPermissionService.requestAccessStub = { mediaType, handler in
|
|
XCTAssertEqual(mediaType, .audio)
|
|
// Deny access.
|
|
handler(false)
|
|
}
|
|
permissionManager.requestAudioPermission { error in
|
|
XCTAssertEqual(error?.code, "AudioAccessDenied")
|
|
XCTAssertEqual(error?.message, "User denied the audio access request.")
|
|
expectation.fulfill()
|
|
}
|
|
|
|
waitForExpectations(timeout: 30, handler: nil)
|
|
}
|
|
}
|