Add Unit tests
This commit is contained in:
parent
a4e4611b2a
commit
20bdda6747
Binary file not shown.
|
@ -26,7 +26,8 @@
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
codeCoverageEnabled = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
skipped = "NO">
|
skipped = "NO">
|
||||||
|
|
|
@ -23,7 +23,7 @@ public enum SModalStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SModal {
|
public class SModal {
|
||||||
static let modalWindow: UIWindow = {
|
public static let modalWindow: UIWindow = {
|
||||||
let window = UIWindow(frame: UIScreen.main.bounds)
|
let window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
window.backgroundColor = .clear
|
window.backgroundColor = .clear
|
||||||
window.windowLevel = windowLevel
|
window.windowLevel = windowLevel
|
||||||
|
@ -31,15 +31,31 @@ public class SModal {
|
||||||
return window
|
return window
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var stack: [SModalPresentation] = []
|
public static var stack: [SModalPresentation] = []
|
||||||
|
|
||||||
static var windowLevel: UIWindowLevel {
|
public static var shouldMakeKey: Bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var windowLevel: UIWindowLevel {
|
||||||
return UIWindowLevelAlert - 1
|
return UIWindowLevelAlert - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
static var animationDuration: TimeInterval {
|
public static var animationDuration: TimeInterval {
|
||||||
return 0.2
|
return 0.2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate static func dropRootViewController() {
|
||||||
|
modalWindow.isHidden = true
|
||||||
|
modalWindow.rootViewController = nil
|
||||||
|
modalWindow.resignKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate static func makeKey() {
|
||||||
|
if shouldMakeKey {
|
||||||
|
SModal.modalWindow.makeKey()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol SModalStack {
|
public protocol SModalStack {
|
||||||
|
@ -79,29 +95,29 @@ extension SModalPresentation {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SModalPresentation where Self: UIViewController {
|
extension SModalPresentation where Self: UIViewController {
|
||||||
func sReplace<T: UIViewController>(with controller: T, animated: Bool, completion: (() -> Void)?) where T: SModalPresentation {
|
public func sReplace<T: UIViewController>(with controller: T, animated: Bool = false, completion: (() -> Void)? = nil) where T: SModalPresentation {
|
||||||
if animated {
|
if animated {
|
||||||
SModal.modalWindow.isHidden = false
|
SModal.modalWindow.isHidden = false
|
||||||
UIView.animate(withDuration: SModal.animationDuration, animations: {
|
UIView.animate(withDuration: SModal.animationDuration, animations: {
|
||||||
SModal.modalWindow.rootViewController = controller
|
SModal.modalWindow.rootViewController = controller
|
||||||
SModal.modalWindow.makeKey()
|
SModal.makeKey()
|
||||||
SModal.modalWindow.alpha = 1
|
SModal.modalWindow.alpha = 1
|
||||||
}, completion: { completed in
|
}, completion: { completed in
|
||||||
completion?()
|
completion?()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
SModal.modalWindow.rootViewController = controller
|
SModal.modalWindow.rootViewController = controller
|
||||||
SModal.modalWindow.makeKey()
|
SModal.makeKey()
|
||||||
SModal.modalWindow.isHidden = false
|
SModal.modalWindow.isHidden = false
|
||||||
completion?()
|
completion?()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func sPresent(animated: Bool, completion: (() -> Void)?) {
|
public func sPresent(animated: Bool = false, completion: (() -> Void)? = nil) {
|
||||||
guard let currentPresented = SModal.modalWindow.rootViewController else {
|
guard let currentPresented = SModal.modalWindow.rootViewController else {
|
||||||
SModal.modalWindow.rootViewController = self
|
SModal.modalWindow.rootViewController = self
|
||||||
SModal.modalWindow.makeKey()
|
SModal.makeKey()
|
||||||
if animated {
|
if animated {
|
||||||
SModal.modalWindow.alpha = 0
|
SModal.modalWindow.alpha = 0
|
||||||
SModal.modalWindow.isHidden = false
|
SModal.modalWindow.isHidden = false
|
||||||
|
@ -116,40 +132,39 @@ extension SModalPresentation where Self: UIViewController {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let sModalController = currentPresented as? Self, sModalController.canDismiss == true {
|
SModal.stack.append(self)
|
||||||
sModalController.sReplace(with: self, animated: animated, completion: completion)
|
if (currentPresented as? SModalPresentation)?.canDismiss == true {
|
||||||
|
(currentPresented as? SModalPresentation)?.sWithdraw(animated: animated, completion: completion)
|
||||||
} else {
|
} else {
|
||||||
SModal.stack.append(self)
|
completion?()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sWithdraw(animated: Bool, completion: (() -> Void)?) {
|
public func sWithdraw(animated: Bool = false, completion: (() -> Void)? = nil) {
|
||||||
|
func completedProcedure() {
|
||||||
|
if let controller = SModal.stack.sorted(by: {$0.priority > $1.priority}).first {
|
||||||
|
SModal.stack = SModal.stack.filter({ $0 !== controller })
|
||||||
|
controller.sPresent(animated: animated, completion: completion)
|
||||||
|
}else {
|
||||||
|
completion?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if SModal.modalWindow.rootViewController === self {
|
if SModal.modalWindow.rootViewController === self {
|
||||||
if animated {
|
if animated {
|
||||||
SModal.modalWindow.alpha = 1
|
SModal.modalWindow.alpha = 1
|
||||||
UIView.animate(withDuration: SModal.animationDuration, animations: {
|
UIView.animate(withDuration: SModal.animationDuration, animations: {
|
||||||
SModal.modalWindow.alpha = 0
|
SModal.modalWindow.alpha = 0
|
||||||
}, completion: { completed in
|
}, completion: { completed in
|
||||||
SModal.modalWindow.isHidden = true
|
SModal.dropRootViewController()
|
||||||
completion?()
|
completedProcedure()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
SModal.modalWindow.isHidden = true
|
SModal.dropRootViewController()
|
||||||
completion?()
|
completedProcedure()
|
||||||
}
|
}
|
||||||
SModal.modalWindow.rootViewController = nil
|
|
||||||
SModal.modalWindow.resignKey()
|
|
||||||
} else if SModal.stack.contains(where: { $0 === self }) {
|
} else if SModal.stack.contains(where: { $0 === self }) {
|
||||||
SModal.stack = SModal.stack.filter() { !($0 === self) }
|
SModal.stack = SModal.stack.filter() { !($0 === self) }
|
||||||
}
|
}
|
||||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + SModal.animationDuration) {
|
|
||||||
if let controller = SModal.stack.sorted(by: {$0.priority > $1.priority}).first {
|
|
||||||
SModal.stack.removeFirst()
|
|
||||||
controller.sPresent(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,23 +13,166 @@ class SWindowTests: XCTestCase {
|
||||||
|
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tearDown() {
|
override func tearDown() {
|
||||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
|
||||||
super.tearDown()
|
super.tearDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExample() {
|
func testLowPriority() {
|
||||||
// This is an example of a functional test case.
|
XCTAssert(SModalPriority.Low == 250)
|
||||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPerformanceExample() {
|
func testRequiredPriority() {
|
||||||
// This is an example of a performance test case.
|
XCTAssert(SModalPriority.Required == 500)
|
||||||
self.measure {
|
}
|
||||||
// Put the code you want to measure the time of here.
|
|
||||||
|
func testHighPriority() {
|
||||||
|
XCTAssert(SModalPriority.High == 750)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSModalWindow() {
|
||||||
|
XCTAssertNotNil(SModal.modalWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSModalWindowLevel() {
|
||||||
|
XCTAssert(SModal.windowLevel == UIWindowLevelAlert - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSModalWindowStack() {
|
||||||
|
XCTAssertNotNil(SModal.stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSModalDuration() {
|
||||||
|
XCTAssertEqualWithAccuracy(SModal.animationDuration, 0.2, accuracy: 0.01)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalCanDismiss() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
XCTAssert(!controller.canDismiss)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalStatusNone() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
XCTAssert(controller.modalStatus == .none)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalStatusPresented() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
SModal.modalWindow.rootViewController = controller
|
||||||
|
XCTAssert(controller.modalStatus == .presented)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalStatusWaitingInStack() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
SModal.stack.append(controller)
|
||||||
|
XCTAssert(controller.modalStatus == .waitingInStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalStatusStack() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
XCTAssertNotNil(controller.stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalStatusPriority() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
XCTAssertNotNil(controller.priority == .Required)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalPresentationStack() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
SModal.modalWindow.rootViewController = controller
|
||||||
|
|
||||||
|
let controllerToPresent = Controller()
|
||||||
|
controllerToPresent.sPresent()
|
||||||
|
XCTAssert(SModal.stack.contains(where: { $0 === controllerToPresent }))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalPresentationCanDismiss() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {
|
||||||
|
var canDismiss: Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let controller = Controller()
|
||||||
|
SModal.modalWindow.rootViewController = controller
|
||||||
|
class ControllerHigh: UIViewController, SModalPresentation {}
|
||||||
|
let controllerToPresent = ControllerHigh()
|
||||||
|
controllerToPresent.sPresent {
|
||||||
|
XCTAssertTrue(SModal.modalWindow.rootViewController === controllerToPresent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalPresentationStackWithdraw() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
|
||||||
|
class ControllerTwo: UIViewController, SModalPresentation {}
|
||||||
|
let controllerTwo = ControllerTwo()
|
||||||
|
|
||||||
|
class ControllerThree: UIViewController, SModalPresentation {}
|
||||||
|
let controllerThree = ControllerThree()
|
||||||
|
|
||||||
|
SModal.stack.append(controller)
|
||||||
|
SModal.stack.append(controllerTwo)
|
||||||
|
SModal.stack.append(controllerThree)
|
||||||
|
|
||||||
|
controllerTwo.sWithdraw {
|
||||||
|
XCTAssertFalse(controller.modalStatus == .waitingInStack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalPresentationPriorityAnimated() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {
|
||||||
|
var canDismiss: Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let controller = Controller()
|
||||||
|
SModal.modalWindow.rootViewController = controller
|
||||||
|
class ControllerHigh: UIViewController, SModalPresentation {}
|
||||||
|
let controllerToPresent = ControllerHigh()
|
||||||
|
controllerToPresent.sPresent(animated: true) {
|
||||||
|
XCTAssertFalse(SModal.modalWindow.rootViewController === controller)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalPresentationStackWithdrawAnimated() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
|
||||||
|
class ControllerTwo: UIViewController, SModalPresentation {}
|
||||||
|
let controllerTwo = ControllerTwo()
|
||||||
|
|
||||||
|
class ControllerThree: UIViewController, SModalPresentation {}
|
||||||
|
let controllerThree = ControllerThree()
|
||||||
|
|
||||||
|
SModal.stack.append(controller)
|
||||||
|
SModal.stack.append(controllerTwo)
|
||||||
|
SModal.stack.append(controllerThree)
|
||||||
|
|
||||||
|
controllerTwo.sWithdraw(animated: true) {
|
||||||
|
XCTAssertFalse(controller.modalStatus == .waitingInStack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testModalPresentationReplace() {
|
||||||
|
class Controller: UIViewController, SModalPresentation {}
|
||||||
|
let controller = Controller()
|
||||||
|
|
||||||
|
class ControllerTwo: UIViewController, SModalPresentation {}
|
||||||
|
let controllerTwo = ControllerTwo()
|
||||||
|
|
||||||
|
SModal.modalWindow.rootViewController = controller
|
||||||
|
controller.sReplace(with: controllerTwo) {
|
||||||
|
XCTAssertTrue(SModal.modalWindow.rootViewController === controllerTwo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue