From eafc3c62386112dd490daf3f9361dcd1f147c993 Mon Sep 17 00:00:00 2001 From: Diogo Autilio Date: Sat, 23 Mar 2024 07:57:52 -0300 Subject: [PATCH] Migrate UserCollectionViewController to VIP --- .../UserCollectionViewController.swift | 127 ++++-------------- .../UserCollectionViewControllerFactory.swift | 8 +- .../Protocols/UserCollectionViewType.swift | 2 - .../UserCollectionViewControllerTests.swift | 53 +++++--- .../Doubles/UserCollectionPresenterSpy.swift | 29 +++- 5 files changed, 96 insertions(+), 123 deletions(-) diff --git a/SWDestinyTrades/Classes/UserCollection/Controller/UserCollectionViewController.swift b/SWDestinyTrades/Classes/UserCollection/Controller/UserCollectionViewController.swift index 35ed8abd..03143f4c 100644 --- a/SWDestinyTrades/Classes/UserCollection/Controller/UserCollectionViewController.swift +++ b/SWDestinyTrades/Classes/UserCollection/Controller/UserCollectionViewController.swift @@ -6,23 +6,20 @@ // Copyright © 2017 Diogo Autilio. All rights reserved. // -import FTPopOverMenu +import Foundation import UIKit final class UserCollectionViewController: UIViewController { - private var currentSortIndex = 0 private let userCollectionView: UserCollectionViewType - private lazy var navigator = UserCollectionNavigator(self) - private let database: DatabaseProtocol? + + var presenter: UserCollectionPresenterProtocol? // MARK: - Life Cycle - init(with view: UserCollectionViewType = UserCollectionTableView(), database: DatabaseProtocol?) { + init(with view: UserCollectionViewType = UserCollectionTableView()) { userCollectionView = view - self.database = database super.init(nibName: nil, bundle: nil) - userCollectionView.userCollectionDelegate = self } @available(*, unavailable) @@ -37,122 +34,44 @@ final class UserCollectionViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - setupNavigationItem() + presenter?.setupNavigationItems { leftItems, rightItems in + navigationItem.rightBarButtonItems = leftItems + navigationItem.leftBarButtonItems = rightItems + } userCollectionView.didSelectCard = { [weak self] list, card in - self?.navigateToCardDetailViewController(cardList: list, card: card) + self?.presenter?.navigateToCardDetail(cardList: list, card: card) } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - navigationItem.title = L10n.myCollection - - loadDataFromRealm() - } - - // MARK: - Private - - private func setupNavigationItem() { - let shareBarItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(share(_:))) - let addCardBarItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(navigateToAddCardViewController)) - navigationItem.rightBarButtonItems = [addCardBarItem, shareBarItem] - navigationItem.leftBarButtonItem = UIBarButtonItem(image: Asset.NavigationBar.icSort.image, style: .plain, target: self, action: #selector(sort(_:event:))) - } + presenter?.setNavigationTitle() - private func createDatabase(object: UserCollectionDTO) { - try? database?.save(object: object) + presenter?.loadDataFromRealm() } +} - private func loadDataFromRealm() { - let user = getUserCollection() - userCollectionView.updateTableViewData(collection: user) - userCollectionView.sort(currentSortIndex) - } - - private func popOverMenuConfiguration() -> FTConfiguration { - let config = FTConfiguration() - config.backgoundTintColor = ColorPalette.appTheme - config.borderColor = ColorPalette.appTheme - config.menuSeparatorColor = .lightGray - config.textColor = .white - config.textAlignment = .center - return config - } - - private func getUserCollection() -> UserCollectionDTO { - var user = UserCollectionDTO() - try? database?.fetch(UserCollectionDTO.self, predicate: nil, sorted: nil) { [weak self] results in - if let userCollection = results.first { - user = userCollection - } else { - self?.createDatabase(object: user) - } - } - return user - } - - // MARK: - Navigation - - private func navigateToCardDetailViewController(cardList: [CardDTO], card: CardDTO) { - navigator.navigate(to: .cardDetail(database: database, with: cardList, card: card)) - } +extension UserCollectionViewController: UserCollectionViewControllerProtocol { - @objc - private func navigateToAddCardViewController() { - navigator.navigate(to: .addCard(database: database, with: getUserCollection())) + func setNavigationTitle(_ title: String) { + navigationItem.title = title } - @objc - private func share(_ sender: UIBarButtonItem) { - var collectionList = "" - - if let cardList = userCollectionView.getCardList() { - for card in cardList { - collectionList.append(String(format: "%d %@\n", card.quantity, card.name)) - } - } - - let activityVC = UIActivityViewController(activityItems: [SwdShareProvider(subject: L10n.myCollection, text: collectionList), L10n.shareText], applicationActivities: nil) - activityVC.excludedActivityTypes = [.saveToCameraRoll, - .postToFlickr, - .postToVimeo, - .assignToContact, - .addToReadingList, - .postToFacebook] - - activityVC.popoverPresentationController?.barButtonItem = sender - DispatchQueue.global(qos: .userInteractive).async { - DispatchQueue.main.async { - self.present(activityVC, animated: true, completion: nil) - } - } + func updateTableViewData(collection: UserCollectionDTO) { + userCollectionView.updateTableViewData(collection: collection) } - @objc - private func sort(_ sender: UIBarButtonItem, event: UIEvent) { - FTPopOverMenu.showForEvent(event: event, - with: [L10n.aToZ, L10n.cardNumber, L10n.color], - config: popOverMenuConfiguration(), - done: { [weak self] selectedIndex in - self?.userCollectionView.sort(selectedIndex) - self?.currentSortIndex = selectedIndex - }, cancel: {}) + func sort(_ selectedIndex: Int) { + userCollectionView.sort(selectedIndex) } -} -extension UserCollectionViewController: UserCollectionProtocol { - - func stepperValueChanged(newValue: Int, card: CardDTO) { - try? database?.update { - card.quantity = newValue - } + func getCardList() -> [CardDTO]? { + userCollectionView.getCardList() } - func remove(at index: Int) { - try? database?.update { [weak self] in - self?.getUserCollection().myCollection.remove(at: index) - } + func presentViewController(_ controller: UIViewController, animated: Bool) { + present(controller, animated: animated, completion: nil) } } diff --git a/SWDestinyTrades/Classes/UserCollection/Factory/UserCollectionViewControllerFactory.swift b/SWDestinyTrades/Classes/UserCollection/Factory/UserCollectionViewControllerFactory.swift index 6c9c8fd4..6a06167b 100644 --- a/SWDestinyTrades/Classes/UserCollection/Factory/UserCollectionViewControllerFactory.swift +++ b/SWDestinyTrades/Classes/UserCollection/Factory/UserCollectionViewControllerFactory.swift @@ -19,7 +19,13 @@ final class UserCollectionViewControllerFactory: ViewControllerFactory { func createViewController() -> UIViewController { let view = UserCollectionTableView() - let viewController = UserCollectionViewController(with: view, database: database) + let viewController = UserCollectionViewController(with: view) + let router = UserCollectionNavigator(viewController) + let presenter = UserCollectionPresenter(controller: viewController, + database: database, + navigator: router) + viewController.presenter = presenter + view.userCollectionDelegate = presenter return viewController } } diff --git a/SWDestinyTrades/Classes/UserCollection/Protocols/UserCollectionViewType.swift b/SWDestinyTrades/Classes/UserCollection/Protocols/UserCollectionViewType.swift index 7259cbbf..072ad687 100644 --- a/SWDestinyTrades/Classes/UserCollection/Protocols/UserCollectionViewType.swift +++ b/SWDestinyTrades/Classes/UserCollection/Protocols/UserCollectionViewType.swift @@ -13,8 +13,6 @@ protocol UserCollectionViewType where Self: UITableView { var didSelectCard: (([CardDTO], CardDTO) -> Void)? { get set } - var userCollectionDelegate: UserCollectionProtocol? { get set } - func updateTableViewData(collection: UserCollectionDTO) func sort(_ selectedIndex: Int) func getCardList() -> [CardDTO]? diff --git a/SWDestinyTradesTests/Screens/UserCollection/Controller/UserCollectionViewControllerTests.swift b/SWDestinyTradesTests/Screens/UserCollection/Controller/UserCollectionViewControllerTests.swift index a9d4467b..ed3caa22 100644 --- a/SWDestinyTradesTests/Screens/UserCollection/Controller/UserCollectionViewControllerTests.swift +++ b/SWDestinyTradesTests/Screens/UserCollection/Controller/UserCollectionViewControllerTests.swift @@ -14,22 +14,25 @@ import XCTest final class UserCollectionViewControllerTests: XCTestCase { private var sut: UserCollectionViewController! + private var presenter: UserCollectionPresenterSpy! private var view: UserCollectionViewSpy! - private var database: RealmDatabase? private var navigationController: UINavigationControllerMock! private var keyWindow: UIWindow! override func setUp() { super.setUp() keyWindow = UIWindow(frame: .testDevice) - database = RealmDatabaseHelper.createMemoryDatabase(identifier: #function) view = UserCollectionViewSpy() - sut = UserCollectionViewController(with: view, database: database) + presenter = UserCollectionPresenterSpy() + sut = UserCollectionViewController(with: view) + sut.presenter = presenter navigationController = UINavigationControllerMock(rootViewController: sut) keyWindow.showTestWindow(controller: navigationController) } override func tearDown() { + view = nil + presenter = nil navigationController = nil sut = nil keyWindow.cleanTestWindow() @@ -45,35 +48,55 @@ final class UserCollectionViewControllerTests: XCTestCase { func test_viewDidLoad() { sut.viewDidLoad() - XCTAssertEqual(sut.navigationItem.rightBarButtonItems?.count, 2) - XCTAssertNotNil(sut.navigationItem.leftBarButtonItem) + XCTAssertEqual(presenter.didCallSetupNavigationItemsCount, 1) } func test_didSelectCard() { sut.viewDidLoad() view.didSelectCard?([.stub()], .stub()) - XCTAssertTrue(navigationController.currentPushedViewController is CardDetailViewController) + XCTAssertEqual(presenter.didCallNavigateToCardDetail.count, 1) } func test_viewWillAppear() { sut.viewWillAppear(false) - XCTAssertEqual(sut.navigationItem.title, "My Collection") + XCTAssertEqual(presenter.didCallSetNavigationTitleCount, 1) + XCTAssertEqual(presenter.didCallLoadDataFromRealmCount, 1) } - func test_stepperValueChanged() { - let card: CardDTO = .stub() - sut.stepperValueChanged(newValue: 4, card: card) + func test_setNavigationTitle() { + sut.setNavigationTitle("Collection Title") - XCTAssertEqual(card.quantity, 4) + XCTAssertEqual(sut.navigationItem.title, "Collection Title") } - func test_remove() { - // XCTAssertEqual(person.borrowed.count, 2) + func test_updateTableViewData() { + let collection = UserCollectionDTO.stub() + sut.updateTableViewData(collection: collection) - sut.remove(at: 0) + XCTAssertEqual(view.didCallUpdateTableViewData.count, 1) + XCTAssertEqual(view.didCallUpdateTableViewData[0], collection) + } + + func test_sort() { + sut.sort(0) + + XCTAssertEqual(view.didCallSort.count, 1) + XCTAssertEqual(view.didCallSort[0], 0) + } + + func test_getCardList() { + _ = sut.getCardList() + + XCTAssertEqual(view.didCallGetCardListCount, 1) + } + + func test_presentViewController() { + let controller = UIViewControllerMock() + + sut.presentViewController(controller, animated: false) - // XCTAssertEqual(person.borrowed.count, 1) + XCTAssertTrue(controller.isBeingPresented) } } diff --git a/SWDestinyTradesTests/Screens/UserCollection/Doubles/UserCollectionPresenterSpy.swift b/SWDestinyTradesTests/Screens/UserCollection/Doubles/UserCollectionPresenterSpy.swift index ee65592d..380c5660 100644 --- a/SWDestinyTradesTests/Screens/UserCollection/Doubles/UserCollectionPresenterSpy.swift +++ b/SWDestinyTradesTests/Screens/UserCollection/Doubles/UserCollectionPresenterSpy.swift @@ -7,10 +7,37 @@ // import Foundation +import UIKit @testable import SWDestinyTrades -final class UserCollectionPresenterSpy: UserCollectionProtocol { +final class UserCollectionPresenterSpy: UserCollectionPresenterProtocol, UserCollectionProtocol { + + private(set) var didCallSetNavigationTitleCount = 0 + func setNavigationTitle() { + didCallSetNavigationTitleCount += 1 + } + + private(set) var didCallSetupNavigationItemsCount = 0 + func setupNavigationItems(completion: ([UIBarButtonItem]?, [UIBarButtonItem]?) -> Void) { + didCallSetupNavigationItemsCount += 1 + completion([], []) + } + + private(set) var didCallLoadDataFromRealmCount = 0 + func loadDataFromRealm() { + didCallLoadDataFromRealmCount += 1 + } + + private(set) var didCallNavigateToCardDetail = [(cardList: [CardDTO], card: CardDTO)]() + func navigateToCardDetail(cardList: [CardDTO], card: CardDTO) { + didCallNavigateToCardDetail.append((cardList, card)) + } + + private(set) var didCallNavigateToAddCardCount = 0 + func navigateToAddCard() { + didCallNavigateToAddCardCount += 1 + } private(set) var didCallStepperValueChanged = [(newValue: Int, card: CardDTO)]() func stepperValueChanged(newValue: Int, card: CardDTO) {