Skip to content
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

Refactor WMFLocationManager to Swift #3

Open
wants to merge 19 commits into
base: develop
from
Open
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

Add LocationManager skeleton and update LocationManagerTests

  • Loading branch information
jantimar authored and VojtaStavik committed Feb 28, 2020
commit 269d184ec8764ab622923c6ea55990ccd7e10a9d
@@ -0,0 +1,70 @@
import UIKit
import CoreLocation

public struct LocationManagerConfiguration {
let accuracy: CLLocationAccuracy
let filter: CLLocationDistance
var activityType: CLActivityType = .fitness
}

extension LocationManagerConfiguration {
/// A configuration preset for fine location updates.
public static let fine = LocationManagerConfiguration(
accuracy: kCLLocationAccuracyBest,
filter: 1
)

/// A configuration preset for coarse location updates.
public static let coarse = LocationManagerConfiguration(
accuracy: kCLLocationAccuracyKilometer,
filter: 1000
)
}

// MARK: - LocationManagerDelegate
public protocol LocationManagerDelegate: class {
func locationManager(_ locationManager: LocationManager, didUpdate location: CLLocation)
func locationManager(_ locationManager: LocationManager, didUpdate heading: CLHeading)
func locationManager(_ locationManager: LocationManager, didReceive error: Error)
func locationManager(_ locationManager: LocationManager, didUpdateAuthorized authorized: Bool)
}

final public class LocationManager: NSObject {

/// The latest known location.
public var location: CLLocation? { fatalError() }

/// The latest known heading.
public var heading: CLHeading? { fatalError() }

/// Returns `true` when the location and heading monitoring is active.
public private(set) var isUpdating = false

/// Set the delegate if you want to receive location and heading updates.
public var delegate: LocationManagerDelegate?

/// Returns the current locationManager permission state.
public var autorizationStatus: CLAuthorizationStatus { fatalError() }

/// Starts monitoring location and heading updates.
public func startMonitoringLocation() { }

/// Stops monitoring location and heading updates.
public func stopMonitoringLocation() { }

/// Creates a new instance of `LocationManager`.
///
/// - Parameters:
/// - locationManager: If needed, provide a custom `CLLocationManager` instance. The default
/// value creates a new instance.
/// - device: If needed, provide a custom `UIDevice` instance. The default value is `UIDevice.current`.
/// - configuration: The configuration used for configuring `CLLocationManager`. The default value
/// is the `.fine` preset.
///
public init(
locationManager: CLLocationManager = .init(),
device: UIDevice = .current,
configuration: LocationManagerConfiguration = .fine
) { }
}
@@ -1292,6 +1292,7 @@
A452F9F924081A5500D8ED09 /* MockCLHeading.swift in Sources */ = {isa = PBXBuildFile; fileRef = A452F9F724081A5500D8ED09 /* MockCLHeading.swift */; };
A452F9FB24081A7200D8ED09 /* LocationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A452F9FA24081A7200D8ED09 /* LocationManagerTests.swift */; };
A452F9FD24081B0200D8ED09 /* MockUIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = A452F9FC24081B0200D8ED09 /* MockUIDevice.swift */; };
A4C558BF2403D7E300AFBFDC /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4C558BE2403D7E200AFBFDC /* LocationManager.swift */; };
B00050141C52D73800515F70 /* UIApplication+RTL.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00050131C52D73800515F70 /* UIApplication+RTL.swift */; };
B0016CB921354D9D00FA1096 /* AutoLayoutSafeMultiLineButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0016CB821354D9D00FA1096 /* AutoLayoutSafeMultiLineButton.swift */; };
B0016CBA21354D9D00FA1096 /* AutoLayoutSafeMultiLineButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0016CB821354D9D00FA1096 /* AutoLayoutSafeMultiLineButton.swift */; };
A452F9F724081A5500D8ED09 /* MockCLHeading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockCLHeading.swift; sourceTree = "<group>"; };
A452F9FA24081A7200D8ED09 /* LocationManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationManagerTests.swift; sourceTree = "<group>"; };
A452F9FC24081B0200D8ED09 /* MockUIDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockUIDevice.swift; sourceTree = "<group>"; };
A4C558BE2403D7E200AFBFDC /* LocationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = "<group>"; };
B00050131C52D73800515F70 /* UIApplication+RTL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIApplication+RTL.swift"; sourceTree = "<group>"; };
B0016CB821354D9D00FA1096 /* AutoLayoutSafeMultiLineButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoLayoutSafeMultiLineButton.swift; sourceTree = "<group>"; };
B0016CBE2136105900FA1096 /* SetupButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupButton.swift; sourceTree = "<group>"; };
0E03E2961B844D7700C1FBD7 /* Location Manager */ = {
isa = PBXGroup;
children = (
A4C558BE2403D7E200AFBFDC /* LocationManager.swift */,
B0E802F91C0CD4EC0065EBC0 /* WMFLocationManager.h */,
B0E802FA1C0CD4EC0065EBC0 /* WMFLocationManager.m */,
BC3944C31C8146210008546D /* CLLocationManager+WMFLocationManagers.h */,
83F1095B23D07E5D003F3E9E /* APIURLComponentsBuilder.swift in Sources */,
D84C35F11F323CCA00895FA1 /* CollectionViewCell.swift in Sources */,
67A6F13823BFB75300736539 /* ImageCacheDBWriter.swift in Sources */,
A4C558BF2403D7E300AFBFDC /* LocationManager.swift in Sources */,
D8FA18F41E1BDA35009675C3 /* UIImage+WMFNormalization.m in Sources */,
D8CD97651E83FAB400ECCA9D /* Cache.xcdatamodeld in Sources */,
6779D45924007AF0002840CA /* MWKImageInfoFetcher.m in Sources */,
@@ -5,7 +5,7 @@ final class LocationManagerTests: XCTestCase {

private var mockCLLocationManager: MockCLLocationManager!
private var mockDevice: MockUIDevice!
private var locationManager: WMFLocationManager!
private var locationManager: LocationManager!
private var delegate: TestLocationManagerDelegate!

override func setUp() {
@@ -16,26 +16,31 @@ final class LocationManagerTests: XCTestCase {

mockDevice = MockUIDevice(orientation: .unknown)

locationManager = WMFLocationManager(locationManager: mockCLLocationManager, device: mockDevice)
locationManager = LocationManager(
locationManager: mockCLLocationManager,
device: mockDevice
)

delegate = TestLocationManagerDelegate()
locationManager.delegate = delegate
}

// MARK: - WMFLocationManager tests
// MARK: - LocationManager tests
func testFineLocationManager() {
let locationManager = WMFLocationManager.fine()
XCTAssertEqual(locationManager.locationManager.distanceFilter, 1)
XCTAssertEqual(locationManager.locationManager.desiredAccuracy, kCLLocationAccuracyBest)
XCTAssertEqual(locationManager.locationManager.activityType, .fitness)
let clLocationManager = CLLocationManager()
_ = LocationManager(locationManager: clLocationManager, configuration: .fine)
XCTAssertEqual(clLocationManager.distanceFilter, 1)
XCTAssertEqual(clLocationManager.desiredAccuracy, kCLLocationAccuracyBest)
XCTAssertEqual(clLocationManager.activityType, .fitness)
}

func testCoarseLocationManager() {
let locationManager = WMFLocationManager.coarse()
XCTAssertEqual(locationManager.locationManager.distanceFilter, 1000)
XCTAssertEqual(locationManager.locationManager.desiredAccuracy, kCLLocationAccuracyKilometer)
XCTAssertEqual(locationManager.locationManager.activityType, .fitness)
let clLocationManager = CLLocationManager()
_ = LocationManager(locationManager: clLocationManager, configuration: .coarse)
XCTAssertEqual(clLocationManager.distanceFilter, 1000)
XCTAssertEqual(clLocationManager.desiredAccuracy, kCLLocationAccuracyKilometer)
XCTAssertEqual(clLocationManager.activityType, .fitness)
}

func testStartMonitoring() {
@@ -107,34 +112,22 @@ final class LocationManagerTests: XCTestCase {
func testAuthorizedStatus() {
// Test authorizedAlways status.
mockCLLocationManager.simulate(authorizationStatus: .authorizedAlways)
XCTAssertEqual(locationManager.isAuthorized(), true)
XCTAssertEqual(locationManager.isAuthorizationNotDetermined(), false)
XCTAssertEqual(locationManager.isAuthorizationDenied(), false)
XCTAssertEqual(locationManager.isAuthorizationRestricted(), false)
XCTAssertEqual(locationManager.autorizationStatus, .authorizedAlways)

// Test notDetermined status.
mockCLLocationManager.simulate(authorizationStatus: .notDetermined)
XCTAssertEqual(locationManager.isAuthorized(), false)
XCTAssertEqual(locationManager.isAuthorizationNotDetermined(), true)
XCTAssertEqual(locationManager.isAuthorizationDenied(), false)
XCTAssertEqual(locationManager.isAuthorizationRestricted(), false)
XCTAssertEqual(locationManager.autorizationStatus, .notDetermined)

// Test denied status.
mockCLLocationManager.simulate(authorizationStatus: .denied)
XCTAssertEqual(locationManager.isAuthorized(), false)
XCTAssertEqual(locationManager.isAuthorizationNotDetermined(), false)
XCTAssertEqual(locationManager.isAuthorizationDenied(), true)
XCTAssertEqual(locationManager.isAuthorizationRestricted(), false)
XCTAssertEqual(locationManager.autorizationStatus, .denied)

// Test restricted status.
mockCLLocationManager.simulate(authorizationStatus: .restricted)
XCTAssertEqual(locationManager.isAuthorized(), false)
XCTAssertEqual(locationManager.isAuthorizationNotDetermined(), false)
XCTAssertEqual(locationManager.isAuthorizationDenied(), false)
XCTAssertEqual(locationManager.isAuthorizationRestricted(), true)
XCTAssertEqual(locationManager.autorizationStatus, .restricted)
}

// MARK: - WMFLocationManagerDelegate tests
// MARK: - LocationManagerDelegate tests
func testUpdateLocation() {
locationManager.startMonitoringLocation()
@@ -153,7 +146,7 @@ final class LocationManagerTests: XCTestCase {
let location = CLLocation(latitude: 10, longitude: 20)
mockCLLocationManager.simulateUpdate(location: location)
let locationManager = WMFLocationManager(locationManager: mockCLLocationManager)
let locationManager = LocationManager(locationManager: mockCLLocationManager)

// `locationManager.startMonitoringLocation()` is not called.
@@ -177,7 +170,7 @@ final class LocationManagerTests: XCTestCase {
let heading = MockCLHeading(headingAccuracy: 10)
mockCLLocationManager.simulateUpdate(heading: heading)
let locationManager = WMFLocationManager(locationManager: mockCLLocationManager)
let locationManager = LocationManager(locationManager: mockCLLocationManager)

// `locationManager.startMonitoringLocation()` is not called.
@@ -260,14 +253,14 @@ final class LocationManagerTests: XCTestCase {

locationManager.stopMonitoringLocation()
XCTAssertEqual(mockDevice.beginGeneratingDeviceOrientationCount, 1)
// XCTAssertEqual(mockDevice.endGeneratingDeviceOrientationCount, 1) - currently failing
XCTAssertEqual(mockDevice.endGeneratingDeviceOrientationCount, 1)

// Verify `stopMonitoringLocation()` is idempotent.
locationManager.stopMonitoringLocation()
locationManager.stopMonitoringLocation()
locationManager.stopMonitoringLocation()
XCTAssertEqual(mockDevice.beginGeneratingDeviceOrientationCount, 1)
// XCTAssertEqual(mockDevice.endGeneratingDeviceOrientationCount, 1) - currently failing
XCTAssertEqual(mockDevice.endGeneratingDeviceOrientationCount, 1)
}

func testMonitoringStopsWhenDeallocated() {
@@ -291,26 +284,26 @@ final class LocationManagerTests: XCTestCase {
}
}

/// A test implementation of `WMFLocationManagerDelegate`.
private final class TestLocationManagerDelegate: NSObject, WMFLocationManagerDelegate {
/// A test implementation of `LocationManagerDelegate`.
private final class TestLocationManagerDelegate: LocationManagerDelegate {
private(set) var heading: CLHeading?
private(set) var location: CLLocation?
private(set) var error: Error?
private(set) var authorized: Bool?

func locationManager(_ controller: WMFLocationManager, didReceiveError error: Error) {
func locationManager(_ locationManager: LocationManager, didReceive error: Error) {
self.error = error
}

func locationManager(_ controller: WMFLocationManager, didUpdate heading: CLHeading) {
func locationManager(_ locationManager: LocationManager, didUpdate heading: CLHeading) {
self.heading = heading
}

func locationManager(_ controller: WMFLocationManager, didUpdate location: CLLocation) {
func locationManager(_ locationManager: LocationManager, didUpdate location: CLLocation) {
self.location = location
}

func locationManager(_ controller: WMFLocationManager, didChangeEnabledState enabled: Bool) {
self.authorized = enabled
func locationManager(_ locationManager: LocationManager, didUpdateAuthorized authorized: Bool) {
self.authorized = authorized
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.