Description
There seems to be an issue with the Store when using a TestClock, the view doesn't react to timer ticks unless we assert for state mutation and recreate the view and the store.
Current versions:
swift-clocks 1.0.2
swift-composable-architecture 1.10.4
swift-snapshot-testing 1.16.0
Checklist
Expected behavior
These tests should pass
@MainActor // ❌
func testExampleFailing() async {
let clock = TestClock()
let store = Store(initialState: .init(), reducer: { ContentViewFeature()}, withDependencies: { $0.continuousClock = clock })
let sut = ContentView(store: store)
await store.send(.startTimer).finish()
await clock.advance(by: .seconds(1))
// Test ends with unexpected result, timer doesn't advance
assertSnapshot(matching: UIHostingController(rootView: sut), as: .image)
// Same here
await clock.advance(by: .seconds(4))
assertSnapshot(matching: UIHostingController(rootView: sut), as: .image)
}
@MainActor // ❌
func testExampleFailing2() async {
let clock = TestClock()
let store = TestStore(initialState: .init(), reducer: { ContentViewFeature()}, withDependencies: { $0.continuousClock = clock })
store.exhaustivity = .off
let sut = ContentView(store: store.snapshotStore)
let task = await store.send(.startTimer)
// Test ends with unexpected result, timer doesn't advance
await clock.advance(by: .seconds(1))
assertSnapshot(matching: UIHostingController(rootView: sut), as: .image)
// Test ends with unexpected result, timer doesn't advance
await clock.advance(by: .seconds(4))
assertSnapshot(matching: UIHostingController(rootView: sut), as: .image)
await task.cancel()
}
Actual behavior
These tests are the only ones that I'm able to make work
@MainActor // ✅
func testExampleMutatingState() async {
let clock = TestClock()
let store = Store(initialState: .init(), reducer: { ContentViewFeature()}, withDependencies: { $0.continuousClock = clock })
await store.send(.startTimer).finish()
// State does get mutated
await clock.advance(by: .seconds(1))
XCTAssertEqual(store.secondsElapsed, 1)
await clock.advance(by: .seconds(4))
XCTAssertEqual(store.secondsElapsed, 5)
}
@MainActor // ✅
func testExampleWithUISnapshot() async {
let clock = TestClock()
let store = TestStore(
initialState: ContentViewFeature.State(),
reducer: { ContentViewFeature() },
withDependencies: { $0.continuousClock = clock }
)
let task = await store.send(.startTimer)
let sut1 = ContentView(store: store.snapshotStore)
assertSnapshot(matching: UIHostingController(rootView: sut1), as: .image)
await clock.advance(by: .seconds(1))
// By asserting the state mutation we mamage to await
await store.receive(\.timerTicked) { $0.secondsElapsed = 1 }
// If we recreate the view and the store with the current state then we get the desired result
let sut2 = ContentView(store: store.snapshotStore)
assertSnapshot(matching: UIHostingController(rootView: sut2), as: .image)
// Same concept here
await clock.advance(by: .seconds(4))
for second in 2...5 {
await store.receive(\.timerTicked) { $0.secondsElapsed = Double(second) }
}
let sut3 = ContentView(store: store.snapshotStore)
assertSnapshot(matching: UIHostingController(rootView: sut3), as: .image)
await task.cancel()
}
Steps to reproduce
- Create a view with a timer
- A store that uses a ContinuousClock
- Create a test for a view that injects a TestClock
- Use assertSnapshot to assert changes in the view
Find here the project:
clockTests.zip
Thanks in advance
swift-clocks version information
1.0.2
Destination operating system
iOS 17.4
Xcode version information
15.3
Swift Compiler version information
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
Description
There seems to be an issue with the Store when using a TestClock, the view doesn't react to timer ticks unless we assert for state mutation and recreate the view and the store.
Current versions:
swift-clocks 1.0.2
swift-composable-architecture 1.10.4
swift-snapshot-testing 1.16.0
Checklist
mainbranch of this package.Expected behavior
These tests should pass
Actual behavior
These tests are the only ones that I'm able to make work
Steps to reproduce
Find here the project:
clockTests.zip
Thanks in advance
swift-clocks version information
1.0.2
Destination operating system
iOS 17.4
Xcode version information
15.3
Swift Compiler version information