From a91d95713f754ffa34ffe3f4e4f2c47e3e173f68 Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Wed, 20 Jul 2016 17:44:50 +0300 Subject: [PATCH] #127: Use Clean Architecture for NumberOfKeys Scene + Unit Tests Improve unit tests for KeyType scene --- .../GroupLock.xcodeproj/project.pbxproj | 42 +++- .../GroupLock/Base.lproj/Main.storyboard | 12 +- .../KeyTypeScene/KeyTypeInteractor.swift | 4 +- .../KeyTypeScene/KeyTypeRouter.swift | 2 +- .../KeyTypeScene/KeyTypeViewController.swift | 2 +- .../NumberOfKeysConfigurator.swift | 40 ++++ .../NumberOfKeysInteractor.swift | 29 +++ .../NumberOfKeysModels.swift | 14 ++ .../NumberOfKeysPresenter.swift | 25 +++ .../NumberOfKeysRouter.swift | 36 ++++ .../NumberOfKeysViewController.swift | 44 ++-- .../ProvideKeyScene/ProvideKeyPresenter.swift | 1 + .../KeyTypeInteractorTests.swift | 5 - .../KeyTypeViewControllerTests.swift | 19 +- .../NumberOfKeysInteractorTests.swift | 40 ++++ .../NumberOfKeysViewControllerTests.swift | 190 ++++++++++++++++++ 16 files changed, 461 insertions(+), 44 deletions(-) create mode 100644 GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysConfigurator.swift create mode 100644 GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysInteractor.swift create mode 100644 GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysModels.swift create mode 100644 GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysPresenter.swift create mode 100644 GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysRouter.swift create mode 100644 GroupLockiOS/GroupLockTests/NumberOfKeysInteractorTests.swift create mode 100644 GroupLockiOS/GroupLockTests/NumberOfKeysViewControllerTests.swift diff --git a/GroupLockiOS/GroupLock.xcodeproj/project.pbxproj b/GroupLockiOS/GroupLock.xcodeproj/project.pbxproj index 304803d..8a4a142 100644 --- a/GroupLockiOS/GroupLock.xcodeproj/project.pbxproj +++ b/GroupLockiOS/GroupLock.xcodeproj/project.pbxproj @@ -17,6 +17,13 @@ 8704DED01D3D03990017F88E /* ProvideKeyRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8704DEC91D3D03990017F88E /* ProvideKeyRouter.swift */; }; 8704DED11D3D03990017F88E /* ProvideKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8704DECA1D3D03990017F88E /* ProvideKeyViewController.swift */; }; 8704DED51D3D08320017F88E /* Crypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8704DED41D3D08320017F88E /* Crypto.swift */; }; + 870DBF921D3F932C004430A5 /* NumberOfKeysConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 870DBF8C1D3F932C004430A5 /* NumberOfKeysConfigurator.swift */; }; + 870DBF931D3F932C004430A5 /* NumberOfKeysInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 870DBF8D1D3F932C004430A5 /* NumberOfKeysInteractor.swift */; }; + 870DBF941D3F932C004430A5 /* NumberOfKeysModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 870DBF8E1D3F932C004430A5 /* NumberOfKeysModels.swift */; }; + 870DBF951D3F932C004430A5 /* NumberOfKeysPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 870DBF8F1D3F932C004430A5 /* NumberOfKeysPresenter.swift */; }; + 870DBF961D3F932C004430A5 /* NumberOfKeysRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 870DBF901D3F932C004430A5 /* NumberOfKeysRouter.swift */; }; + 870DBF9E1D3F9BE9004430A5 /* NumberOfKeysInteractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 870DBF9A1D3F9BE9004430A5 /* NumberOfKeysInteractorTests.swift */; }; + 870DBFA01D3F9BE9004430A5 /* NumberOfKeysViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 870DBF9C1D3F9BE9004430A5 /* NumberOfKeysViewControllerTests.swift */; }; 8713DE4B1CEFA5400089C92A /* ChooseFileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8713DE4A1CEFA5400089C92A /* ChooseFileViewController.swift */; }; 8713DE4F1CEFAAF30089C92A /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8713DE4E1CEFAAF30089C92A /* HomeViewController.swift */; }; 871C6AE11CF1E8A7004C5B38 /* NUIGeneralViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 871C6AE01CF1E8A7004C5B38 /* NUIGeneralViewTests.swift */; }; @@ -113,6 +120,13 @@ 8704DEC91D3D03990017F88E /* ProvideKeyRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProvideKeyRouter.swift; path = Scenes/Home_Stack/ProvideKeyScene/ProvideKeyRouter.swift; sourceTree = ""; }; 8704DECA1D3D03990017F88E /* ProvideKeyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProvideKeyViewController.swift; path = Scenes/Home_Stack/ProvideKeyScene/ProvideKeyViewController.swift; sourceTree = ""; }; 8704DED41D3D08320017F88E /* Crypto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Crypto.swift; path = Core/Crypto.swift; sourceTree = ""; }; + 870DBF8C1D3F932C004430A5 /* NumberOfKeysConfigurator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NumberOfKeysConfigurator.swift; path = Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysConfigurator.swift; sourceTree = ""; }; + 870DBF8D1D3F932C004430A5 /* NumberOfKeysInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NumberOfKeysInteractor.swift; path = Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysInteractor.swift; sourceTree = ""; }; + 870DBF8E1D3F932C004430A5 /* NumberOfKeysModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NumberOfKeysModels.swift; path = Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysModels.swift; sourceTree = ""; }; + 870DBF8F1D3F932C004430A5 /* NumberOfKeysPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NumberOfKeysPresenter.swift; path = Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysPresenter.swift; sourceTree = ""; }; + 870DBF901D3F932C004430A5 /* NumberOfKeysRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NumberOfKeysRouter.swift; path = Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysRouter.swift; sourceTree = ""; }; + 870DBF9A1D3F9BE9004430A5 /* NumberOfKeysInteractorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberOfKeysInteractorTests.swift; sourceTree = ""; }; + 870DBF9C1D3F9BE9004430A5 /* NumberOfKeysViewControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberOfKeysViewControllerTests.swift; sourceTree = ""; }; 8713DE4A1CEFA5400089C92A /* ChooseFileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChooseFileViewController.swift; path = Scenes/Home_Stack/ChooseFileScene/ChooseFileViewController.swift; sourceTree = ""; }; 8713DE4E1CEFAAF30089C92A /* HomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HomeViewController.swift; path = Scenes/Home_Stack/HomeViewController.swift; sourceTree = ""; }; 871C6AE01CF1E8A7004C5B38 /* NUIGeneralViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NUIGeneralViewTests.swift; sourceTree = ""; }; @@ -244,6 +258,15 @@ name = Core; sourceTree = ""; }; + 870DBF991D3F9BBB004430A5 /* NumberOfKeysSceneTests */ = { + isa = PBXGroup; + children = ( + 870DBF9A1D3F9BE9004430A5 /* NumberOfKeysInteractorTests.swift */, + 870DBF9C1D3F9BE9004430A5 /* NumberOfKeysViewControllerTests.swift */, + ); + name = NumberOfKeysSceneTests; + sourceTree = ""; + }; 8713DE4C1CEFA5520089C92A /* Library Stack */ = { isa = PBXGroup; children = ( @@ -315,13 +338,13 @@ name = PasswordScene; sourceTree = ""; }; - 87736F181D3D562800B93D7B /* KeyTypesceneTests */ = { + 87736F181D3D562800B93D7B /* KeyTypeSceneTests */ = { isa = PBXGroup; children = ( 87736F191D3D565300B93D7B /* KeyTypeInteractorTests.swift */, 87736F1B1D3D565300B93D7B /* KeyTypeViewControllerTests.swift */, ); - name = KeyTypesceneTests; + name = KeyTypeSceneTests; sourceTree = ""; }; 877ED3301CF7B1F000C5D0D4 /* ViewController Tests */ = { @@ -425,7 +448,8 @@ 873419B31D3817A0005D036C /* Test Resources */, 87FFF0341D33BFB1007315C7 /* PasswordSceneTests */, 874801871D36C3F8001A086C /* ChooseFileSceneTests */, - 87736F181D3D562800B93D7B /* KeyTypesceneTests */, + 87736F181D3D562800B93D7B /* KeyTypeSceneTests */, + 870DBF991D3F9BBB004430A5 /* NumberOfKeysSceneTests */, 877ED3301CF7B1F000C5D0D4 /* ViewController Tests */, 87B072C61CC0E0C400916D09 /* NUI Tests */, 87B6922A1CB425E0008ACB6A /* Info.plist */, @@ -465,7 +489,12 @@ 87FAC9EF1D34ECBE00FE3602 /* NumberOfKeysScene */ = { isa = PBXGroup; children = ( + 870DBF901D3F932C004430A5 /* NumberOfKeysRouter.swift */, 8AE919D91D2F508A002024AC /* NumberOfKeysViewController.swift */, + 870DBF8D1D3F932C004430A5 /* NumberOfKeysInteractor.swift */, + 870DBF8F1D3F932C004430A5 /* NumberOfKeysPresenter.swift */, + 870DBF8C1D3F932C004430A5 /* NumberOfKeysConfigurator.swift */, + 870DBF8E1D3F932C004430A5 /* NumberOfKeysModels.swift */, ); name = NumberOfKeysScene; sourceTree = ""; @@ -779,12 +808,16 @@ 8713DE4B1CEFA5400089C92A /* ChooseFileViewController.swift in Sources */, 87FFF0521D34E9AE007315C7 /* ChooseFileRouter.swift in Sources */, 87736F141D3D49C200B93D7B /* KeyTypeModels.swift in Sources */, + 870DBF951D3F932C004430A5 /* NumberOfKeysPresenter.swift in Sources */, + 870DBF931D3F932C004430A5 /* NumberOfKeysInteractor.swift in Sources */, 8704DED01D3D03990017F88E /* ProvideKeyRouter.swift in Sources */, 87FFF0531D34E9AE007315C7 /* ChooseFileWorker.swift in Sources */, 87B509C11CD0B67A00641EC3 /* FileManager.swift in Sources */, 87FFF0501D34E9AE007315C7 /* ChooseFileModels.swift in Sources */, 87B6927F1CB45188008ACB6A /* UIViewController.swift in Sources */, + 870DBF941D3F932C004430A5 /* NumberOfKeysModels.swift in Sources */, 8AE919DA1D2F508A002024AC /* NumberOfKeysViewController.swift in Sources */, + 870DBF921D3F932C004430A5 /* NumberOfKeysConfigurator.swift in Sources */, 8704DECD1D3D03990017F88E /* ProvideKeyInteractor.swift in Sources */, 8704DED11D3D03990017F88E /* ProvideKeyViewController.swift in Sources */, 8704DEB31D3CCD8E0017F88E /* ManagedFile+CoreDataProperties.swift in Sources */, @@ -797,6 +830,7 @@ 8704DED51D3D08320017F88E /* Crypto.swift in Sources */, 87B692111CB425E0008ACB6A /* AppDelegate.swift in Sources */, 87CF826A1D3E3058000147EB /* ProvideKeyCell.swift in Sources */, + 870DBF961D3F932C004430A5 /* NumberOfKeysRouter.swift in Sources */, 873419B21D37D686005D036C /* GroupLock.xcdatamodeld in Sources */, 87FFF02E1D33ACCE007315C7 /* PasswordConfigurator.swift in Sources */, ); @@ -811,6 +845,7 @@ 87B072E21CC1B7B300916D09 /* NUIPasswordViewTests.swift in Sources */, 877ED32F1CF7B1E300C5D0D4 /* UIViewControllerTests.swift in Sources */, 87C49EA11CF1EBDB006C0A83 /* NUIGeneralTableTests.swift in Sources */, + 870DBF9E1D3F9BE9004430A5 /* NumberOfKeysInteractorTests.swift in Sources */, 87736F1F1D3D565300B93D7B /* KeyTypeViewControllerTests.swift in Sources */, 87B072E41CC1B8E600916D09 /* NUIProceedButtonTests.swift in Sources */, 87C49EA51CF1F349006C0A83 /* NUIGeneralTableCellTests.swift in Sources */, @@ -828,6 +863,7 @@ 877ED3351CF8B18900C5D0D4 /* NUICollectionViewCellTests.swift in Sources */, 87B072DB1CC1AB4200916D09 /* NUIBarButtonTests.swift in Sources */, 8748018D1D36C434001A086C /* ChooseFilePresenterTests.swift in Sources */, + 870DBFA01D3F9BE9004430A5 /* NumberOfKeysViewControllerTests.swift in Sources */, 87B072E71CC1B9F900916D09 /* NUIEnterPasswordLabelTests.swift in Sources */, 87C49EA91CF1FB85006C0A83 /* NUIDirectoryButtonTests.swift in Sources */, ); diff --git a/GroupLockiOS/GroupLock/Base.lproj/Main.storyboard b/GroupLockiOS/GroupLock/Base.lproj/Main.storyboard index a626f8a..a616670 100644 --- a/GroupLockiOS/GroupLock/Base.lproj/Main.storyboard +++ b/GroupLockiOS/GroupLock/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -278,7 +278,7 @@ - + @@ -390,7 +390,7 @@ - + @@ -455,7 +455,7 @@ - + @@ -467,10 +467,10 @@ - + - + diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeInteractor.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeInteractor.swift index 46845de..340ee8b 100644 --- a/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeInteractor.swift +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeInteractor.swift @@ -9,7 +9,7 @@ import Foundation protocol KeyTypeInteractorInput { - var files: [ManagedFile] { get set } + var files: [ManagedFile]! { get set } var keyType: KeyType { get } func setKeyType(request: KeyTypeModels.SetType.Request) @@ -25,7 +25,7 @@ class KeyTypeInteractor: KeyTypeInteractorInput { // MARK: - Business logic - var files = [ManagedFile]() + var files: [ManagedFile]! var keyType: KeyType = .QRCode func setKeyType(request: KeyTypeModels.SetType.Request) { diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeRouter.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeRouter.swift index 9057a21..3fd605c 100644 --- a/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeRouter.swift +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeRouter.swift @@ -34,6 +34,6 @@ class KeyTypeRouter: KeyTypeRouterInput { func passDataToNumberOfKeysScene(segue: UIStoryboardSegue) { let numberOfKeysViewController = segue.destinationViewController as! NumberOfKeysViewController - + numberOfKeysViewController.output.files = viewController.output.files } } diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeViewController.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeViewController.swift index d0e5381..51fc1a0 100644 --- a/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeViewController.swift +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/KeyTypeScene/KeyTypeViewController.swift @@ -13,7 +13,7 @@ protocol KeyTypeViewControllerInput { } protocol KeyTypeViewControllerOutput { - var files: [ManagedFile] { get set } + var files: [ManagedFile]! { get set } var keyType: KeyType { get } func setKeyType(request: KeyTypeModels.SetType.Request) diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysConfigurator.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysConfigurator.swift new file mode 100644 index 0000000..6468e61 --- /dev/null +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysConfigurator.swift @@ -0,0 +1,40 @@ +// +// NumberOfKeysConfigurator.swift +// GroupLock +// +// Created by Sergej Jaskiewicz on 20.07.16. +// Copyright (c) 2016 Lanit-Tercom School. All rights reserved. +// + +import UIKit + +// MARK: - Connect View, Interactor, and Presenter + +extension NumberOfKeysViewController: NumberOfKeysPresenterOutput { + override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + router.passDataToNextScene(segue) + } +} + +extension NumberOfKeysInteractor: NumberOfKeysViewControllerOutput {} + +extension NumberOfKeysPresenter: NumberOfKeysInteractorOutput {} + +class NumberOfKeysConfigurator { + + // MARK: - Configuration + + static func configure(viewController: NumberOfKeysViewController) { + let router = NumberOfKeysRouter() + router.viewController = viewController + + let presenter = NumberOfKeysPresenter() + presenter.output = viewController + + let interactor = NumberOfKeysInteractor() + interactor.output = presenter + + viewController.output = interactor + viewController.router = router + } +} diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysInteractor.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysInteractor.swift new file mode 100644 index 0000000..49d5360 --- /dev/null +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysInteractor.swift @@ -0,0 +1,29 @@ +// +// NumberOfKeysInteractor.swift +// GroupLock +// +// Created by Sergej Jaskiewicz on 20.07.16. +// Copyright (c) 2016 Lanit-Tercom School. All rights reserved. +// + +import Foundation + +protocol NumberOfKeysInteractorInput { + var numberOfKeys: Int { get } + var files: [ManagedFile]! { get } +} + +protocol NumberOfKeysInteractorOutput { + +} + +class NumberOfKeysInteractor: NumberOfKeysInteractorInput { + + var output: NumberOfKeysInteractorOutput! + + // MARK: - Business logic + + var numberOfKeys = Crypto.maximumNumberOfKeys + + var files: [ManagedFile]! +} diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysModels.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysModels.swift new file mode 100644 index 0000000..d1207d5 --- /dev/null +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysModels.swift @@ -0,0 +1,14 @@ +// +// NumberOfKeysModels.swift +// GroupLock +// +// Created by Sergej Jaskiewicz on 20.07.16. +// Copyright (c) 2016 Lanit-Tercom School. All rights reserved. +// + +import Foundation + +// MARK: Scene +struct NumberOfKeys { + +} diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysPresenter.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysPresenter.swift new file mode 100644 index 0000000..faa76c1 --- /dev/null +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysPresenter.swift @@ -0,0 +1,25 @@ +// +// NumberOfKeysPresenter.swift +// GroupLock +// +// Created by Sergej Jaskiewicz on 20.07.16. +// Copyright (c) 2016 Lanit-Tercom School. All rights reserved. +// + +import Foundation + +protocol NumberOfKeysPresenterInput { + +} + +protocol NumberOfKeysPresenterOutput: class { + +} + +class NumberOfKeysPresenter: NumberOfKeysPresenterInput { + + weak var output: NumberOfKeysPresenterOutput! + + // MARK: - Presentation logic + +} diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysRouter.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysRouter.swift new file mode 100644 index 0000000..3149bc6 --- /dev/null +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysRouter.swift @@ -0,0 +1,36 @@ +// +// NumberOfKeysRouter.swift +// GroupLock +// +// Created by Sergej Jaskiewicz on 20.07.16. +// Copyright (c) 2016 Lanit-Tercom School. All rights reserved. +// + +import UIKit + +protocol NumberOfKeysRouterInput { + +} + +class NumberOfKeysRouter: NumberOfKeysRouterInput { + + weak var viewController: NumberOfKeysViewController! + + // MARK: - Navigation + + // MARK: - Communication + + func passDataToNextScene(segue: UIStoryboardSegue) { + + if segue.identifier == "ProvideKey" { + passDataToProvideKeyScene(segue) + } + } + + func passDataToProvideKeyScene(segue: UIStoryboardSegue) { + + let provideKeysViewController = segue.destinationViewController as! ProvideKeyViewController + provideKeysViewController.output.numberOfKeys = (viewController.pickerView.selectedRowInComponent(0) + 1, + viewController.pickerView.selectedRowInComponent(1) + 1) + } +} diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysViewController.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysViewController.swift index 3e6d476..8f00037 100644 --- a/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysViewController.swift +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/NumberOfKeysScene/NumberOfKeysViewController.swift @@ -8,30 +8,40 @@ import UIKit -class NumberOfKeysViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource { +protocol NumberOfKeysViewControllerInput { - @IBOutlet var pickerView: UIPickerView! +} + +protocol NumberOfKeysViewControllerOutput { + var numberOfKeys: Int { get } + var files: [ManagedFile]! { get set } +} + +class NumberOfKeysViewController: UIViewController { - var options = [Int](1...Crypto.maximumNumberOfKeys) + var output: NumberOfKeysViewControllerOutput! + var router: NumberOfKeysRouter! - override func viewDidLoad() { - super.viewDidLoad() - - } + @IBOutlet var pickerView: UIPickerView! +} + +extension NumberOfKeysViewController: UIPickerViewDataSource { func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { return 2 } func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { - return options.count + return output.numberOfKeys } func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { - return "\(options[row])" + return "\(row + 1)" } - +} + +extension NumberOfKeysViewController: UIPickerViewDelegate { func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { if pickerView.selectedRowInComponent(0) > pickerView.selectedRowInComponent(1) { pickerView.selectRow(pickerView.selectedRowInComponent(component), @@ -39,11 +49,11 @@ class NumberOfKeysViewController: UIViewController, UIPickerViewDelegate, UIPick animated: true) } } - - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { - if let destination = segue.destinationViewController as? ProvideKeyViewController { - destination.output.numberOfKeys = (options[pickerView.selectedRowInComponent(0)], - options[pickerView.selectedRowInComponent(1)]) - } +} + +extension NumberOfKeysViewController { + override func awakeFromNib() { + super.awakeFromNib() + NumberOfKeysConfigurator.configure(self) } -} \ No newline at end of file +} diff --git a/GroupLockiOS/GroupLock/Scenes/Home_Stack/ProvideKeyScene/ProvideKeyPresenter.swift b/GroupLockiOS/GroupLock/Scenes/Home_Stack/ProvideKeyScene/ProvideKeyPresenter.swift index ac5526f..7e86185 100644 --- a/GroupLockiOS/GroupLock/Scenes/Home_Stack/ProvideKeyScene/ProvideKeyPresenter.swift +++ b/GroupLockiOS/GroupLock/Scenes/Home_Stack/ProvideKeyScene/ProvideKeyPresenter.swift @@ -29,6 +29,7 @@ class ProvideKeyPresenter: ProvideKeyPresenterInput { var uiImageQRCodes = [UIImage]() for key in keys { + // TODO: Вынести в отдельный класс let data = key.dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false) guard let filter = CIFilter(name: "CIQRCodeGenerator") else { return } filter.setValue(data, forKey: "inputMessage") diff --git a/GroupLockiOS/GroupLockTests/KeyTypeInteractorTests.swift b/GroupLockiOS/GroupLockTests/KeyTypeInteractorTests.swift index 8206cac..4758bc0 100644 --- a/GroupLockiOS/GroupLockTests/KeyTypeInteractorTests.swift +++ b/GroupLockiOS/GroupLockTests/KeyTypeInteractorTests.swift @@ -21,11 +21,6 @@ class KeyTypeInteractorTests: XCTestCase { sut = KeyTypeInteractor() } - override func tearDown() { - - super.tearDown() - } - // MARK: - Test doubles // MARK: - Tests diff --git a/GroupLockiOS/GroupLockTests/KeyTypeViewControllerTests.swift b/GroupLockiOS/GroupLockTests/KeyTypeViewControllerTests.swift index ae10038..c58439d 100644 --- a/GroupLockiOS/GroupLockTests/KeyTypeViewControllerTests.swift +++ b/GroupLockiOS/GroupLockTests/KeyTypeViewControllerTests.swift @@ -60,7 +60,7 @@ class KeyTypeViewControllerTests: XCTestCase { var setKeyType_called = false var receivedKeyName = "none" - var files: [ManagedFile] = [] + var files: [ManagedFile]! var keyType = Seeds.SetKeyType.defaultKeyType func setKeyType(request: KeyTypeModels.SetType.Request) { @@ -71,11 +71,11 @@ class KeyTypeViewControllerTests: XCTestCase { } class KeyTypeRouterSpy: KeyTypeRouter { - - var navigateToNumberOfKeysScene_called = false - - override func navigateToNumberOfKeysScene() { - navigateToNumberOfKeysScene_called = true + + var passDataToNumberOfKeysScene_called = false + + override func passDataToNumberOfKeysScene(segue: UIStoryboardSegue) { + passDataToNumberOfKeysScene_called = true } } @@ -114,11 +114,12 @@ class KeyTypeViewControllerTests: XCTestCase { XCTAssertEqual(expectedValue, returnedValue, "The text on a key type button should be passed to output") } - func test_ThatKeyTypeButtons_PerformSegueToNumberOfKeysScene() { + func test_ThatKeyTypeButtons_TriggerPassingDataToNumberOfKeysScene() { // Given let keyTypeRouterSpy = KeyTypeRouterSpy() sut.router = keyTypeRouterSpy + sut.router.viewController = sut let keyTypeButton = UIButton(type: .Custom) keyTypeButton.titleLabel?.text = Seeds.SetKeyType.buttonLabelText @@ -126,7 +127,7 @@ class KeyTypeViewControllerTests: XCTestCase { sut.onKeyType(keyTypeButton) // Then - XCTAssertTrue(keyTypeRouterSpy.navigateToNumberOfKeysScene_called, - "Tapping on a key type button should trigger a segue to NumberOfKeys scene") + XCTAssertTrue(keyTypeRouterSpy.passDataToNumberOfKeysScene_called, + "Tapping on a key type button should trigger passing data to NumberOfKeys scene") } } diff --git a/GroupLockiOS/GroupLockTests/NumberOfKeysInteractorTests.swift b/GroupLockiOS/GroupLockTests/NumberOfKeysInteractorTests.swift new file mode 100644 index 0000000..6509e64 --- /dev/null +++ b/GroupLockiOS/GroupLockTests/NumberOfKeysInteractorTests.swift @@ -0,0 +1,40 @@ +// +// NumberOfKeysInteractorTests.swift +// GroupLock +// +// Created by Sergej Jaskiewicz on 20.07.16. +// Copyright (c) 2016 Lanit-Tercom School. All rights reserved. +// + +import XCTest +@testable import GroupLock + +class NumberOfKeysInteractorTests: XCTestCase { + + // MARK: Subject under test + var sut: NumberOfKeysInteractor! + + // MARK: - Test lifecycle + override func setUp() { + super.setUp() + + sut = NumberOfKeysInteractor() + } + + // MARK: - Test doubles + + // MARK: - Tests + + func test_ThatNumberOfKeysInteractor_FetchesMaximumNumberOfKeysFromCrypto() { + + // Given + let expectedNumber = Crypto.maximumNumberOfKeys + + // When + let returnedNumber = sut.numberOfKeys + + // Then + XCTAssertEqual(expectedNumber, returnedNumber, + "NumberOfKeysInteractor should fetch maximum number of keys from the Crypto class") + } +} diff --git a/GroupLockiOS/GroupLockTests/NumberOfKeysViewControllerTests.swift b/GroupLockiOS/GroupLockTests/NumberOfKeysViewControllerTests.swift new file mode 100644 index 0000000..b357552 --- /dev/null +++ b/GroupLockiOS/GroupLockTests/NumberOfKeysViewControllerTests.swift @@ -0,0 +1,190 @@ +// +// NumberOfKeysViewControllerTests.swift +// GroupLock +// +// Created by Sergej Jaskiewicz on 20.07.16. +// Copyright (c) 2016 Lanit-Tercom School. All rights reserved. +// + +import XCTest +@testable import GroupLock + +class NumberOfKeysViewControllerTests: XCTestCase { + + struct Seeds { + struct PickerViewDataSource { + static let numberOfComponents = 2 + static let numberOfKeys = 42 + static let arbitraryRow = 23 + static let titleForArbitraryRow = "24" + } + + struct PickerViewDelegate { + static let min = 10 + static let max = 5 + } + } + + // MARK: Subject under test + var sut: NumberOfKeysViewController! + + var window: UIWindow! + + // MARK: - Test lifecycle + + override func setUp() { + super.setUp() + + window = UIWindow() + setupNumberOfKeysViewController() + } + + override func tearDown() { + + window = nil + super.tearDown() + } + + // MARK: - Test setup + + func setupNumberOfKeysViewController() { + + let bundle = NSBundle.mainBundle() + let storyboard = UIStoryboard(name: "Main", bundle: bundle) + sut = storyboard + .instantiateViewControllerWithIdentifier("NumberOfKeysViewController") as! NumberOfKeysViewController + loadView() + } + + func loadView() { + window.addSubview(sut.view) + NSRunLoop.currentRunLoop().runUntilDate(NSDate()) + } + + // MARK: - Test doubles + + class NumberOfKeysViewControllerOutputStub: NumberOfKeysViewControllerOutput { + var numberOfKeys = Seeds.PickerViewDataSource.numberOfKeys + var files: [ManagedFile]! + } + + class NumberOfKeysRouterSpy: NumberOfKeysRouter { + + var passDataToProvideKeyScene_called = false + + override func passDataToProvideKeyScene(segue: UIStoryboardSegue) { + passDataToProvideKeyScene_called = true + } + } + + // MARK: - Tests + + func test_ThatPickerViewDataSource_ReturnsCorrectNumberOfComponents() { + + // Given + let expectedNumberOfComponents = Seeds.PickerViewDataSource.numberOfComponents + let pickerView = sut.pickerView + + // When + let returnedNumberOfComponents = sut.numberOfComponentsInPickerView(pickerView) + + // Then + XCTAssertEqual(expectedNumberOfComponents, returnedNumberOfComponents, + "PickerView data source should provide the correct number of components") + } + + func test_ThatPickerViewDataSource_ReturnsCorrectNumberOfRows() { + + // Given + sut.output = NumberOfKeysViewControllerOutputStub() + let expectedNumberOfRows = Seeds.PickerViewDataSource.numberOfKeys + let pickerView = sut.pickerView + + // When + let returnedNumberOfRowsInComponent0 = sut.pickerView(pickerView, numberOfRowsInComponent: 0) + let returnedNumberOfRowsInComponent1 = sut.pickerView(pickerView, numberOfRowsInComponent: 1) + + // Then + XCTAssertEqual(returnedNumberOfRowsInComponent0, returnedNumberOfRowsInComponent1, + "Numbers of rows in both components should be equal") + XCTAssertEqual(expectedNumberOfRows, returnedNumberOfRowsInComponent0, + "PickerView data source should provide the correct number of components") + } + + func test_ThatPickerViewDataSource_ReturnsCorrectTitleForRow() { + + // Given + let row = Seeds.PickerViewDataSource.arbitraryRow + let expectedTitleOfRow = Seeds.PickerViewDataSource.titleForArbitraryRow + let pickerView = sut.pickerView + + // When + let returnedTitleOfRowInComponent0 = sut.pickerView(pickerView, titleForRow: row, forComponent: 0) + let returnedTitleOfRowInComponent1 = sut.pickerView(pickerView, titleForRow: row, forComponent: 1) + + // Then + XCTAssertEqual(returnedTitleOfRowInComponent0, returnedTitleOfRowInComponent1, + "Titles of the same rows in each component should be the equal") + XCTAssertEqual(expectedTitleOfRow, returnedTitleOfRowInComponent0, + "PickerView data source should provide the correct title for a row") + } + + func test_ThatPickerViewDelegate_CorrectsIfMinSetGreaterThanMax() { + + // Given + sut.output = NumberOfKeysViewControllerOutputStub() + let pickerView = sut.pickerView + + // When + sut.pickerView.selectRow(Seeds.PickerViewDelegate.max, inComponent: 1, animated: false) + sut.pickerView(pickerView, didSelectRow: Seeds.PickerViewDelegate.max, inComponent: 1) + sut.pickerView.selectRow(Seeds.PickerViewDelegate.min, inComponent: 0, animated: false) + sut.pickerView(pickerView, didSelectRow: Seeds.PickerViewDelegate.min, inComponent: 0) + + // Then + XCTAssertEqual(pickerView.selectedRowInComponent(0), pickerView.selectedRowInComponent(1), + "PickerView delegate should correct picker view's values so that MIN" + + "is never greater than MAX") + + let expectedSelectedRowInComponent1 = Seeds.PickerViewDelegate.min + XCTAssertEqual(expectedSelectedRowInComponent1, pickerView.selectedRowInComponent(1), + "If MIN is set incorrectly after MAX, MAX should be adjusted") + } + + func test_ThatPickerViewDelegate_CorrectsIfMaxSetLessThanMin() { + + // Given + sut.output = NumberOfKeysViewControllerOutputStub() + let pickerView = sut.pickerView + + // When + sut.pickerView.selectRow(Seeds.PickerViewDelegate.min, inComponent: 0, animated: false) + sut.pickerView(pickerView, didSelectRow: Seeds.PickerViewDelegate.min, inComponent: 0) + sut.pickerView.selectRow(Seeds.PickerViewDelegate.max, inComponent: 1, animated: false) + sut.pickerView(pickerView, didSelectRow: Seeds.PickerViewDelegate.max, inComponent: 1) + + // Then + XCTAssertEqual(pickerView.selectedRowInComponent(0), pickerView.selectedRowInComponent(1), + "PickerView delegate should correct picker view's values so that MIN" + + "is never greater than MAX") + + let expectedSelectedRowInComponent0 = Seeds.PickerViewDelegate.max + XCTAssertEqual(expectedSelectedRowInComponent0, pickerView.selectedRowInComponent(0), + "If MIN is set incorrectly before MAX, MIN should be adjusted") + } + + func test_ThatNumberOfKeysViewController_PassesDataToProvideKeyScene() { + + // Given + let numberOfKeysRouterSpy = NumberOfKeysRouterSpy() + sut.router = numberOfKeysRouterSpy + sut.router.viewController = sut + + // When + sut.performSegueWithIdentifier("ProvideKey", sender: nil) + + // Then + XCTAssertTrue(numberOfKeysRouterSpy.passDataToProvideKeyScene_called, + "Performing segue should trigger passing data to ProvideKey scene") + } +}