Verified Commit aa52cef5 authored by Geoff Pado's avatar Geoff Pado

Handle photo permissions restricted state

parent 586ae6e4
......@@ -137,7 +137,7 @@
041EFF0C2251A9F50058D8EE /* HighlighterTests */ = {
isa = PBXGroup;
children = (
041EFF0D2251A9F50058D8EE /* HighlighterTests.swift */,
04D68BCD2262B9BF00D09BBD /* Photo Selection */,
041EFF0F2251A9F50058D8EE /* Info.plist */,
);
path = HighlighterTests;
......@@ -207,6 +207,22 @@
path = "Photo Permissions";
sourceTree = "<group>";
};
04D68BCD2262B9BF00D09BBD /* Photo Selection */ = {
isa = PBXGroup;
children = (
04D68BCE2262BA0E00D09BBD /* Intro View */,
);
path = "Photo Selection";
sourceTree = "<group>";
};
04D68BCE2262BA0E00D09BBD /* Intro View */ = {
isa = PBXGroup;
children = (
041EFF0D2251A9F50058D8EE /* HighlighterTests.swift */,
);
path = "Intro View";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
......
......@@ -14,4 +14,8 @@
"PhotoPermissionsDeniedAlertController.actionButtonTitle" = "Open Settings";
"PhotoPermissionsDeniedAlertController.cancelButtonTitle" = "Dismiss";
"PhotoPermissionsRestrictedAlertController.alertTitle" = "Photos Access Restricted";
"PhotoPermissionsRestrictedAlertController.alertMessage" = "Black Highlighter needs permission to edit your photos. However, restrictions on your device prevent that access. Ask whoever controls permissions for you to grant access to the photo library to Black Highlighter.";
"PhotoPermissionsRestrictedAlertController.dismissButtonTitle" = "Dismiss";
"PhotoSelectionViewController.navigationItemTitle" = "Photos";
......@@ -4,7 +4,8 @@
import UIKit
class IntroViewController: UIViewController {
init() {
init(permissionsRequester: PhotoPermissionsRequester = PhotoPermissionsRequester()) {
self.permissionsRequester = permissionsRequester
super.init(nibName: nil, bundle: nil)
}
......@@ -18,8 +19,7 @@ class IntroViewController: UIViewController {
case .authorized:
UIApplication.shared.sendAction(#selector(PhotoSelectionViewController.showPhotoLibrary), to: nil, from: self, for: nil)
case .restricted:
#warning("handle restricted state")
fatalError("handle restricted state")
self?.present(PhotoPermissionsRestrictedAlertController(), animated: true)
case .denied:
self?.present(PhotoPermissionsDeniedAlertController(), animated: true)
case .notDetermined:
......@@ -30,11 +30,9 @@ class IntroViewController: UIViewController {
}
}
// MARK: Boilerplate
private let permissionsRequester = PhotoPermissionsRequester()
private let permissionsRequester: PhotoPermissionsRequester
@available(*, unavailable)
required init(coder: NSCoder) {
......
......@@ -35,3 +35,30 @@ class PhotoPermissionsDeniedAlertController: UIAlertController {
fatalError("\(className) does not implement init(coder:)")
}
}
class PhotoPermissionsRestrictedAlertController: UIAlertController {
init() {
super.init(nibName: nil, bundle: nil)
title = PhotoPermissionsRestrictedAlertController.alertTitle
message = PhotoPermissionsRestrictedAlertController.alertMessage
addAction(dismissAction)
}
private let dismissAction = UIAlertAction(title: PhotoPermissionsRestrictedAlertController.dismissButtonTitle, style: .cancel, handler: nil)
// MARK: Boilerplate
override var preferredStyle: UIAlertController.Style { return .alert }
private static let alertTitle = NSLocalizedString("PhotoPermissionsRestrictedAlertController.alertTitle", comment: "Title for the photo permissions restricted alert")
private static let alertMessage = NSLocalizedString("PhotoPermissionsRestrictedAlertController.alertMessage", comment: "Message for the photo permissions restricted alert")
private static let dismissButtonTitle = NSLocalizedString("PhotoPermissionsRestrictedAlertController.dismissButtonTitle", comment: "Title for the cancel button on the photo permissions restricted alert")
@available(*, unavailable)
required init(coder: NSCoder) {
let className = String(describing: type(of: self))
fatalError("\(className) does not implement init(coder:)")
}
}
//
// HighlighterTests.swift
// HighlighterTests
//
// Created by Geoff Pado on 3/31/19.
// Copyright © 2019 Cocoatype, LLC. All rights reserved.
//
import XCTest
@testable import Highlighter
class HighlighterTests: XCTestCase {
override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
// Created by Geoff Pado on 3/31/19.
// Copyright © 2019 Cocoatype, LLC. All rights reserved.
import Photos
import XCTest
@testable import Highlighter
class IntroViewControllerTests: XCTestCase {
func testDisplayingDeniedAlert() {
let permissionsRequester = MockPhotoPermissionsRequester(desiredAuthorizationStatus: .denied)
let viewController = PresentationExpectationMockIntroViewController(permissionsRequester: permissionsRequester)
viewController.presentedViewControllerExpectedType = PhotoPermissionsDeniedAlertController.self
viewController.presentationExpectation = expectation(description: "denied alert is shown")
viewController.requestPermission()
waitForExpectations(timeout: 1)
}
func testDisplayingRestrictedAlert() {
let permissionsRequester = MockPhotoPermissionsRequester(desiredAuthorizationStatus: .restricted)
let viewController = PresentationExpectationMockIntroViewController(permissionsRequester: permissionsRequester)
viewController.presentedViewControllerExpectedType = PhotoPermissionsRestrictedAlertController.self
viewController.presentationExpectation = expectation(description: "restricted alert is shown")
viewController.requestPermission()
waitForExpectations(timeout: 1)
}
class MockPhotoPermissionsRequester: PhotoPermissionsRequester {
init(desiredAuthorizationStatus: PHAuthorizationStatus) {
self.authorizationStatus = desiredAuthorizationStatus
super.init()
}
var authorizationStatus: PHAuthorizationStatus
override func requestAuthorization(_ handler: @escaping (PHAuthorizationStatus) -> Void) {
handler(authorizationStatus)
}
}
class PresentationExpectationMockIntroViewController: IntroViewController {
var presentedViewControllerExpectedType: UIViewController.Type?
var presentationExpectation: XCTestExpectation?
override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
guard let expectedType = presentedViewControllerExpectedType else { return }
if viewControllerToPresent.isKind(of: expectedType) {
presentationExpectation?.fulfill()
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment