From 28a82bdaf7de626dccf460c81b06e9dc781bbd29 Mon Sep 17 00:00:00 2001 From: Felix Mau Date: Sun, 25 Aug 2019 22:34:48 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20::=20Adapt=20test=20cases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project.pbxproj | 22 +- .../GradientLoadingBarViewModelTestCase.swift | 202 ------------------ ...dicatorView+AnimateIsHiddenTestCase.swift} | 56 ++--- .../GradientLoadingBarViewModelTestCase.swift | 147 +++++++++++++ 4 files changed, 186 insertions(+), 241 deletions(-) delete mode 100644 Example/Tests/GradientLoadingBarViewModelTestCase.swift rename Example/Tests/{Extensions/UIView/UIView+AnimateIsHiddenTestCase.swift => View/GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift} (58%) create mode 100644 Example/Tests/ViewModel/GradientLoadingBarViewModelTestCase.swift diff --git a/Example/GradientLoadingBar.xcodeproj/project.pbxproj b/Example/GradientLoadingBar.xcodeproj/project.pbxproj index 30ac747..f6bfac7 100644 --- a/Example/GradientLoadingBar.xcodeproj/project.pbxproj +++ b/Example/GradientLoadingBar.xcodeproj/project.pbxproj @@ -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 = ""; }; 64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModelTestCase.swift; sourceTree = ""; }; - 64E7F4242293E16B00BE5095 /* UIView+AnimateIsHiddenTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+AnimateIsHiddenTestCase.swift"; sourceTree = ""; }; + 64E7F4242293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift"; sourceTree = ""; }; 972CFBCB2138849A006F14C9 /* SafeAreaExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeAreaExampleViewController.swift; sourceTree = ""; }; 97464E6621372BCD0097183A /* AdvancedExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedExampleViewController.swift; sourceTree = ""; }; 97464E6821372C010097183A /* NavigationBarExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarExampleViewController.swift; sourceTree = ""; }; @@ -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 = ""; }; - 64E7F4222293E16B00BE5095 /* Extensions */ = { + 64C6B3E72313259500076A69 /* ViewModel */ = { isa = PBXGroup; children = ( - 64E7F4232293E16B00BE5095 /* UIView */, + 64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */, ); - path = Extensions; + path = ViewModel; sourceTree = ""; }; - 64E7F4232293E16B00BE5095 /* UIView */ = { + 64E7F4222293E16B00BE5095 /* View */ = { isa = PBXGroup; children = ( - 64E7F4242293E16B00BE5095 /* UIView+AnimateIsHiddenTestCase.swift */, + 64E7F4242293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift */, ); - path = UIView; + path = View; sourceTree = ""; }; 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; }; diff --git a/Example/Tests/GradientLoadingBarViewModelTestCase.swift b/Example/Tests/GradientLoadingBarViewModelTestCase.swift deleted file mode 100644 index f592373..0000000 --- a/Example/Tests/GradientLoadingBarViewModelTestCase.swift +++ /dev/null @@ -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? -} diff --git a/Example/Tests/Extensions/UIView/UIView+AnimateIsHiddenTestCase.swift b/Example/Tests/View/GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift similarity index 58% rename from Example/Tests/Extensions/UIView/UIView+AnimateIsHiddenTestCase.swift rename to Example/Tests/View/GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift index 0fd140c..f43255a 100644 --- a/Example/Tests/Extensions/UIView/UIView+AnimateIsHiddenTestCase.swift +++ b/Example/Tests/View/GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift @@ -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`.") } } diff --git a/Example/Tests/ViewModel/GradientLoadingBarViewModelTestCase.swift b/Example/Tests/ViewModel/GradientLoadingBarViewModelTestCase.swift new file mode 100644 index 0000000..2595b90 --- /dev/null +++ b/Example/Tests/ViewModel/GradientLoadingBarViewModelTestCase.swift @@ -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? +}