Files
swift-composable-architectu…/Examples/LocationManager/CommonTests/CommonTests.swift
Brandon Williams 82d2a23e0c ComposableCoreLocation (#120)
* wip

* wip

* wip

* wip

* wip

* basics

* wip

* wip

* wip got LocalSearchClient spm package

* got a common spm package

* basics of desktop

* renamed

* wip

* clean up

* Fix

* clean up

* formatting and remove deprecated

* wip

* move stuff around, readmes

* fix

* clean up

* image

* typo

* docs

* wip

* typo

* rename

* wip

* clean up

* clean up

* rename

* wip

* Update README.md

* custom button

* format

* wip

* fix

* error info

* public interface

* set, alpha

* add error

* fix

* alpha

* internal

* Revert "internal"

This reverts commit 97da6f3086.

* wip

* wip

* docs

* rename

* cleanup

* add fatal error messages to mock

* fixes

* fixes

* clean up

* 13.3 fixes

* another fix

* 13.3 fixes

* wip

* fix mac tests

* wip

* just use double

* fix

* Revert "fix"

This reverts commit 4565a6485f.

* fix

* Fix?

* Fix

* More fix

Co-authored-by: Stephen Celis <stephen@stephencelis.com>
2020-05-20 11:12:59 -07:00

260 lines
7.3 KiB
Swift

import Combine
import ComposableArchitecture
import ComposableCoreLocation
import CoreLocation
import MapKit
import XCTest
#if os(iOS)
import LocationManagerMobile
#elseif os(macOS)
import LocationManagerDesktop
#endif
class LocationManagerTests: XCTestCase {
func testRequestLocation_Allow() {
var didRequestInUseAuthorization = false
var didRequestLocation = false
let locationManagerSubject = PassthroughSubject<LocationManager.Action, Never>()
#if os(iOS)
let store = TestStore(
initialState: AppState(),
reducer: appReducer,
environment: AppEnvironment(
localSearch: .mock(),
locationManager: .mock(
authorizationStatus: { .notDetermined },
create: { _ in locationManagerSubject.eraseToEffect() },
locationServicesEnabled: { true },
requestLocation: { _ in .fireAndForget { didRequestLocation = true } },
requestWhenInUseAuthorization: { _ in
.fireAndForget { didRequestInUseAuthorization = true }
}
)
)
)
#elseif os(macOS)
let store = TestStore(
initialState: AppState(),
reducer: appReducer,
environment: AppEnvironment(
localSearch: .mock(),
locationManager: .mock(
authorizationStatus: { .notDetermined },
create: { _ in locationManagerSubject.eraseToEffect() },
locationServicesEnabled: { true },
requestAlwaysAuthorization: { _ in
.fireAndForget { didRequestInUseAuthorization = true }
},
requestLocation: { _ in .fireAndForget { didRequestLocation = true } }
)
)
)
#endif
let currentLocation = Location(
altitude: 0,
coordinate: CLLocationCoordinate2D(latitude: 10, longitude: 20),
course: 0,
floor: nil,
horizontalAccuracy: 0,
speed: 0,
timestamp: Date(timeIntervalSince1970: 1_234_567_890),
verticalAccuracy: 0
)
store.assert(
.send(.onAppear),
// Tap on the button to request current location
.send(.currentLocationButtonTapped) {
$0.isRequestingCurrentLocation = true
},
.do {
XCTAssertTrue(didRequestInUseAuthorization)
},
// Simulate being given authorized to access location
.do {
locationManagerSubject.send(.didChangeAuthorization(.authorizedAlways))
},
.receive(.locationManager(.didChangeAuthorization(.authorizedAlways))),
.do {
XCTAssertTrue(didRequestLocation)
},
// Simulate finding the user's current location
.do {
locationManagerSubject.send(.didUpdateLocations([currentLocation]))
},
.receive(.locationManager(.didUpdateLocations([currentLocation]))) {
$0.isRequestingCurrentLocation = false
$0.region = CoordinateRegion(
center: CLLocationCoordinate2D(latitude: 10, longitude: 20),
span: MKCoordinateSpan.init(latitudeDelta: 0.05, longitudeDelta: 0.05)
)
},
.do {
locationManagerSubject.send(completion: .finished)
}
)
}
func testRequestLocation_Deny() {
var didRequestInUseAuthorization = false
let locationManagerSubject = PassthroughSubject<LocationManager.Action, Never>()
#if os(iOS)
let store = TestStore(
initialState: AppState(),
reducer: appReducer,
environment: AppEnvironment(
localSearch: .mock(),
locationManager: .mock(
authorizationStatus: { .notDetermined },
create: { _ in locationManagerSubject.eraseToEffect() },
locationServicesEnabled: { true },
requestWhenInUseAuthorization: { _ in
.fireAndForget { didRequestInUseAuthorization = true }
}
)
)
)
#elseif os(macOS)
let store = TestStore(
initialState: AppState(),
reducer: appReducer,
environment: AppEnvironment(
localSearch: .mock(),
locationManager: .mock(
authorizationStatus: { .notDetermined },
create: { _ in locationManagerSubject.eraseToEffect() },
locationServicesEnabled: { true },
requestAlwaysAuthorization: { _ in
.fireAndForget { didRequestInUseAuthorization = true }
}
)
)
)
#endif
store.assert(
.send(.onAppear),
.send(.currentLocationButtonTapped) {
$0.isRequestingCurrentLocation = true
},
.do {
XCTAssertTrue(didRequestInUseAuthorization)
},
// Simulate the user denying location access
.do {
locationManagerSubject.send(.didChangeAuthorization(.denied))
},
.receive(.locationManager(.didChangeAuthorization(.denied))) {
$0.alert = "Location makes this app better. Please consider giving us access."
$0.isRequestingCurrentLocation = false
},
.do {
locationManagerSubject.send(completion: .finished)
}
)
}
func testSearchPointsOfInterest_TapCategory() {
let mapItem = MapItem(
isCurrentLocation: false,
name: "Blob's Cafe",
phoneNumber: nil,
placemark: Placemark(),
pointOfInterestCategory: .cafe,
timeZone: nil,
url: nil
)
let localSearchResponse = LocalSearchResponse(
boundingRegion: MKCoordinateRegion(),
mapItems: [mapItem]
)
let store = TestStore(
initialState: AppState(),
reducer: appReducer,
environment: AppEnvironment(
localSearch: .mock(
search: { _ in .result { .success(localSearchResponse) } }
),
locationManager: .mock()
)
)
store.assert(
.send(.categoryButtonTapped(.cafe)) {
$0.pointOfInterestCategory = .cafe
},
.receive(.localSearchResponse(.success(localSearchResponse))) {
$0.pointsOfInterest = [
PointOfInterest(
coordinate: CLLocationCoordinate2D(),
subtitle: nil,
title: "Blob's Cafe"
)
]
}
)
}
func testSearchPointsOfInterest_PanMap() {
let mapItem = MapItem(
isCurrentLocation: false,
name: "Blob's Cafe",
phoneNumber: nil,
placemark: Placemark(),
pointOfInterestCategory: .cafe,
timeZone: nil,
url: nil
)
let localSearchResponse = LocalSearchResponse(
boundingRegion: MKCoordinateRegion(),
mapItems: [mapItem]
)
let store = TestStore(
initialState: AppState(
pointOfInterestCategory: .cafe
),
reducer: appReducer,
environment: AppEnvironment(
localSearch: .mock(
search: { request in
return .result { .success(localSearchResponse) }
}),
locationManager: .mock()
)
)
let coordinateRegion = CoordinateRegion(
center: CLLocationCoordinate2D(latitude: 10, longitude: 20),
span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 2)
)
store.assert(
.send(.updateRegion(coordinateRegion)) {
$0.region = coordinateRegion
},
.receive(.localSearchResponse(.success(localSearchResponse))) {
$0.pointsOfInterest = [
PointOfInterest(
coordinate: CLLocationCoordinate2D(),
subtitle: nil,
title: "Blob's Cafe"
)
]
}
)
}
}