Skip to content

Commit

Permalink
Migrate PeopleListViewController to VIP
Browse files Browse the repository at this point in the history
  • Loading branch information
dogo committed Mar 6, 2024
1 parent 91fcd7f commit 76f9ca0
Show file tree
Hide file tree
Showing 16 changed files with 201 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@ protocol UpdateTableDataDelegate: AnyObject {
func insertNew(person: PersonDTO)
}

final class PeopleListViewController: UIViewController, UpdateTableDataDelegate {
final class PeopleListViewController: UIViewController {

private lazy var peopleListView: PeopleListViewType = PeopleListTableView()
private lazy var navigator = PeopleListNavigator(self)
private let database: DatabaseProtocol?
private let peopleListView: PeopleListViewType

var presenter: PeopleListPresenterProtocol?

// MARK: - Life Cycle

init(database: DatabaseProtocol?) {
self.database = database
init(with view: PeopleListViewType) {
peopleListView = view
super.init(nibName: nil, bundle: nil)
peopleListView.peopleListDelegate = self
}

@available(*, unavailable)
Expand All @@ -38,84 +37,43 @@ final class PeopleListViewController: UIViewController, UpdateTableDataDelegate
override func viewDidLoad() {
super.viewDidLoad()

setupNavigationItem()

loadDataFromRealm()
presenter?.setupNavigationItems { [weak self] items in
self?.navigationItem.leftBarButtonItem = items?.first
self?.navigationItem.rightBarButtonItem = items?.last
}

NotificationCenter.default.addObserver(self, selector: #selector(reloadTableView), name: NotificationKey.reloadTableViewNotification, object: nil)
presenter?.loadDataFromRealm()

peopleListView.didSelectPerson = { [weak self] person in
self?.navigateToLoansDetailViewController(person: person)
self?.presenter?.navigateToLoansDetail(person: person)
}
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

navigationItem.title = L10n.people
presenter?.setNavigationTitle()
peopleListView.reloadData()
}
}

// MARK: - Private

func setupNavigationItem() {
navigationItem.leftBarButtonItem = UIBarButtonItem(title: L10n.edit, style: .plain, target: self, action: #selector(editButtonTouched(_:)))
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(navigateToNextController(_:)))
}
extension PeopleListViewController: PeopleListViewControllerProtocol {

func loadDataFromRealm() {
try? database?.fetch(PersonDTO.self, predicate: nil, sorted: nil) { [weak self] persons in
self?.peopleListView.updateTableViewData(persons)
}
func updateTableViewData(_ peopleList: [PersonDTO]) {
peopleListView.updateTableViewData(peopleList)
}

@objc
private func reloadTableView(_ notification: NSNotification) {
loadDataFromRealm()
func setNavigationTitle(_ title: String) {
navigationItem.title = title
}

// MARK: - <UpdateTableDataDelegate>

func insertNew(person: PersonDTO) {
peopleListView.insert(person)
}

// MARK: - UIBarButton Actions

@objc
func editButtonTouched(_ sender: Any) {
toggleTableViewEditable(editable: isEditing)
}

// MARK: - Helper

private func toggleTableViewEditable(editable: Bool) {
func toggleTableViewEditable(editable: Bool, title: String) {
super.setEditing(!editable, animated: true)
peopleListView.toggleTableViewEditable(editable: editable)
navigationItem.leftBarButtonItem?.title = !editable ? L10n.done : L10n.edit
}

// MARK: - Navigation

@objc
func navigateToNextController(_ sender: Any) {
if isEditing {
toggleTableViewEditable(editable: isEditing)
}
navigator.navigate(to: .newPerson(with: self))
navigationItem.leftBarButtonItem?.title = title
}

func navigateToLoansDetailViewController(person: PersonDTO) {
navigator.navigate(to: .loanDetail(database: database, with: person))
}
}

extension PeopleListViewController: PeopleListProtocol {
func remove(person: PersonDTO) {
try? database?.delete(object: person)
}

func insert(person: PersonDTO) {
try? database?.save(object: person)
func insert(_ person: PersonDTO) {
peopleListView.insert(person)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// PeopleListViewControllerFactory.swift
// SWDestinyTrades
//
// Created by Diogo Autilio on 04/03/24.
// Copyright © 2024 Diogo Autilio. All rights reserved.
//

import Foundation
import UIKit

final class PeopleListViewControllerFactory: ViewControllerFactory {

private let database: DatabaseProtocol?

init(database: DatabaseProtocol?) {
self.database = database
}

func createViewController() -> UIViewController {
let view = PeopleListTableView()
let viewController = PeopleListViewController(with: view)
let router = PeopleListNavigator(viewController)
let presenter = PeopleListPresenter(controller: viewController,
database: database,
navigator: router)
viewController.presenter = presenter
view.peopleListDelegate = presenter
return viewController
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,11 @@ final class PeopleListPresenter: PeopleListPresenterProtocol {
private let navigator: PeopleListNavigator

private weak var controller: PeopleListViewControllerProtocol?
private weak var delegate: UpdateTableDataDelegate?

init(controller: PeopleListViewControllerProtocol?,
delegate: UpdateTableDataDelegate?,
database: DatabaseProtocol?,
navigator: PeopleListNavigator) {
self.controller = controller
self.delegate = delegate
self.database = database
self.navigator = navigator

Expand Down Expand Up @@ -73,7 +70,7 @@ final class PeopleListPresenter: PeopleListPresenterProtocol {
if isEditing {
toggleTableViewEditable(editable: isEditing)
}
navigator.navigate(to: .newPerson(with: delegate))
navigator.navigate(to: .newPerson(with: self))
}

// MARK: - Helper
Expand All @@ -99,3 +96,10 @@ extension PeopleListPresenter: PeopleListProtocol {
try? database?.save(object: person)
}
}

extension PeopleListPresenter: UpdateTableDataDelegate {

func insertNew(person: PersonDTO) {
controller?.insert(person)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ protocol PeopleListViewControllerProtocol where Self: UIViewController {
func updateTableViewData(_ peopleList: [PersonDTO])
func setNavigationTitle(_ title: String)
func toggleTableViewEditable(editable: Bool, title: String)
func insert(_ person: PersonDTO)
}
5 changes: 5 additions & 0 deletions SWDestinyTrades/Classes/TabBar/SWDTabBarFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ final class SWDTabBarFactory {
let factory = DeckListViewControllerFactory(database: database)
return factory.createViewController()
}

func makePeopleList(with database: DatabaseProtocol?) -> UIViewController {
let factory = PeopleListViewControllerFactory(database: database)
return factory.createViewController()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ final class SWDTabBarViewController: UITabBarController {
decktab.tabBarItem = UITabBarItem(title: L10n.decks, image: Asset.Tabbar.icDecks.image, selectedImage: nil)

// Create PeopleListViewController Tab
let loansTab = UINavigationController(rootViewController: PeopleListViewController(database: database))
let loansTab = UINavigationController(rootViewController: factory.makePeopleList(with: database))
loansTab.tabBarItem = UITabBarItem(title: L10n.loans, image: Asset.Tabbar.icLoans.image, selectedImage: nil)

// Create UserCollectionViewController Tab
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -11,79 +11,106 @@ import XCTest

@testable import SWDestinyTrades

final class PeopleListViewControllerTests: XCSnapshotableTestCase {
final class PeopleListViewControllerTests: XCTestCase {

private var sut: PeopleListViewController!
private var presenter: PeopleListPresenterSpy!
private var view: PeopleListViewSpy!
private var database: DatabaseProtocol!
private var navigation: UINavigationController!
private var window: UIWindow!
private var navigationController: UINavigationControllerMock!
private var keyWindow: UIWindow!

override func setUp() {
super.setUp()
AppearanceProxyHelper.customizeNavigationBar()
window = UIWindow(frame: .testDevice)
database = RealmDatabaseHelper.createMemoryDatabase(identifier: "PeopleList")
keyWindow = UIWindow(frame: .testDevice)
view = PeopleListViewSpy()
presenter = PeopleListPresenterSpy()
sut = PeopleListViewController(with: view)
sut.presenter = presenter
database = RealmDatabaseHelper.createMemoryDatabase(identifier: #function)
navigationController = UINavigationControllerMock(rootViewController: sut)
keyWindow.showTestWindow(controller: navigationController)
}

override func tearDown() {
try! database.reset()
window.cleanTestWindow()
sut = nil
database = nil
view = nil
navigationController = nil
keyWindow = nil
super.tearDown()
}

func testEmptyStateLayout() {
sut = PeopleListViewController(database: database)
navigation = UINavigationController(rootViewController: sut)
window.showTestWindow(controller: navigation)
func test_loadView() {
sut.loadView()

XCTAssertTrue(snapshot(navigation, named: "PeopleListViewController with an empty state layout"))
XCTAssertTrue(sut.view is PeopleListViewType)
}

func testPersonWithNoLoansLayout() {
let person = PersonDTO.stub()
try! database.save(object: person)
func test_viewDidLoad() {
sut.viewDidLoad()

sut = PeopleListViewController(database: database)
navigation = UINavigationController(rootViewController: sut)
window.showTestWindow(controller: navigation)
XCTAssertEqual(presenter.didCallSetupNavigationItemsCount, 1)
XCTAssertEqual(presenter.didCallLoadDataFromRealmCount, 1)
}

func test_didSelectPerson() {
sut.viewDidLoad()
view.didSelectPerson?(.stub())

XCTAssertTrue(snapshot(navigation, named: "PeopleListViewController with a person with no loans"))
XCTAssertEqual(presenter.didCallNavigateToLoansDetailValues.count, 1)
XCTAssertNotNil(presenter.didCallNavigateToLoansDetailValues[0])
}

func testPersonWithLentCardsLayout() {
let person = PersonDTO.stub()
person.lentMe.append(CardDTO.stub())
try! database.save(object: person)
func test_viewWillAppear() {
sut.viewWillAppear(false)

XCTAssertEqual(presenter.didCallSetNavigationTitleCount, 1)
}

sut = PeopleListViewController(database: database)
navigation = UINavigationController(rootViewController: sut)
window.showTestWindow(controller: navigation)
func test_updateTableViewData() {
sut.updateTableViewData([.stub()])

XCTAssertTrue(snapshot(navigation, named: "PeopleListViewController with a person with lent cards"))
XCTAssertEqual(view.didCallUpdateTableViewDataValues.count, 1)
XCTAssertNotNil(view.didCallUpdateTableViewDataValues[0])
}

func testPersonWithBorrowedCardsLayout() {
let person = PersonDTO.stub()
person.borrowed.append(CardDTO.stub())
try! database.save(object: person)
func test_setNavigationTitle() {
sut.setNavigationTitle("Darth Vader")

sut = PeopleListViewController(database: database)
navigation = UINavigationController(rootViewController: sut)
window.showTestWindow(controller: navigation)
XCTAssertEqual(sut.navigationItem.title, "Darth Vader")
}

XCTAssertTrue(snapshot(navigation, named: "PeopleListViewController with a person with borrowed cards"))
func test_toggleTableViewEditable_true() {
sut.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Test",
style: .plain,
target: nil,
action: nil)
sut.toggleTableViewEditable(editable: true, title: "Edit")

XCTAssertFalse(sut.isEditing)
XCTAssertEqual(view.didICallToggleTableViewEditableValues.count, 1)
XCTAssertTrue(view.didICallToggleTableViewEditableValues[0])
XCTAssertEqual(sut.navigationItem.leftBarButtonItem?.title, "Edit")
}

func testPersonWithLentAndBorrowedCardsLayout() {
let person = PersonDTO.stub()
person.lentMe.append(CardDTO.stub())
person.borrowed.append(CardDTO.stub())
try! database.save(object: person)
func test_toggleTableViewEditable_false() {
sut.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Test",
style: .plain,
target: nil,
action: nil)
sut.toggleTableViewEditable(editable: false, title: "Done")

XCTAssertTrue(sut.isEditing)
XCTAssertEqual(view.didICallToggleTableViewEditableValues.count, 1)
XCTAssertFalse(view.didICallToggleTableViewEditableValues[0])
XCTAssertEqual(sut.navigationItem.leftBarButtonItem?.title, "Done")
}

sut = PeopleListViewController(database: database)
navigation = UINavigationController(rootViewController: sut)
window.showTestWindow(controller: navigation)
func test_insert() {
sut.insert(.stub())

XCTAssertTrue(snapshot(navigation, named: "PeopleListViewController with a person with lent and borrowed cards"))
XCTAssertEqual(view.didICallnsertValues.count, 1)
XCTAssertNotNil(view.didICallnsertValues[0])
}
}
Loading

0 comments on commit 76f9ca0

Please sign in to comment.