I am working into a difficulty with snapshot testing a view that listens for updates from a view mannequin utilizing a Mix writer. The difficulty appears to be with the sink that’s acquired on the primary queue – the closure is what updates the view state. After I connect the view mannequin to the view, the closure contained in the sink is just not executed till after the snapshot take a look at runs, and I am left with an empty button! Is there a method to drive the sink’s closure to execute earlier than working the take a look at?
import Mix
import SnapshotTesting
import UIKit
import XCTest
struct ButtonState {
let textual content: String
let colour: UIColor
}
protocol ButtonViewModel {
var state: AnyPublisher<ButtonState, By no means> { get }
}
ultimate class MyButton: UIButton {
non-public var cancellable: Cancellable?
func connect(viewModel: some ButtonViewModel) {
cancellable = viewModel.state
.obtain(on: DispatchQueue.most important)
.sink { [weak self] in
self?.convertState($0)
}
}
non-public func convertState(_ state: ButtonState) {
setTitle(state.textual content, for: .regular)
setTitleColor(state.colour, for: .regular)
}
}
struct MockViewModel: ButtonViewModel {
var state: AnyPublisher<ButtonState, By no means> {
currentState.eraseToAnyPublisher()
}
non-public let currentState: CurrentValueSubject<ButtonState, By no means>
init(initialState: ButtonState) {
currentState = CurrentValueSubject(initialState)
}
}
ultimate class ButtonSnapshotTest: XCTestCase {
func testMyButton() {
let myButton = MyButton()
myButton.connect(viewModel: MockViewModel(initialState: .init(textual content: "Hi", colour: .blue)))
assertSnapshot(matching: myButton, as: .picture)
}
}