Skip to content

Commit

Permalink
add unit test; refactor view-controller initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
vermont42 committed May 3, 2019
1 parent 8cbea8e commit 747fa37
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 155 deletions.
12 changes: 8 additions & 4 deletions Conjugar.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
038E031E22734800005CFC96 /* URLProtocolStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038E031D22734800005CFC96 /* URLProtocolStub.swift */; };
038E03202273BF29005CFC96 /* RatingsFetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038E031F2273BF29005CFC96 /* RatingsFetcherTests.swift */; };
038E032222760A40005CFC96 /* UIViewExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038E032122760A40005CFC96 /* UIViewExtensionsTests.swift */; };
038E0324227617FC005CFC96 /* UIApplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038E0323227617FC005CFC96 /* UIApplicationTests.swift */; };
038E0324227617FC005CFC96 /* UIApplicationExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038E0323227617FC005CFC96 /* UIApplicationExtensionTests.swift */; };
038E03262279CCCB005CFC96 /* SettingsVCTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038E03252279CCCB005CFC96 /* SettingsVCTests.swift */; };
038E03282279D034005CFC96 /* URLSessionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038E03272279D034005CFC96 /* URLSessionExtension.swift */; };
038E032A227CD8B7005CFC96 /* UIAlertControllerExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038E0329227CD8B7005CFC96 /* UIAlertControllerExtensionTests.swift */; };
E10178021F3F753400F0BC97 /* UIViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10178011F3F753400F0BC97 /* UIViewExtensions.swift */; };
E107B08B1EB66CE6004C5E91 /* verbs.xml in Resources */ = {isa = PBXBuildFile; fileRef = E107B08A1EB66CE6004C5E91 /* verbs.xml */; };
E107B0921EB66F28004C5E91 /* VerbParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107B0911EB66F28004C5E91 /* VerbParser.swift */; };
Expand Down Expand Up @@ -162,9 +163,10 @@
038E031D22734800005CFC96 /* URLProtocolStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLProtocolStub.swift; sourceTree = "<group>"; };
038E031F2273BF29005CFC96 /* RatingsFetcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingsFetcherTests.swift; sourceTree = "<group>"; };
038E032122760A40005CFC96 /* UIViewExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewExtensionsTests.swift; sourceTree = "<group>"; };
038E0323227617FC005CFC96 /* UIApplicationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplicationTests.swift; sourceTree = "<group>"; };
038E0323227617FC005CFC96 /* UIApplicationExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplicationExtensionTests.swift; sourceTree = "<group>"; };
038E03252279CCCB005CFC96 /* SettingsVCTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsVCTests.swift; sourceTree = "<group>"; };
038E03272279D034005CFC96 /* URLSessionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionExtension.swift; sourceTree = "<group>"; };
038E0329227CD8B7005CFC96 /* UIAlertControllerExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertControllerExtensionTests.swift; sourceTree = "<group>"; };
E10178011F3F753400F0BC97 /* UIViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewExtensions.swift; sourceTree = "<group>"; };
E107B08A1EB66CE6004C5E91 /* verbs.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = verbs.xml; sourceTree = "<group>"; };
E107B0911EB66F28004C5E91 /* VerbParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerbParser.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -426,7 +428,8 @@
038E03122270A868005CFC96 /* IntExtensionTests.swift */,
038E031F2273BF29005CFC96 /* RatingsFetcherTests.swift */,
038E03142270A9FB005CFC96 /* TestGameCenterTests.swift */,
038E0323227617FC005CFC96 /* UIApplicationTests.swift */,
038E0329227CD8B7005CFC96 /* UIAlertControllerExtensionTests.swift */,
038E0323227617FC005CFC96 /* UIApplicationExtensionTests.swift */,
038E031922711B76005CFC96 /* UIViewControllerExtensionTests.swift */,
038E032122760A40005CFC96 /* UIViewExtensionsTests.swift */,
);
Expand Down Expand Up @@ -849,14 +852,15 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
038E0324227617FC005CFC96 /* UIApplicationTests.swift in Sources */,
038E0324227617FC005CFC96 /* UIApplicationExtensionTests.swift in Sources */,
038E03182270AC01005CFC96 /* DeviceUtilityTests.swift in Sources */,
E12D06A31F5E85A200CDD54E /* VerbCellTests.swift in Sources */,
038E032222760A40005CFC96 /* UIViewExtensionsTests.swift in Sources */,
038E031A22711B76005CFC96 /* UIViewControllerExtensionTests.swift in Sources */,
038E03132270A868005CFC96 /* IntExtensionTests.swift in Sources */,
E151223121A62AE9008EF307 /* ReviewPrompterTests.swift in Sources */,
E1DC939521B5836400DD4048 /* QuizTests.swift in Sources */,
038E032A227CD8B7005CFC96 /* UIAlertControllerExtensionTests.swift in Sources */,
E198F9051F5D7CB200BAF553 /* ConjugatorTests.swift in Sources */,
E1EC70F22198A10B00872787 /* UIViewControllerExtension.swift in Sources */,
E14589F41F5B7BB000EEF141 /* BrowseInfoVCTests.swift in Sources */,
Expand Down
27 changes: 10 additions & 17 deletions Conjugar/BrowseInfoVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class BrowseInfoVC: UIViewController, UITableViewDelegate, UITableViewDataSource
private var allInfos: [Info] = []
private var easyModerateInfos: [Info] = []
private var easyInfos: [Info] = []
private var settings: Settings?
private var analyticsService: AnalyticsServiceable?
private let settings: Settings
private let analyticsService: AnalyticsServiceable

private var currentInfos: [Info] {
switch browseInfoView.difficultyControl.selectedSegmentIndex {
Expand All @@ -37,10 +37,14 @@ class BrowseInfoVC: UIViewController, UITableViewDelegate, UITableViewDataSource
}
}

convenience init(settings: Settings, analyticsService: AnalyticsServiceable) {
self.init()
init(settings: Settings, analyticsService: AnalyticsServiceable) {
self.settings = settings
self.analyticsService = analyticsService
super.init(nibName: nil, bundle: nil)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func loadView() {
Expand All @@ -66,13 +70,10 @@ class BrowseInfoVC: UIViewController, UITableViewDelegate, UITableViewDataSource

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
analyticsService?.recordVisitation(viewController: "\(BrowseInfoVC.self)")
analyticsService.recordVisitation(viewController: "\(BrowseInfoVC.self)")
}

private func updateDifficultyControl() {
guard let settings = settings else {
fatalError("settings was nil.")
}
switch settings.infoDifficulty {
case .easy:
browseInfoView.difficultyControl.selectedSegmentIndex = 0
Expand Down Expand Up @@ -115,19 +116,11 @@ class BrowseInfoVC: UIViewController, UITableViewDelegate, UITableViewDataSource
}

private func showInfo() {
guard let analyticsService = analyticsService else {
fatalError("analyticsService was nil.")
}
let infoVC = InfoVC(analyticsService: analyticsService)
infoVC.infoString = currentInfos[selectedRow].infoString
infoVC.infoDelegate = self
let infoVC = InfoVC(analyticsService: analyticsService, infoString: currentInfos[selectedRow].infoString, infoDelegate: self)
navigationController?.pushViewController(infoVC, animated: true)
}

@objc func difficultyChanged(_ sender: UISegmentedControl) {
guard let settings = settings else {
fatalError("settings was nil.")
}
let index = browseInfoView.difficultyControl.selectedSegmentIndex
if index == 0 {
settings.infoDifficulty = .easy
Expand Down
27 changes: 12 additions & 15 deletions Conjugar/BrowseVerbsVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class BrowseVerbsVC: UIViewController, UITableViewDelegate, UITableViewDataSourc
private var allVerbs: [String] = []
private var regularVerbs: [String] = []
private var irregularVerbs: [String] = []
private var settings: Settings?
private var analyticsService: AnalyticsServiceable?
private var reviewPrompter: ReviewPromptable?
private let settings: Settings
private let analyticsService: AnalyticsServiceable
private let reviewPrompter: ReviewPromptable

private var currentVerbs: [String] {
switch browseVerbsView.filterControl.selectedSegmentIndex {
Expand All @@ -37,11 +37,15 @@ class BrowseVerbsVC: UIViewController, UITableViewDelegate, UITableViewDataSourc
}
}

convenience init(settings: Settings, analyticsService: AnalyticsServiceable, reviewPrompter: ReviewPromptable) {
self.init()
init(settings: Settings, analyticsService: AnalyticsServiceable, reviewPrompter: ReviewPromptable) {
self.settings = settings
self.analyticsService = analyticsService
self.reviewPrompter = reviewPrompter
super.init(nibName: nil, bundle: nil)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func loadView() {
Expand All @@ -53,13 +57,13 @@ class BrowseVerbsVC: UIViewController, UITableViewDelegate, UITableViewDataSourc
irregularVerbs = Conjugator.shared.irregularVerbsArray()
navigationItem.titleView = UILabel.titleLabel(title: "Browse")
view = browseVerbsView
reviewPrompter?.promptableActionHappened()
reviewPrompter.promptableActionHappened()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
browseVerbsView.isHidden = false
analyticsService?.recordVisitation(viewController: "\(BrowseVerbsVC.self)")
analyticsService.recordVisitation(viewController: "\(BrowseVerbsVC.self)")
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
Expand All @@ -75,15 +79,8 @@ class BrowseVerbsVC: UIViewController, UITableViewDelegate, UITableViewDataSourc
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let settings = settings else {
fatalError("settings was nil.")
}
guard let analyticsService = analyticsService else {
fatalError("analyticsService was nil.")
}
tableView.deselectRow(at: indexPath, animated: false)
let verbVC = VerbVC(settings: settings, analyticsService: analyticsService)
verbVC.verb = currentVerbs[indexPath.row]
let verbVC = VerbVC(verb: currentVerbs[indexPath.row], settings: settings, analyticsService: analyticsService)
browseVerbsView.isHidden = true
navigationController?.pushViewController(verbVC, animated: true)
}
Expand Down
21 changes: 12 additions & 9 deletions Conjugar/InfoVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import UIKit

class InfoVC: UIViewController, UITextViewDelegate {
weak var infoDelegate: InfoDelegate?
var infoString: NSAttributedString?
private var analyticsService: AnalyticsServiceable?
private weak var infoDelegate: InfoDelegate?
private let infoString: NSAttributedString
private let analyticsService: AnalyticsServiceable

var infoView: InfoView {
if let castedView = view as? InfoView {
Expand All @@ -21,17 +21,20 @@ class InfoVC: UIViewController, UITextViewDelegate {
}
}

convenience init(analyticsService: AnalyticsServiceable) {
self.init()
init(analyticsService: AnalyticsServiceable, infoString: NSAttributedString, infoDelegate: InfoDelegate) {
self.analyticsService = analyticsService
self.infoString = infoString
self.infoDelegate = infoDelegate
super.init(nibName: nil, bundle: nil)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func loadView() {
let infoView: InfoView
infoView = InfoView(frame: UIScreen.main.bounds)
guard let infoString = infoString else {
fatalError("InfoVC's infoString property is nil.")
}
infoView.info.attributedText = infoString
infoView.info.delegate = self
infoView.info.contentOffset = CGPoint.zero
Expand All @@ -40,7 +43,7 @@ class InfoVC: UIViewController, UITextViewDelegate {

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
analyticsService?.recordVisitation(viewController: "\(InfoVC.self)")
analyticsService.recordVisitation(viewController: "\(InfoVC.self)")
}

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
Expand Down
57 changes: 14 additions & 43 deletions Conjugar/QuizVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
import UIKit

class QuizVC: UIViewController, UITextFieldDelegate, QuizDelegate {
private var settings: Settings?
private var quiz: Quiz?
private var analyticsService: AnalyticsServiceable?
private var gameCenter: GameCenterable?
private let settings: Settings
private let quiz: Quiz
private let analyticsService: AnalyticsServiceable
private let gameCenter: GameCenterable

var quizView: QuizView {
if let castedView = view as? QuizView {
Expand All @@ -22,12 +22,16 @@ class QuizVC: UIViewController, UITextFieldDelegate, QuizDelegate {
}
}

convenience init(settings: Settings, quiz: Quiz, analyticsService: AnalyticsServiceable, gameCenter: GameCenterable) {
self.init()
init(settings: Settings, quiz: Quiz, analyticsService: AnalyticsServiceable, gameCenter: GameCenterable) {
self.settings = settings
self.quiz = quiz
self.analyticsService = analyticsService
self.gameCenter = gameCenter
super.init(nibName: nil, bundle: nil)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func loadView() {
Expand All @@ -41,9 +45,6 @@ class QuizVC: UIViewController, UITextFieldDelegate, QuizDelegate {

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let quiz = quiz else {
fatalError("quiz was nil.")
}
quiz.delegate = self
switch quiz.quizState {
case .notStarted, .finished:
Expand All @@ -68,19 +69,10 @@ class QuizVC: UIViewController, UITextFieldDelegate, QuizDelegate {
}
quizView.startRestartButton.pulsate()
authenticate()
analyticsService?.recordVisitation(viewController: "\(QuizVC.self)")
analyticsService.recordVisitation(viewController: "\(QuizVC.self)")
}

private func authenticate() {
guard let settings = settings else {
fatalError("settings was nil.")
}
guard let analyticsService = analyticsService else {
fatalError("analyticsService was nil.")
}
guard let gameCenter = gameCenter else {
fatalError("gameCenter was nil.")
}
if !gameCenter.isAuthenticated && settings.userRejectedGameCenter {
if !settings.didShowGameCenterDialog {
showGameCenterDialog()
Expand All @@ -91,33 +83,21 @@ class QuizVC: UIViewController, UITextFieldDelegate, QuizDelegate {
}

private func showGameCenterDialog() {
guard let settings = settings else {
fatalError("settings was nil.")
}
guard let analyticsService = analyticsService else {
fatalError("analyticsService was nil.")
}
guard let gameCenter = gameCenter else {
fatalError("gameCenter was nil.")
}
settings.didShowGameCenterDialog = true
let gameCenterController = UIAlertController(title: "Game Center", message: "Would you like Conjugar to upload your future scores to Game Center after your quiz? See how you stack up against the global community of conjugators.", preferredStyle: UIAlertController.Style.alert)
let noAction = UIAlertAction(title: "No", style: UIAlertAction.Style.destructive) { _ in
SoundPlayer.play(.sadTrombone)
settings.userRejectedGameCenter = true
self.settings.userRejectedGameCenter = true
}
gameCenterController.addAction(noAction)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertAction.Style.default) { _ in
gameCenter.authenticate(analyticsService: analyticsService, completion: nil)
self.gameCenter.authenticate(analyticsService: self.analyticsService, completion: nil)
}
gameCenterController.addAction(yesAction)
present(gameCenterController, animated: true, completion: nil)
}

@objc func startRestart() {
guard let quiz = quiz else {
fatalError("quiz was nil.")
}
SoundPlayer.play(.gun)
quiz.start()
quizView.startRestartButton.setTitle("Restart", for: .normal)
Expand All @@ -127,7 +107,7 @@ class QuizVC: UIViewController, UITextFieldDelegate, QuizDelegate {
quizView.showInProgressUI()
quizView.startRestartButton.pulsate()
quizView.conjugationField.becomeFirstResponder()
analyticsService?.recordQuizStart()
analyticsService.recordQuizStart()
}

func scoreDidChange(newScore: Int) {
Expand Down Expand Up @@ -157,12 +137,6 @@ class QuizVC: UIViewController, UITextFieldDelegate, QuizDelegate {
}

func quizDidFinish() {
guard let analyticsService = analyticsService else {
fatalError("analyticsService was nil.")
}
guard let quiz = quiz else {
fatalError("quiz was nil.")
}
quizView.hideInProgressUI()
quizView.startRestartButton.setTitle("Start", for: .normal)
let applauseIndex = Int.random(in: 1...Sound.applauseCount)
Expand All @@ -182,9 +156,6 @@ class QuizVC: UIViewController, UITextFieldDelegate, QuizDelegate {
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
guard let quiz = quiz else {
fatalError("quiz was nil.")
}
guard let text = quizView.conjugationField.text else { return false }
guard text != "" else { return false }
quizView.conjugationField.resignFirstResponder()
Expand Down
Loading

0 comments on commit 747fa37

Please sign in to comment.