✅ :: Adapt test cases

This commit is contained in:
Felix Mau
2019-08-25 22:34:48 +02:00
parent 88cfdeb994
commit 28a82bdaf7
4 changed files with 186 additions and 241 deletions
@@ -13,7 +13,7 @@
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
64E0F5BF2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */; };
64E7F4252293E16B00BE5095 /* UIView+AnimateIsHiddenTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E7F4242293E16B00BE5095 /* UIView+AnimateIsHiddenTestCase.swift */; };
64E7F4252293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E7F4242293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift */; };
77357BD34CFF2778341F80E8 /* Pods_GradientLoadingBar_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03CD5D69D7C3FBBDBF5FABBB /* Pods_GradientLoadingBar_Example.framework */; };
8020C040972E902A8CCAA9E7 /* Pods_GradientLoadingBar_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 434E3C8A6E245A38C2831E73 /* Pods_GradientLoadingBar_Tests.framework */; };
972CFBCC2138849A006F14C9 /* SafeAreaExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972CFBCB2138849A006F14C9 /* SafeAreaExampleViewController.swift */; };
@@ -51,7 +51,7 @@
607FACE51AFB9204008FA782 /* GradientLoadingBar_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GradientLoadingBar_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModelTestCase.swift; sourceTree = "<group>"; };
64E7F4242293E16B00BE5095 /* UIView+AnimateIsHiddenTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+AnimateIsHiddenTestCase.swift"; sourceTree = "<group>"; };
64E7F4242293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift"; sourceTree = "<group>"; };
972CFBCB2138849A006F14C9 /* SafeAreaExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeAreaExampleViewController.swift; sourceTree = "<group>"; };
97464E6621372BCD0097183A /* AdvancedExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedExampleViewController.swift; sourceTree = "<group>"; };
97464E6821372C010097183A /* NavigationBarExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarExampleViewController.swift; sourceTree = "<group>"; };
@@ -134,8 +134,8 @@
607FACE81AFB9204008FA782 /* Tests */ = {
isa = PBXGroup;
children = (
64E7F4222293E16B00BE5095 /* Extensions */,
64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */,
64C6B3E72313259500076A69 /* ViewModel */,
64E7F4222293E16B00BE5095 /* View */,
607FACE91AFB9204008FA782 /* Supporting Files */,
);
path = Tests;
@@ -159,20 +159,20 @@
name = "Podspec Metadata";
sourceTree = "<group>";
};
64E7F4222293E16B00BE5095 /* Extensions */ = {
64C6B3E72313259500076A69 /* ViewModel */ = {
isa = PBXGroup;
children = (
64E7F4232293E16B00BE5095 /* UIView */,
64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */,
);
path = Extensions;
path = ViewModel;
sourceTree = "<group>";
};
64E7F4232293E16B00BE5095 /* UIView */ = {
64E7F4222293E16B00BE5095 /* View */ = {
isa = PBXGroup;
children = (
64E7F4242293E16B00BE5095 /* UIView+AnimateIsHiddenTestCase.swift */,
64E7F4242293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift */,
);
path = UIView;
path = View;
sourceTree = "<group>";
};
97B6F5F92143F31F008CFEA5 /* Extensions */ = {
@@ -453,7 +453,7 @@
buildActionMask = 2147483647;
files = (
64E0F5BF2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift in Sources */,
64E7F4252293E16B00BE5095 /* UIView+AnimateIsHiddenTestCase.swift in Sources */,
64E7F4252293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1,202 +0,0 @@
//
// GradientLoadingBarViewModelTestCase.swift
// GradientLoadingBar_Tests
//
// Created by Felix Mau on 12/26/17.
// Copyright © 2017 Felix Mau. All rights reserved.
//
import XCTest
@testable import LightweightObservable
@testable import GradientLoadingBar
class GradientLoadingBarViewModelTestCase: XCTestCase {
// MARK: - Private properties
private var superview: UIView!
private var durations: Durations!
private var sharedApplicationMock: SharedApplicationMock!
private var notificationCenter: NotificationCenter!
private var viewModel: GradientLoadingBarViewModel!
// MARK: - Public methods
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 observable `superview`
func testInitializerShouldSetupSuperviewObservableWithCustomSuperview() {
// Then
XCTAssertEqual(viewModel.superview.value,
superview,
"We passed a custom superview to the view-model in `setUp()`, and therfore expect this view to be the superview.")
}
func testInitializerShouldSetupSuperviewObservableWithKeyWindow() {
// Given
let keyWindow = UIWindow()
sharedApplicationMock.keyWindow = keyWindow
// When
let viewModel = GradientLoadingBarViewModel(superview: nil,
durations: durations,
sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
// Then
XCTAssertEqual(viewModel.superview.value,
keyWindow)
}
func testInitializerShouldSetupSuperviewObservableAfterUIWindowDidBecomeKeyNotification() {
// Given
let viewModel = GradientLoadingBarViewModel(superview: nil,
durations: durations,
sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
let keyWindow = UIWindow()
// When
sharedApplicationMock.keyWindow = keyWindow
notificationCenter.post(name: UIWindow.didBecomeKeyNotification,
object: nil)
// Then
XCTAssertEqual(viewModel.superview.value,
keyWindow)
}
func testInitializerShouldSetupSuperviewObservableAfterUIWindowDidBecomeKeyNotificationJustOnce() {
// Given
let viewModel = GradientLoadingBarViewModel(superview: nil,
durations: durations,
sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
let expectation = self.expectation(description: "Expected observer for superview to be informed just once.")
var disposeBag = DisposeBag()
viewModel.superview.subscribe { newSuperview, _ in
guard newSuperview != nil else {
// Skip initial call to observer.
return
}
expectation.fulfill()
}.disposed(by: &disposeBag)
// When
for _ in 1 ... 3 {
sharedApplicationMock.keyWindow = UIWindow()
notificationCenter.post(name: UIWindow.didBecomeKeyNotification,
object: nil)
}
// Then
wait(for: [expectation], timeout: 0.1)
}
// MARK: - Test observable `animatedVisibilityUpdate`
func testInitializerShouldSetupAnimatedVisibilityUpdateObservableWithImmediatelyHidden() {
// Then
let receivedAnimatedVisibilityUpdate = viewModel.animatedVisibilityUpdate.value
let expectedAnimatedVisibilityUpdate = GradientLoadingBarViewModel.AnimatedVisibilityUpdate.immediatelyHidden
XCTAssertEqual(receivedAnimatedVisibilityUpdate, expectedAnimatedVisibilityUpdate)
}
func testShowShouldUpdateAnimatedVisibilityUpdateObservable() {
// When
viewModel.show()
// Then
let receivedAnimatedVisibilityUpdate = viewModel.animatedVisibilityUpdate.value
let expectedAnimatedVisibilityUpdate = makeAnimatedVisibilityUpdateForStateIsVisible()
XCTAssertEqual(receivedAnimatedVisibilityUpdate, expectedAnimatedVisibilityUpdate)
}
func testHideShouldUpdateAnimatedVisibilityUpdateObservable() {
// When
viewModel.hide()
// Then
let receivedAnimatedVisibilityUpdate = viewModel.animatedVisibilityUpdate.value
let expectedAnimatedVisibilityUpdate = makeAnimatedVisibilityUpdateForStateIsHidden()
XCTAssertEqual(receivedAnimatedVisibilityUpdate, expectedAnimatedVisibilityUpdate)
}
func testToggleShouldUpdateAnimatedVisibilityUpdateObservable() {
// Given
for idx in 1 ... 5 {
// When
viewModel.toggle()
// Then
let receivedAnimatedVisibilityUpdate = viewModel.animatedVisibilityUpdate.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.
func makeAnimatedVisibilityUpdateForStateIsHidden() -> GradientLoadingBarViewModel.AnimatedVisibilityUpdate {
return GradientLoadingBarViewModel.AnimatedVisibilityUpdate(duration: durations.fadeOut,
isHidden: true)
}
/// Returns an object for animated visibility updates from state hidden to visible.
func makeAnimatedVisibilityUpdateForStateIsVisible() -> GradientLoadingBarViewModel.AnimatedVisibilityUpdate {
return GradientLoadingBarViewModel.AnimatedVisibilityUpdate(duration: durations.fadeIn,
isHidden: false)
}
}
// MARK: - Mocks
class SharedApplicationMock: UIApplicationProtocol {
var keyWindow: UIWindow?
}
@@ -1,5 +1,5 @@
//
// UIView+AnimateIsHiddenTestCase.swift
// GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift
// GradientLoadingBar_Tests
//
// Created by Felix Mau on 19/05/19.
@@ -14,7 +14,7 @@ class UIViewAnimateIsHiddenTestCase: XCTestCase {
// MARK: - Private properties
private var window: UIWindow!
private var view: UIView!
private var gradientActivityIndicatorView: GradientActivityIndicatorView!
// MARK: - Public methods
@@ -25,13 +25,13 @@ class UIViewAnimateIsHiddenTestCase: XCTestCase {
// Therefore we're gonna use the current key-window, add our testing view here in `setUp()` and remove it later in `tearDown()`.
window = UIApplication.shared.keyWindow
view = UIView()
window.addSubview(view)
gradientActivityIndicatorView = GradientActivityIndicatorView()
window.addSubview(gradientActivityIndicatorView)
}
override func tearDown() {
view.removeFromSuperview()
view = nil
gradientActivityIndicatorView.removeFromSuperview()
gradientActivityIndicatorView = nil
window = nil
@@ -45,19 +45,19 @@ class UIViewAnimateIsHiddenTestCase: XCTestCase {
let expectation = self.expectation(description: "Expect completion handler to be called.")
// Hide view to validate fade-in.
view.alpha = 0.0
view.isHidden = true
gradientActivityIndicatorView.alpha = 0.0
gradientActivityIndicatorView.isHidden = true
// When
view.animate(isHidden: false, duration: 0.1) { _ in
gradientActivityIndicatorView.animate(isHidden: false, duration: 0.1) { _ in
expectation.fulfill()
}
// Then
wait(for: [expectation], timeout: 0.2)
XCTAssertFalse(view.isHidden)
XCTAssertEqual(view.alpha, 1.0, accuracy: CGFloat.ulpOfOne)
XCTAssertFalse(gradientActivityIndicatorView.isHidden)
XCTAssertEqual(gradientActivityIndicatorView.alpha, 1.0, accuracy: CGFloat.ulpOfOne)
}
func testAnimateIsHiddenShouldHideViewAndCallCompletionHandler() {
@@ -65,15 +65,15 @@ class UIViewAnimateIsHiddenTestCase: XCTestCase {
let expectation = self.expectation(description: "Expect completion handler to be called.")
// When
view.animate(isHidden: true, duration: 0.1) { _ in
gradientActivityIndicatorView.animate(isHidden: true, duration: 0.1) { _ in
expectation.fulfill()
}
// Then
wait(for: [expectation], timeout: 0.2)
XCTAssertTrue(view.isHidden)
XCTAssertEqual(view.alpha, 0.0, accuracy: CGFloat.ulpOfOne)
XCTAssertTrue(gradientActivityIndicatorView.isHidden)
XCTAssertEqual(gradientActivityIndicatorView.alpha, 0.0, accuracy: CGFloat.ulpOfOne)
}
func testAnimateIsHiddenWithCancelationShouldResetIsHiddenFlagAndCallCompletionHandler() {
@@ -81,17 +81,17 @@ class UIViewAnimateIsHiddenTestCase: XCTestCase {
let expectation = self.expectation(description: "Expect completion handler to be called.")
// When
view.animate(isHidden: true, duration: 0.1) { _ in
gradientActivityIndicatorView.animate(isHidden: true, duration: 0.1) { _ in
expectation.fulfill()
}
// Cancel animation.
view.layer.removeAllAnimations()
gradientActivityIndicatorView.layer.removeAllAnimations()
// Then
wait(for: [expectation], timeout: 0.2)
XCTAssertFalse(view.isHidden, "As we've interrupted the animation, we expect the `isHidden` flag to still be `false`.")
XCTAssertFalse(gradientActivityIndicatorView.isHidden, "As we've interrupted the animation, we expect the `isHidden` flag to still be `false`.")
}
// MARK: - Test method `fadeIn()`
@@ -101,19 +101,19 @@ class UIViewAnimateIsHiddenTestCase: XCTestCase {
let expectation = self.expectation(description: "Expect completion handler to be called.")
// Hide view to validate fade-in.
view.alpha = 0.0
view.isHidden = true
gradientActivityIndicatorView.alpha = 0.0
gradientActivityIndicatorView.isHidden = true
// When
view.fadeIn(duration: 0.1) { _ in
gradientActivityIndicatorView.fadeIn(duration: 0.1) { _ in
expectation.fulfill()
}
// Then
wait(for: [expectation], timeout: 0.2)
XCTAssertFalse(view.isHidden)
XCTAssertEqual(view.alpha, 1.0, accuracy: CGFloat.ulpOfOne)
XCTAssertFalse(gradientActivityIndicatorView.isHidden)
XCTAssertEqual(gradientActivityIndicatorView.alpha, 1.0, accuracy: CGFloat.ulpOfOne)
}
// MARK: - Test method `fadeOut()`
@@ -123,15 +123,15 @@ class UIViewAnimateIsHiddenTestCase: XCTestCase {
let expectation = self.expectation(description: "Expect completion handler to be called.")
// When
view.fadeOut(duration: 0.1) { _ in
gradientActivityIndicatorView.fadeOut(duration: 0.1) { _ in
expectation.fulfill()
}
// Then
wait(for: [expectation], timeout: 0.2)
XCTAssertTrue(view.isHidden)
XCTAssertEqual(view.alpha, 0.0, accuracy: CGFloat.ulpOfOne)
XCTAssertTrue(gradientActivityIndicatorView.isHidden)
XCTAssertEqual(gradientActivityIndicatorView.alpha, 0.0, accuracy: CGFloat.ulpOfOne)
}
func testFadeOutWithCancelationShouldResetIsHiddenFlagAndCallCompletionHandler() {
@@ -139,16 +139,16 @@ class UIViewAnimateIsHiddenTestCase: XCTestCase {
let expectation = self.expectation(description: "Expect completion handler to be called.")
// When
view.fadeOut(duration: 0.1) { _ in
gradientActivityIndicatorView.fadeOut(duration: 0.1) { _ in
expectation.fulfill()
}
// Cancel animation.
view.layer.removeAllAnimations()
gradientActivityIndicatorView.layer.removeAllAnimations()
// Then
wait(for: [expectation], timeout: 0.2)
XCTAssertFalse(view.isHidden, "As we've interrupted the animation, we expect the `isHidden` flag to still be `false`.")
XCTAssertFalse(gradientActivityIndicatorView.isHidden, "As we've interrupted the animation, we expect the `isHidden` flag to still be `false`.")
}
}
@@ -0,0 +1,147 @@
//
// GradientLoadingBarViewModelTestCase.swift
// GradientLoadingBar_Tests
//
// Created by Felix Mau on 12/26/17.
// Copyright © 2017 Felix Mau. All rights reserved.
//
import XCTest
@testable import LightweightObservable
@testable import GradientLoadingBar
class GradientLoadingBarViewModelTestCase: XCTestCase {
// MARK: - Types
typealias VisibilityAnimation = GradientLoadingBarViewModel.VisibilityAnimation
// MARK: - Private properties
private var sharedApplicationMock: SharedApplicationMock!
private var notificationCenter: NotificationCenter!
private var viewModel: GradientLoadingBarViewModel!
// MARK: - Public methods
override func setUp() {
super.setUp()
sharedApplicationMock = SharedApplicationMock()
notificationCenter = NotificationCenter()
viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
}
override func tearDown() {
viewModel = nil
notificationCenter = nil
sharedApplicationMock = nil
super.tearDown()
}
// MARK: - Test observable `superview`
func testInitializerShouldSetupSuperviewObservableWithKeyWindow() {
// Given
let keyWindow = UIWindow()
sharedApplicationMock.keyWindow = keyWindow
// When
let viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
// Then
XCTAssertEqual(viewModel.superview.value,
keyWindow)
}
func testInitializerShouldSetupSuperviewObservableAfterUIWindowDidBecomeKeyNotification() {
// Given
let viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
let keyWindow = UIWindow()
// When
sharedApplicationMock.keyWindow = keyWindow
notificationCenter.post(name: UIWindow.didBecomeKeyNotification,
object: nil)
// Then
XCTAssertEqual(viewModel.superview.value,
keyWindow)
}
func testInitializerShouldSetupSuperviewObservableAfterUIWindowDidBecomeKeyNotificationJustOnce() {
// Given
let viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
let expectation = self.expectation(description: "Expected observer for superview to be informed just once.")
var disposeBag = DisposeBag()
viewModel.superview.subscribe { newSuperview, _ in
guard newSuperview != nil else {
// Skip initial call to observer.
return
}
expectation.fulfill()
}.disposed(by: &disposeBag)
// When
for _ in 1 ... 3 {
sharedApplicationMock.keyWindow = UIWindow()
notificationCenter.post(name: UIWindow.didBecomeKeyNotification,
object: nil)
}
// Then
wait(for: [expectation], timeout: 0.1)
}
// MARK: - Test observable `visibilityAnimation`
func testInitializerShouldSetupVisibilityAnimationObservableWithImmediatelyHidden() {
// Then
let receivedVisibilityAnimation = viewModel.visibilityAnimation.value
let expectedVisibilityAnimation = VisibilityAnimation.immediatelyHidden
XCTAssertEqual(receivedVisibilityAnimation, expectedVisibilityAnimation)
}
func testShowShouldUpdateVisibilityAnimationObservable() {
// When
viewModel.show()
// Then
let receivedVisibilityAnimation = viewModel.visibilityAnimation.value
let expectedVisibilityAnimation = VisibilityAnimation(duration: viewModel.fadeInDuration,
isHidden: false)
XCTAssertEqual(receivedVisibilityAnimation, expectedVisibilityAnimation)
}
func testHideShouldUpdateVisibilityAnimationObservable() {
// When
viewModel.hide()
// Then
let receivedVisibilityAnimation = viewModel.visibilityAnimation.value
let expectedVisibilityAnimation = VisibilityAnimation(duration: viewModel.fadeOutDuration,
isHidden: true)
XCTAssertEqual(receivedVisibilityAnimation, expectedVisibilityAnimation)
}
}
// MARK: - Mocks
class SharedApplicationMock: UIApplicationProtocol {
var keyWindow: UIWindow?
}