mirror of
https://github.com/pointfreeco/swift-composable-architecture.git
synced 2025-12-24 12:14:25 +01:00
* Merge Test Support Module An attempt to fix #70. * Remove import * Update README * Assertion failure * Cleanup * Add NB * Revert format change * Update Sources/ComposableArchitecture/TestSupport/TestStore.swift * TicTacToe fixes * Hide test store in debug flag Co-authored-by: Brandon Williams <mbw234@gmail.com>
190 lines
5.0 KiB
Swift
190 lines
5.0 KiB
Swift
import Combine
|
|
import ComposableArchitecture
|
|
import XCTest
|
|
|
|
@testable import Search
|
|
|
|
class SearchTests: XCTestCase {
|
|
let scheduler = DispatchQueue.testScheduler
|
|
lazy var environment = SearchEnvironment(
|
|
weatherClient: .unimplemented,
|
|
mainQueue: AnyScheduler(self.scheduler)
|
|
)
|
|
|
|
func testSearchAndClearQuery() {
|
|
let store = TestStore(
|
|
initialState: .init(),
|
|
reducer: searchReducer,
|
|
environment: self.environment
|
|
)
|
|
|
|
store.assert(
|
|
.environment {
|
|
$0.weatherClient.searchLocation = { _ in Effect(value: mockLocations) }
|
|
},
|
|
.send(.searchQueryChanged("S")) {
|
|
$0.searchQuery = "S"
|
|
},
|
|
.do { self.scheduler.advance(by: 0.3) },
|
|
.receive(.locationsResponse(.success(mockLocations))) {
|
|
$0.locations = mockLocations
|
|
},
|
|
.send(.searchQueryChanged("")) {
|
|
$0.locations = []
|
|
$0.searchQuery = ""
|
|
}
|
|
)
|
|
}
|
|
|
|
func testSearchFailure() {
|
|
let store = TestStore(
|
|
initialState: .init(),
|
|
reducer: searchReducer,
|
|
environment: self.environment
|
|
)
|
|
|
|
store.assert(
|
|
.environment {
|
|
$0.weatherClient.searchLocation = { _ in Effect(error: .init()) }
|
|
},
|
|
.send(.searchQueryChanged("S")) {
|
|
$0.searchQuery = "S"
|
|
},
|
|
.do { self.scheduler.advance(by: 0.3) },
|
|
.receive(.locationsResponse(.failure(.init())))
|
|
)
|
|
}
|
|
|
|
func testClearQueryCancelsInFlightSearchRequest() {
|
|
let store = TestStore(
|
|
initialState: .init(),
|
|
reducer: searchReducer,
|
|
environment: self.environment
|
|
)
|
|
|
|
store.assert(
|
|
.environment {
|
|
$0.weatherClient.searchLocation = { _ in Effect(value: mockLocations) }
|
|
},
|
|
.send(.searchQueryChanged("S")) {
|
|
$0.searchQuery = "S"
|
|
},
|
|
.do { self.scheduler.advance(by: 0.2) },
|
|
.send(.searchQueryChanged("")) {
|
|
$0.searchQuery = ""
|
|
},
|
|
.do { self.scheduler.run() }
|
|
)
|
|
}
|
|
|
|
func testTapOnLocation() {
|
|
let specialLocation = Location(id: 42, title: "Special Place")
|
|
let specialLocationWeather = LocationWeather(
|
|
consolidatedWeather: mockWeather,
|
|
id: 42
|
|
)
|
|
|
|
let store = TestStore(
|
|
initialState: .init(locations: mockLocations + [specialLocation]),
|
|
reducer: searchReducer,
|
|
environment: self.environment
|
|
)
|
|
|
|
store.assert(
|
|
.environment {
|
|
$0.weatherClient.weather = { _ in Effect(value: specialLocationWeather) }
|
|
},
|
|
.send(.locationTapped(specialLocation)) {
|
|
$0.locationWeatherRequestInFlight = specialLocation
|
|
},
|
|
.do { self.scheduler.advance() },
|
|
.receive(.locationWeatherResponse(.success(specialLocationWeather))) {
|
|
$0.locationWeatherRequestInFlight = nil
|
|
$0.locationWeather = specialLocationWeather
|
|
}
|
|
)
|
|
}
|
|
|
|
func testTapOnLocationCancelsInFlightRequest() {
|
|
let specialLocation = Location(id: 42, title: "Special Place")
|
|
let specialLocationWeather = LocationWeather(
|
|
consolidatedWeather: mockWeather,
|
|
id: 42
|
|
)
|
|
|
|
let store = TestStore(
|
|
initialState: .init(locations: mockLocations + [specialLocation]),
|
|
reducer: searchReducer,
|
|
environment: self.environment
|
|
)
|
|
|
|
store.assert(
|
|
.environment {
|
|
$0.weatherClient.weather = { _ in Effect(value: specialLocationWeather) }
|
|
},
|
|
.send(.locationTapped(mockLocations.first!)) {
|
|
$0.locationWeatherRequestInFlight = mockLocations.first!
|
|
},
|
|
.send(.locationTapped(specialLocation)) {
|
|
$0.locationWeatherRequestInFlight = specialLocation
|
|
},
|
|
.do { self.scheduler.advance() },
|
|
.receive(.locationWeatherResponse(.success(specialLocationWeather))) {
|
|
$0.locationWeatherRequestInFlight = nil
|
|
$0.locationWeather = specialLocationWeather
|
|
}
|
|
)
|
|
}
|
|
|
|
func testTapOnLocationFailure() {
|
|
let store = TestStore(
|
|
initialState: .init(locations: mockLocations),
|
|
reducer: searchReducer,
|
|
environment: self.environment
|
|
)
|
|
|
|
store.assert(
|
|
.environment {
|
|
$0.weatherClient.weather = { _ in Fail(error: .init()).eraseToEffect() }
|
|
},
|
|
.send(.locationTapped(mockLocations.first!)) {
|
|
$0.locationWeatherRequestInFlight = mockLocations.first!
|
|
},
|
|
.do { self.scheduler.advance() },
|
|
.receive(.locationWeatherResponse(.failure(.init()))) {
|
|
$0.locationWeatherRequestInFlight = nil
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
private let mockWeather: [LocationWeather.ConsolidatedWeather] = [
|
|
.init(
|
|
applicableDate: Date(timeIntervalSince1970: 0),
|
|
maxTemp: 90,
|
|
minTemp: 70,
|
|
theTemp: 80,
|
|
weatherStateName: "Clear"
|
|
),
|
|
.init(
|
|
applicableDate: Date(timeIntervalSince1970: 86_400),
|
|
maxTemp: 70,
|
|
minTemp: 50,
|
|
theTemp: 60,
|
|
weatherStateName: "Rain"
|
|
),
|
|
.init(
|
|
applicableDate: Date(timeIntervalSince1970: 172_800),
|
|
maxTemp: 100,
|
|
minTemp: 80,
|
|
theTemp: 90,
|
|
weatherStateName: "Cloudy"
|
|
),
|
|
]
|
|
|
|
private let mockLocations = [
|
|
Location(id: 1, title: "Brooklyn"),
|
|
Location(id: 2, title: "Los Angeles"),
|
|
Location(id: 3, title: "San Francisco"),
|
|
]
|