From ad4fedc1f0039a0efca89f19860f5885de401cd1 Mon Sep 17 00:00:00 2001 From: CosynPa Date: Wed, 9 Mar 2016 22:36:34 +0800 Subject: [PATCH] Add tests --- TZStackView.xcodeproj/project.pbxproj | 4 + TZStackViewTests/HidingAnimationTests.swift | 290 ++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 TZStackViewTests/HidingAnimationTests.swift diff --git a/TZStackView.xcodeproj/project.pbxproj b/TZStackView.xcodeproj/project.pbxproj index cf969b2..5e0aab0 100644 --- a/TZStackView.xcodeproj/project.pbxproj +++ b/TZStackView.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 5F50EAD959E8ACC5929DBD75 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB41AF691B294B8E003DB902 /* NSLayoutConstraintExtension.swift */; }; 5F50EF474D670FC33E8E80EA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F50ED5A43FBFC32B9B9E1AA /* Images.xcassets */; }; 7E44D3921C906B1800A3D266 /* TZFuncAnimationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E44D3911C906B1800A3D266 /* TZFuncAnimationDelegate.swift */; }; + 7E44D3941C906C3F00A3D266 /* HidingAnimationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E44D3931C906C3F00A3D266 /* HidingAnimationTests.swift */; }; A45441C21B9B6D71002452BA /* TZStackView.h in Headers */ = {isa = PBXBuildFile; fileRef = A45441C11B9B6D71002452BA /* TZStackView.h */; settings = {ATTRIBUTES = (Public, ); }; }; A45441C61B9B6D71002452BA /* TZStackView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A45441BF1B9B6D71002452BA /* TZStackView.framework */; }; A45441C71B9B6D71002452BA /* TZStackView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A45441BF1B9B6D71002452BA /* TZStackView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -69,6 +70,7 @@ 5F50EF54F01A3A6938C6CEA1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 5F50EFD0C46B7C7F989F10E1 /* TZStackViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TZStackViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7E44D3911C906B1800A3D266 /* TZFuncAnimationDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TZFuncAnimationDelegate.swift; sourceTree = ""; }; + 7E44D3931C906C3F00A3D266 /* HidingAnimationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HidingAnimationTests.swift; sourceTree = ""; }; A45441BF1B9B6D71002452BA /* TZStackView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TZStackView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A45441C11B9B6D71002452BA /* TZStackView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TZStackView.h; sourceTree = ""; }; A45441C31B9B6D71002452BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -130,6 +132,7 @@ isa = PBXGroup; children = ( 5F50EDEB0947F99E67140FC6 /* TZStackViewTests.swift */, + 7E44D3931C906C3F00A3D266 /* HidingAnimationTests.swift */, DB5B70841B2A1963006043BD /* TestView.swift */, DB5B70861B2B8816006043BD /* TZStackViewTestCase.swift */, 5F50E05A91CC731E5AFD4E94 /* Supporting Files */, @@ -329,6 +332,7 @@ DB5B70871B2B8816006043BD /* TZStackViewTestCase.swift in Sources */, DB5B70851B2A1963006043BD /* TestView.swift in Sources */, 5F50EAD959E8ACC5929DBD75 /* NSLayoutConstraintExtension.swift in Sources */, + 7E44D3941C906C3F00A3D266 /* HidingAnimationTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/TZStackViewTests/HidingAnimationTests.swift b/TZStackViewTests/HidingAnimationTests.swift new file mode 100644 index 0000000..78d3f44 --- /dev/null +++ b/TZStackViewTests/HidingAnimationTests.swift @@ -0,0 +1,290 @@ +// +// HidingAnimationTests.swift +// TZStackView +// +// Created by CosynPa on 3/6/16. +// Copyright © 2016 Tom van Zummeren. All rights reserved. +// + +import Foundation +import UIKit +import XCTest +import TZStackView + +class HidingAnimationTests: TZStackViewTestCase { + var uiTestView: UIView! + var tzTestView: UIView! + + override func createTestViews() -> [UIView] { + var views = [UIView]() + for i in 0 ..< 5 { + views.append(TestView(index: i, size: CGSize(width: 100 * (i + 1), height: 100 * (i + 1)))) + } + return views + } + + override func setUp() { + super.setUp() + uiTestView = uiStackView.arrangedSubviews.last! + tzTestView = tzStackView.arrangedSubviews.last! + } + + // If you are not animating the hidden property, the hidden property should be set immediately + func testNonAnimatingHidden() { + let expectation = expectationWithDescription("delay") + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + self.uiTestView.hidden = true + self.tzTestView.hidden = true + + XCTAssert(self.uiTestView.hidden) + XCTAssert(self.tzTestView.hidden) + XCTAssert(self.uiTestView.layer.hidden) + XCTAssert(self.tzTestView.layer.hidden) + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.2 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + expectation.fulfill() + } + + waitForExpectationsWithTimeout(100, handler: nil) + } + + // If you are not animating the hidden property, the hidden property should be set immediately + func testNonAnimatingHiddenWithOther() { + let expectation = expectationWithDescription("delay") + + uiTestView.backgroundColor = UIColor.clearColor() + tzTestView.backgroundColor = UIColor.clearColor() + UIView.animateWithDuration(2) { + self.uiTestView.backgroundColor = UIColor.greenColor() + self.tzTestView.backgroundColor = UIColor.greenColor() + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + self.uiTestView.hidden = true + self.tzTestView.hidden = true + + XCTAssert(self.uiTestView.hidden) + XCTAssert(self.tzTestView.hidden) + XCTAssert(self.uiTestView.layer.hidden) + XCTAssert(self.tzTestView.layer.hidden) + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.2 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + expectation.fulfill() + } + + waitForExpectationsWithTimeout(100, handler: nil) + } + + func animationHiddenWithDelay(delay: NSTimeInterval) { + let expectation = expectationWithDescription("delay") + + let duration = 1.0 + + UIView.animateWithDuration(duration, delay: delay, options: [], + animations: { () -> Void in + self.uiTestView.hidden = true + self.tzTestView.hidden = true + + // Note uiTestView.hidden == true, tzTestView.hidden == false + + // The presentation should not be hidden. + XCTAssert(!self.uiTestView.layer.hidden) + XCTAssert(!self.tzTestView.layer.hidden) + + }, completion: { _ in + XCTAssert(self.uiTestView.hidden) + XCTAssert(self.tzTestView.hidden) + XCTAssert(self.uiTestView.layer.hidden) + XCTAssert(self.tzTestView.layer.hidden) + }) + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64((duration + delay + 0.2) * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + XCTAssert(self.uiTestView.hidden) + XCTAssert(self.tzTestView.hidden) + XCTAssert(self.uiTestView.layer.hidden) + XCTAssert(self.tzTestView.layer.hidden) + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64((duration + delay + 0.4) * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + expectation.fulfill() + } + + waitForExpectationsWithTimeout(100, handler: nil) + } + + func testAnimatingHidden() { + animationHiddenWithDelay(0) + } + + func testAnimatingHiddenWithDelay() { + animationHiddenWithDelay(1) + } + + func testAnimatingHiddenWithOther() { + let expectation = expectationWithDescription("delay") + + UIView.animateWithDuration(1) { + self.uiTestView.hidden = true + self.tzTestView.hidden = true + } + + uiTestView.backgroundColor = UIColor.clearColor() + tzTestView.backgroundColor = UIColor.clearColor() + UIView.animateWithDuration(2) { + self.uiTestView.backgroundColor = UIColor.greenColor() + self.tzTestView.backgroundColor = UIColor.greenColor() + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.2 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + // The view should be hidden after the hiding animation completes even if there are still other animations + XCTAssert(self.uiTestView.hidden) + XCTAssert(self.tzTestView.hidden) + XCTAssert(self.uiTestView.layer.hidden) + XCTAssert(self.tzTestView.layer.hidden) + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2.2 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + expectation.fulfill() + } + + waitForExpectationsWithTimeout(100, handler: nil) + } + + // The completion callback of an animation should be called + func testHidingAnimationCallback() { + let expectation = expectationWithDescription("delay") + + var uiCompletionCalled = false + var tzCompletionCalled = false + + UIView.animateWithDuration(1, + animations: { + self.uiTestView.hidden = true + }, completion: { _ in + uiCompletionCalled = true + }) + + UIView.animateWithDuration(1, + animations: { + self.tzTestView.hidden = true + }, completion: { _ in + tzCompletionCalled = true + }) + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.2 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + XCTAssert(uiCompletionCalled) + XCTAssert(tzCompletionCalled) + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.4 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + expectation.fulfill() + } + + waitForExpectationsWithTimeout(100, handler: nil) + } + + // The completion callback of an animation should be called when the animation is canceled + func testHidingAnimationCallbackCancel() { + let expectation = expectationWithDescription("delay") + + var uiCompletionCalled = false + var tzCompletionCalled = false + + UIView.animateWithDuration(1, + animations: { + self.uiTestView.hidden = true + }, completion: { finished in + uiCompletionCalled = true + XCTAssert(!finished) + }) + + UIView.animateWithDuration(1, + animations: { + self.tzTestView.hidden = true + }, completion: { finished in + tzCompletionCalled = true + XCTAssert(!finished) + }) + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + // This will cancel the animation + self.uiStackView.removeFromSuperview() + self.tzStackView.removeFromSuperview() + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.7 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + XCTAssert(uiCompletionCalled) + XCTAssert(tzCompletionCalled) + XCTAssert(self.uiTestView.hidden) + XCTAssert(self.tzTestView.hidden) + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.4 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + expectation.fulfill() + } + + waitForExpectationsWithTimeout(100, handler: nil) + } + + // When set the hidden property in the middle of an animation, the hidden property should be updated eventually + func hidingAnimationSetAgainFirstHidden(firstHidden: Bool, withAnimation: Bool) { + let expectation = expectationWithDescription("delay") + + uiTestView.hidden = firstHidden + tzTestView.hidden = firstHidden + + UIView.animateWithDuration(2) { + self.uiTestView.hidden = !firstHidden + self.tzTestView.hidden = !firstHidden + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + if !withAnimation { + self.uiTestView.hidden = firstHidden + self.tzTestView.hidden = firstHidden + } else { + UIView.animateWithDuration(2) { + self.uiTestView.hidden = firstHidden + self.tzTestView.hidden = firstHidden + + // Animating, the presentation is not hidden + XCTAssert(!self.uiTestView.layer.hidden) + XCTAssert(!self.tzTestView.layer.hidden) + } + } + + // Note, here we don't expect the hidden property to be the right value even when without animation, + } + + let endTime = !withAnimation ? 2.2 : 3.2 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(endTime * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + XCTAssert(self.uiTestView.hidden == firstHidden) + XCTAssert(self.tzTestView.hidden == firstHidden) + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64((endTime + 0.2) * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { + expectation.fulfill() + } + + waitForExpectationsWithTimeout(100, handler: nil) + } + + func testHidingAnimationSetAgainFirstNotHidden() { + hidingAnimationSetAgainFirstHidden(false, withAnimation: false) + } + + func testHidingAnimationSetAgainFirstHidden() { + hidingAnimationSetAgainFirstHidden(true, withAnimation: false) + } + + func testHidingAnimationSetAgainFirstNotHiddenWithAnimation() { + hidingAnimationSetAgainFirstHidden(false, withAnimation: true) + } + + func testHidingAnimationSetAgainFirstHiddenWithAnimation() { + hidingAnimationSetAgainFirstHidden(true, withAnimation: true) + } +} \ No newline at end of file