Skip to content

Commit

Permalink
Implement some FloatingTextfield unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dogo committed Aug 26, 2024
1 parent e873f34 commit 9f56cea
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// NotificationCenterProtocol.swift
// SWDestinyTrades
//
// Created by Diogo Autilio on 25/08/24.
// Copyright © 2024 Diogo Autilio. All rights reserved.
//

import Foundation

protocol NotificationCenterProtocol {

func post(_ notification: Notification)

func addObserver(_ observer: Any,
selector aSelector: Selector,
name aName: NSNotification.Name?,
object anObject: Any?)

func removeObserver(_ observer: Any)
}

extension NotificationCenter: NotificationCenterProtocol {}
65 changes: 42 additions & 23 deletions SWDestinyTrades/Classes/Base/View/FloatingTextfield.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import UIKit

final class FloatingTextfield: UITextField {

// MARK: - Properties

private let notificationCenter: NotificationCenterProtocol

var underlineWidth: CGFloat = 2.0
var underlineColor: UIColor = .black
var underlineAlphaBefore: CGFloat = 0.5
Expand All @@ -31,7 +34,8 @@ final class FloatingTextfield: UITextField {

// MARK: - Life Cycle

override init(frame: CGRect) {
init(frame: CGRect, notificationCenter: NotificationCenterProtocol = NotificationCenter.default) {
self.notificationCenter = notificationCenter
super.init(frame: frame)
setupObserver()
}
Expand Down Expand Up @@ -149,7 +153,11 @@ final class FloatingTextfield: UITextField {

@objc
func didEndChangingText() {
liftDownPlaceholderIfTextIsEmpty()
if let text, text.isEmpty {
liftDownPlaceholderIfTextIsEmpty()
} else {
liftUpPlaceholder()
}
}

// MARK: - Private
Expand Down Expand Up @@ -194,8 +202,12 @@ final class FloatingTextfield: UITextField {
// MARK: - Animations

private func animateUnderline(withAlpha alpha: CGFloat) {
UIView.animate(withDuration: animationDuration) {
self.underlineView.alpha = alpha
if animationDuration > 0 {
UIView.animate(withDuration: animationDuration) {
self.underlineView.alpha = alpha
}
} else {
underlineView.alpha = alpha
}
}

Expand All @@ -204,12 +216,19 @@ final class FloatingTextfield: UITextField {
newAlpha: CGFloat,
underlineAlpha: CGFloat,
isLiftedAfterFinishing: Bool) {
UIView.animate(withDuration: animationDuration,
animations: {
self.placeholderLabel.transform(withCoeff: scaleCoeff, andMoveCenterToPoint: newCenter)
self.placeholderLabel.alpha = newAlpha
self.underlineView.alpha = underlineAlpha
}, completion: isLiftedCompletion(withNewValue: isLiftedAfterFinishing))
if animationDuration > 0 {
UIView.animate(withDuration: animationDuration,
animations: {
self.placeholderLabel.transform(withCoeff: scaleCoeff, andMoveCenterToPoint: newCenter)
self.placeholderLabel.alpha = newAlpha
self.underlineView.alpha = underlineAlpha
}, completion: isLiftedCompletion(withNewValue: isLiftedAfterFinishing))
} else {
placeholderLabel.transform(withCoeff: scaleCoeff, andMoveCenterToPoint: newCenter)
placeholderLabel.alpha = newAlpha
underlineView.alpha = underlineAlpha
isLiftedCompletion(withNewValue: isLiftedAfterFinishing)?(true)
}
}

private func isLiftedCompletion(withNewValue value: Bool) -> ((Bool) -> Void)? {
Expand All @@ -223,24 +242,24 @@ final class FloatingTextfield: UITextField {
// MARK: - Notification

private func setupObserver() {
NotificationCenter.default.addObserver(self,
selector: #selector(didBeginChangeText),
name: UITextField.textDidBeginEditingNotification,
object: self)
NotificationCenter.default.addObserver(self,
selector: #selector(didChangeText),
name: UITextField.textDidChangeNotification,
object: self)
NotificationCenter.default.addObserver(self,
selector: #selector(didEndChangingText),
name: UITextField.textDidEndEditingNotification,
object: self)
notificationCenter.addObserver(self,
selector: #selector(didBeginChangeText),
name: UITextField.textDidBeginEditingNotification,
object: self)
notificationCenter.addObserver(self,
selector: #selector(didChangeText),
name: UITextField.textDidChangeNotification,
object: self)
notificationCenter.addObserver(self,
selector: #selector(didEndChangingText),
name: UITextField.textDidEndEditingNotification,
object: self)
}

// MARK: - deinit

deinit {
NotificationCenter.default.removeObserver(self)
notificationCenter.removeObserver(self)
}
}

Expand Down
144 changes: 144 additions & 0 deletions SWDestinyTradesTests/Base/View/FloatingTextfieldTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//
// FloatingTextfieldTests.swift
// SWDestinyTradesTests
//
// Created by Diogo Autilio on 25/08/24.
// Copyright © 2024 Diogo Autilio. All rights reserved.
//

import Foundation
import XCTest

@testable import SWDestinyTrades

final class FloatingTextfieldTests: XCTestCase {

private var sut: FloatingTextfield!
private var notificationCenter: NotificationCenterMock!

override func setUp() {
super.setUp()
notificationCenter = NotificationCenterMock()
sut = FloatingTextfield(frame: CGRect(x: 0, y: 0, width: 200, height: 50),
notificationCenter: notificationCenter)
sut.animationDuration = 0.0
}

override func tearDown() {
sut = nil
super.tearDown()
}

func testInitialState() {
sut.draw(sut.frame)
sut.drawPlaceholder(in: sut.frame)

XCTAssertEqual(sut.isLifted, false)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaBefore)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaBefore)
}

func testDrawUnderline() {
sut.draw(CGRect(x: 0, y: 0, width: 200, height: 50))

XCTAssertEqual(sut.underlineView.frame.size.height, sut.underlineWidth)
XCTAssertEqual(sut.underlineView.frame.size.width, sut.frame.size.width)
XCTAssertEqual(sut.underlineView.backgroundColor, sut.underlineColor)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaBefore)
}

func testPlaceholderLabelSetup() {
let placeholderText = "Test Placeholder"
sut.placeholder = placeholderText
sut.drawPlaceholder(in: sut.bounds)

XCTAssertEqual(sut.placeholderLabel.text, placeholderText)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaBefore)
XCTAssertEqual(sut.placeholderLabel.textColor, sut.placeholderTextColor)
}

func testLiftUpPlaceholder() {
sut.didBeginChangeText()

XCTAssertEqual(sut.isLifted, true)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaAfter, accuracy: 0.0001)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaAfter)
}

func testLiftDownPlaceholderIfTextIsEmpty() {
sut.text = ""
sut.didEndChangingText()

XCTAssertEqual(sut.isLifted, false)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaBefore)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaBefore)
}

func testLiftDownPlaceholderIfTextIsNotEmpty() {
sut.text = "Some text"
sut.didEndChangingText()

XCTAssertEqual(sut.isLifted, true)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaAfter, accuracy: 0.0001)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaAfter)
}

func testDidChangeText() {
sut.text = "Some text"
sut.didChangeText()

XCTAssertEqual(sut.isLifted, true)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaAfter, accuracy: 0.0001)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaAfter)
}

func testPlaceholderTextChangesOnTextChange() {
sut.text = ""
sut.didChangeText()

XCTAssertEqual(sut.isLifted, false)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaBefore)
}

func testPlaceholderLiftWhenEditingBegins() {
sut.text = ""
sut.didBeginChangeText()

XCTAssertEqual(sut.isLifted, true)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaAfter, accuracy: 0.0001)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaAfter)
}

func testPlaceholderFallsWhenEditingEndsAndTextIsEmpty() {
sut.text = ""
sut.didEndChangingText()

XCTAssertEqual(sut.isLifted, false)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaBefore)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaBefore)
}

func testPlaceholderRemainsLiftedWhenTextIsNotEmptyAfterEditing() {
sut.text = "Some text"
sut.didEndChangingText()

XCTAssertEqual(sut.isLifted, true)
XCTAssertEqual(sut.placeholderLabel.alpha, sut.placeholderAlphaAfter, accuracy: 0.0001)
XCTAssertEqual(sut.underlineView.alpha, sut.underlineAlphaAfter)
}

func testNotificationObservers() {
let textDidBeginEditingNotification = notificationCenter.notificationNames.contains(UITextField.textDidBeginEditingNotification)
let textDidChangeNotification = notificationCenter.notificationNames.contains(UITextField.textDidChangeNotification)
let textDidEndEditingNotification = notificationCenter.notificationNames.contains(UITextField.textDidEndEditingNotification)

XCTAssertTrue(textDidBeginEditingNotification)
XCTAssertTrue(textDidChangeNotification)
XCTAssertTrue(textDidEndEditingNotification)
}

func testDeinit() {
sut = nil
XCTAssertEqual(notificationCenter.didCallRemoveObserverCount, 1)
}
}
46 changes: 46 additions & 0 deletions SWDestinyTradesTests/Doubles/NotificationCenterMock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// NotificationCenterMock.swift
// SWDestinyTradesTests
//
// Created by Diogo Autilio on 25/08/24.
// Copyright © 2024 Diogo Autilio. All rights reserved.
//

import Foundation

@testable import SWDestinyTrades

final class NotificationCenterMock: NotificationCenterProtocol {

private(set) var notificationNames: [Notification.Name] = []

private(set) var didCallPostNotificationCount = 0
func post(_ notification: Notification) {
didCallPostNotificationCount += 1
notificationNames.append(notification.name)
NotificationCenter.default.post(notification)
}

private(set) var didCallAddObserverCount = 0
func addObserver(_ observer: Any,
selector aSelector: Selector,
name aName: NSNotification.Name?,
object anObject: Any?) {
didCallAddObserverCount += 1

if let aName {
notificationNames.append(aName)
}

NotificationCenter.default.addObserver(observer,
selector: aSelector,
name: aName,
object: anObject)
}

private(set) var didCallRemoveObserverCount = 0
func removeObserver(_ observer: Any) {
didCallRemoveObserverCount += 1
NotificationCenter.default.removeObserver(observer)
}
}

0 comments on commit 9f56cea

Please sign in to comment.