Files
GradientLoadingBar/Example/Tests/ViewModel/GradientLoadingBarViewModelTestCase.swift
T
2018-09-19 21:43:17 +02:00

194 lines
6.4 KiB
Swift

//
// GradientLoadingBarViewModelTestCase.swift
// GradientLoadingBar_Tests
//
// Created by Felix Mau on 26.12.17.
// Copyright © 2017 CocoaPods. All rights reserved.
//
import Observable
import XCTest
@testable import GradientLoadingBar
// MARK: - Test case
class GradientLoadingBarViewModelTestCase: XCTestCase {
private var superview: UIView!
private var durations: Durations!
private var sharedApplicationMock: SharedApplicationMock!
private var notificationCenter: NotificationCenter!
var viewModel: GradientLoadingBarViewModel!
override func setUp() {
super.setUp()
superview = UIView()
durations = Durations(fadeIn: 1.2,
fadeOut: 3.4,
progress: 5.6)
sharedApplicationMock = SharedApplicationMock()
notificationCenter = NotificationCenter()
viewModel = GradientLoadingBarViewModel(superview: superview,
durations: durations,
sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
}
override func tearDown() {
viewModel = nil
superview = nil
durations = nil
notificationCenter = nil
sharedApplicationMock = nil
super.tearDown()
}
// MARK: - Test `superview`
func testListenerForSuperviewShouldBeInformedImmediately() {
// When
var disposal = Disposal()
viewModel.superview.observe { [weak self] nextValue, _ in
// Then
XCTAssertNotNil(nextValue)
XCTAssertEqual(nextValue, self?.superview)
}.add(to: &disposal)
}
func testListenerForSuperviewShouldBeInformedAfterUIWindowDidBecomeKeyNotification() {
// Given
let viewModel = GradientLoadingBarViewModel(superview: nil,
durations: durations,
sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
let keyWindow = UIWindow()
sharedApplicationMock.keyWindow = keyWindow
var disposal = Disposal()
viewModel.superview.observe { nextValue, _ in
guard let nextValue = nextValue else {
// Skip initial call to observer.
return
}
// Then
XCTAssertEqual(nextValue, keyWindow)
}.add(to: &disposal)
// When
notificationCenter.post(name: .UIWindowDidBecomeKey,
object: nil)
}
func testListenerForSuperviewShouldBeInformedAfterUIWindowDidBecomeKeyNotificationJustOnce() {
// Given
let viewModel = GradientLoadingBarViewModel(superview: nil,
durations: durations,
sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
let keyWindow = UIWindow()
sharedApplicationMock.keyWindow = keyWindow
var observerCounter = 0
var disposal = Disposal()
viewModel.superview.observe { nextValue, _ in
guard nextValue != nil else {
// Skip initial call to observer.
return
}
observerCounter += 1
}.add(to: &disposal)
// When
for _ in 1 ... 3 {
notificationCenter.post(name: .UIWindowDidBecomeKey,
object: nil)
}
XCTAssertEqual(observerCounter, 1)
}
// MARK: - Test visibility
func testShowShouldUpdateVisibility() {
// When
viewModel.show()
// Then
let receivedAnimatedVisibilityUpdate = viewModel.isVisible.value
let expectedAnimatedVisibilityUpdate = makeAnimatedVisibilityUpdateForStateIsVisible
XCTAssertEqual(receivedAnimatedVisibilityUpdate, expectedAnimatedVisibilityUpdate)
}
func testHideShouldUpdateVisibility() {
// Given
// Start by showing the gradient loading bar, so we'll notice the change.
viewModel.show()
// When
viewModel.hide()
// Then
let receivedAnimatedVisibilityUpdate = viewModel.isVisible.value
let expectedAnimatedVisibilityUpdate = makeAnimatedVisibilityUpdateForStateIsHidden
XCTAssertEqual(receivedAnimatedVisibilityUpdate, expectedAnimatedVisibilityUpdate)
}
func testToggleShouldUpdateVisibility() {
// Given
for idx in 1 ... 5 {
// When
viewModel.toggle()
// Then
let receivedAnimatedVisibilityUpdate = viewModel.isVisible.value
let expectedAnimatedVisibilityUpdate: GradientLoadingBarViewModel.AnimatedVisibilityUpdate
let viewShouldBeHidden = idx % 2 == 0
if viewShouldBeHidden {
expectedAnimatedVisibilityUpdate = makeAnimatedVisibilityUpdateForStateIsHidden
} else {
expectedAnimatedVisibilityUpdate = makeAnimatedVisibilityUpdateForStateIsVisible
}
XCTAssertEqual(receivedAnimatedVisibilityUpdate, expectedAnimatedVisibilityUpdate)
}
}
}
// MARK: - Helpers
extension GradientLoadingBarViewModelTestCase {
/// Returns an object for animated visibility updates from state visible to hidden.
var makeAnimatedVisibilityUpdateForStateIsHidden: GradientLoadingBarViewModel.AnimatedVisibilityUpdate {
// swiftlint:disable:previous identifier_name
return GradientLoadingBarViewModel.AnimatedVisibilityUpdate(duration: durations.fadeOut,
isHidden: true)
}
/// Returns an object for animated visibility updates from state hidden to visible.
var makeAnimatedVisibilityUpdateForStateIsVisible: GradientLoadingBarViewModel.AnimatedVisibilityUpdate {
// swiftlint:disable:previous identifier_name
return GradientLoadingBarViewModel.AnimatedVisibilityUpdate(duration: durations.fadeIn,
isHidden: false)
}
}
// MARK: - Mocks
class SharedApplicationMock: UIApplicationProtocol {
var keyWindow: UIWindow?
}