Skip to content

Commit

Permalink
chore Adding tests (#1470)
Browse files Browse the repository at this point in the history
## Added tests
- Drop-in reloading (partial payment)
- Partial payment encoding/decoding
  • Loading branch information
goergisn authored Nov 29, 2023
2 parents 4bbce20 + 09cd403 commit 86fb191
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 28 deletions.
6 changes: 5 additions & 1 deletion Adyen.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
81825CC52AC59C6C00F91912 /* XCTestCase+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81825CC32AC59C6C00F91912 /* XCTestCase+Wait.swift */; };
81896E852A4DB5F300C532CA /* SearchViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81896E842A4DB5F300C532CA /* SearchViewControllerTests.swift */; };
8191838E2A53062F008EB61A /* FormAddressItem+Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8191838D2A53062F008EB61A /* FormAddressItem+Configuration.swift */; };
819CC3342B14C53200D2EEE9 /* PaymentMethods+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 819CC3332B14C53200D2EEE9 /* PaymentMethods+Equatable.swift */; };
81A2E3BE2A5C453200CF5F9C /* LinkTextViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A2E3BD2A5C453200CF5F9C /* LinkTextViewTests.swift */; };
81A48DBB2A5709F600242341 /* DemoAddressLookupProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A48DBA2A5709F600242341 /* DemoAddressLookupProvider.swift */; };
81A48DBC2A5709F600242341 /* DemoAddressLookupProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A48DBA2A5709F600242341 /* DemoAddressLookupProvider.swift */; };
Expand Down Expand Up @@ -1368,6 +1369,7 @@
81825CC32AC59C6C00F91912 /* XCTestCase+Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Wait.swift"; sourceTree = "<group>"; };
81896E842A4DB5F300C532CA /* SearchViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewControllerTests.swift; sourceTree = "<group>"; };
8191838D2A53062F008EB61A /* FormAddressItem+Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FormAddressItem+Configuration.swift"; sourceTree = "<group>"; };
819CC3332B14C53200D2EEE9 /* PaymentMethods+Equatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PaymentMethods+Equatable.swift"; sourceTree = "<group>"; };
81A2E3BD2A5C453200CF5F9C /* LinkTextViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkTextViewTests.swift; sourceTree = "<group>"; };
81A2E3BF2A5C453F00CF5F9C /* LinkTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkTextView.swift; sourceTree = "<group>"; };
81A48DBA2A5709F600242341 /* DemoAddressLookupProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoAddressLookupProvider.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2910,6 +2912,7 @@
A04E60D227E0E6280051C72C /* XCTestCase+Result.swift */,
00EACBC5288013990082B360 /* XCTestCase+Coder.swift */,
81B505782A7BE209009B4CB3 /* UIBarButtonItem+XCTest.swift */,
819CC3332B14C53200D2EEE9 /* PaymentMethods+Equatable.swift */,
);
path = Helpers;
sourceTree = "<group>";
Expand Down Expand Up @@ -3767,8 +3770,8 @@
F9EDB79023965FFC00CFB3C9 /* Payment Method List */,
E759E1F425CB373F00B1F8DC /* DropInTests.swift */,
F9EDB79D2397AEF400CFB3C9 /* ComponentManagerTests.swift */,
E7D189AF25D31936006AD3B7 /* DropInActionTests.swift */,
E74CE3DE26727EB1008231D2 /* DropInDelegateMock.swift */,
E7D189AF25D31936006AD3B7 /* DropInActionTests.swift */,
E767F4DB25A603A50077029E /* ModalToolbarTests.swift */,
E7620EAC23C3466B00A492C3 /* ModalViewControllerTests.swift */,
E7D5311B2447065B000046B4 /* PreselectedPaymentComponentTests.swift */,
Expand Down Expand Up @@ -6604,6 +6607,7 @@
81BBB34B2A692F6500AF1F9E /* FormPickerSearchViewControllerTests.swift in Sources */,
8109FF4E2AD6D8A9000748C8 /* MockAddressLookupProvider.swift in Sources */,
E72521EE25517EB100533E35 /* BLIKComponentTests.swift in Sources */,
819CC3342B14C53200D2EEE9 /* PaymentMethods+Equatable.swift in Sources */,
E2B317A22265BC9400C1BB30 /* LengthValidatorTests.swift in Sources */,
F9B019442611E965001F23FC /* EContextATMShareableVoucherViewProviderTests.swift in Sources */,
E9E3DAB2221D79C800697074 /* CardNumberFormatterTests.swift in Sources */,
Expand Down
28 changes: 22 additions & 6 deletions AdyenDropIn/DropInComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,27 @@ public final class DropInComponent: NSObject,
self.configuration = configuration
self.context = context
self.paymentMethods = paymentMethods

let scheduler = SimpleScheduler(maximumCount: 3)
self.apiClient = APIClient(apiContext: context.apiContext)
.retryAPIClient(with: scheduler)
.retryOnErrorAPIClient()

super.init()
}

/// For testing only
internal init(paymentMethods: PaymentMethods,
context: AdyenContext,
configuration: Configuration = .init(),
title: String? = nil,
apiClient: APIClientProtocol) {
self.title = title ?? Bundle.main.displayName
self.configuration = configuration
self.context = context
self.paymentMethods = paymentMethods
self.apiClient = apiClient

super.init()
}

Expand Down Expand Up @@ -92,12 +113,7 @@ public final class DropInComponent: NSObject,

// MARK: - Handling Partial Payments

private lazy var apiClient: APIClientProtocol = {
let scheduler = SimpleScheduler(maximumCount: 3)
return APIClient(apiContext: context.apiContext)
.retryAPIClient(with: scheduler)
.retryOnErrorAPIClient()
}()
private let apiClient: APIClientProtocol

internal func reloadComponentManager() {
componentManager = createComponentManager(componentManager.order)
Expand Down
7 changes: 6 additions & 1 deletion Demo/Common/Utils/APIClientMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ internal final class APIClientMock: APIClientProtocol {
self.onExecute?(request)
switch nextResult {
case let .success(response):
guard let response = response as? R.ResponseType else { return }
guard let response = response as? R.ResponseType else {
fatalError("""
The provided Response "\(response.self)" does not match \
the ResponseType of the Request "\(R.ResponseType.self)"
""")
}
completionHandler(.success(response))
case let .failure(error):
completionHandler(.failure(error))
Expand Down
2 changes: 2 additions & 0 deletions Scripts/test-carthage-integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,10 @@ cp "../Tests/Card Tests/3DS2 Component/ThreeDSResultExtension.swift" Tests/Three
cp "../Tests/Helpers/XCTestCase+RootViewController.swift" Tests/XCTestCase+RootViewController.swift
cp "../Tests/Helpers/XCTestCase+Wait.swift" Tests/XCTestCase+Wait.swift
cp "../Tests/Helpers/UIViewController+Search.swift" Tests/UIViewController+Search.swift
cp "../Tests/Helpers/PaymentMethods+Equatable.swift" Tests/PaymentMethods+Equatable.swift
cp "../Tests/Adyen Tests/Analytics/AnalyticsProviderMock.swift" Tests/AnalyticsProviderMock.swift
cp "../Tests/DummyData/Dummy.swift" Tests/Dummy.swift
cp "../Demo/Common/Utils/APIClientMock.swift" Tests/APIClientMock.swift
cp -a "../Demo/Common" Source/
cp -a "../Demo/UIKit" Source/
cp "../Demo/Configuration.swift" Source/Configuration.swift
Expand Down
9 changes: 9 additions & 0 deletions Tests/Adyen Tests/Mocks/PaymentComponentDelegateMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
@_spi(AdyenInternal) @testable import Adyen

final class PaymentComponentDelegateMock: PaymentComponentDelegate {

init(
onDidSubmit: ((PaymentComponentData, PaymentComponent) -> Void)? = nil,
onDidFail: ((Error, PaymentComponent) -> Void)? = nil
) {
self.onDidSubmit = onDidSubmit
self.onDidFail = onDidFail
}

var onDidSubmit: ((PaymentComponentData, PaymentComponent) -> Void)?
func didSubmit(_ data: PaymentComponentData, from component: PaymentComponent) {
onDidSubmit?(data, component)
Expand Down
11 changes: 11 additions & 0 deletions Tests/Card Tests/CardComponentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,17 @@ class CardComponentTests: XCTestCase {
XCTAssertTrue(expDateItem.isValid())
}

func testInstallmentEncoding() throws {

let installments = Installments(totalMonths: 12, plan: .regular)

let installmentsData = try JSONEncoder().encode(installments)
let decodedInstallments = try XCTUnwrap(JSONSerialization.jsonObject(with: installmentsData) as? [String: Any])

XCTAssertEqual(decodedInstallments["value"] as? Int, installments.totalMonths)
XCTAssertEqual(decodedInstallments["plan"] as? String, installments.plan.rawValue)
}

func testInstallmentsWithDefaultAndCardBasedOptions() {
let cardBasedInstallmentOptions: [CardType: InstallmentOptions] = [.visa:
InstallmentOptions(maxInstallmentMonth: 8, includesRevolving: true)]
Expand Down
47 changes: 46 additions & 1 deletion Tests/Components Tests/Gift Card/GiftCardComponentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -615,8 +615,53 @@ class GiftCardComponentTests: XCTestCase {
XCTAssertNotNil(expiryDateItemView, "expiry date should still be shown when security code item is hidden")
XCTAssertNil(securityCodeItemView)
}

func testPartialConfirmationPaymentMethod() {

let giftCard = GiftCardPaymentMethod(type: .giftcard, name: "Giftcard", brand: "giftcard")

let paymentMethod = PartialConfirmationPaymentMethod(
paymentMethod: giftCard,
lastFour: "1234",
remainingAmount: .init(value: 1000, currencyCode: "USD")
)

XCTAssertEqual(paymentMethod.type, giftCard.type)

let displayInformation = paymentMethod.defaultDisplayInformation(using: nil)

XCTAssertEqual(displayInformation.title, "•••• 1234")
XCTAssertEqual(displayInformation.logoName, giftCard.brand)
XCTAssertEqual(displayInformation.accessibilityLabel, "Giftcard, Last 4 digits: 1, 2, 3, 4, Remaining balance will be $10.00")
}

func testPartialPaymentOrder() throws {

let order = PartialPaymentOrder(
pspReference: "psp-reference",
orderData: "order-data",
reference: "reference",
amount: .init(value: 1000, currencyCode: "USD"),
remainingAmount: .init(value: 500, currencyCode: "USD"),
expiresAt: Date()
)

let encodedOrder = try JSONEncoder().encode(order)
let decodedOrder = try JSONDecoder().decode(PartialPaymentOrder.self, from: encodedOrder)

XCTAssertEqual(order.pspReference, decodedOrder.pspReference)
XCTAssertEqual(order.orderData, decodedOrder.orderData)
XCTAssertEqual(order.reference, decodedOrder.reference)
XCTAssertEqual(order.amount, decodedOrder.amount)
XCTAssertEqual(order.remainingAmount, decodedOrder.remainingAmount)
XCTAssertNil(decodedOrder.expiresAt)
XCTAssertEqual(order.compactOrder, decodedOrder.compactOrder)
}
}

private func populate(cardNumber: String, pin: String) {
private extension GiftCardComponentTests {

func populate(cardNumber: String, pin: String) {
populate(textItemView: numberItemView!, with: cardNumber)
populate(textItemView: securityCodeItemView!, with: pin)
}
Expand Down
16 changes: 16 additions & 0 deletions Tests/DropIn Tests/DropInDelegateMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@
import AdyenDropIn

class DropInDelegateMock: DropInComponentDelegate {

internal init(
didSubmitHandler: ((PaymentComponentData, AnyDropInComponent) -> Void)? = nil,
didProvideHandler: ((ActionComponentData, AnyDropInComponent) -> Void)? = nil,
didCompleteHandler: ((AnyDropInComponent) -> Void)? = nil,
didFailHandler: ((Error, AnyDropInComponent) -> Void)? = nil,
didOpenExternalApplicationHandler: ((AnyDropInComponent) -> Void)? = nil,
didCancelHandler: ((PaymentComponent, AnyDropInComponent) -> Void)? = nil
) {
self.didSubmitHandler = didSubmitHandler
self.didProvideHandler = didProvideHandler
self.didCompleteHandler = didCompleteHandler
self.didFailHandler = didFailHandler
self.didOpenExternalApplicationHandler = didOpenExternalApplicationHandler
self.didCancelHandler = didCancelHandler
}

var didSubmitHandler: ((PaymentComponentData, AnyDropInComponent) -> Void)?
var didProvideHandler: ((ActionComponentData, AnyDropInComponent) -> Void)?
Expand Down
128 changes: 127 additions & 1 deletion Tests/DropIn Tests/DropInTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@_spi(AdyenInternal) @testable import Adyen
@_spi(AdyenInternal) @testable import AdyenActions
import AdyenDropIn
@testable import AdyenDropIn
import SafariServices
import XCTest

Expand Down Expand Up @@ -130,6 +130,42 @@ class DropInTests: XCTestCase {
}
}

func testDropInStyle() throws {
var style = DropInComponent.Style(tintColor: .brown)

XCTAssertEqual(style.formComponent.textField.tintColor, .brown)
XCTAssertEqual(style.navigation.tintColor, .brown)

// MARK: Update separatorColor

style.separatorColor = .yellow

XCTAssertEqual(style.formComponent.separatorColor, .yellow)
XCTAssertEqual(style.navigation.separatorColor, .yellow)

style.separatorColor = .green

/*
In its current implementation calling `separatorColor` with multiple times with different colors
won't have any effect. This might be unexpected but this tests confirms the current implementation detail.
*/
XCTAssertEqual(style.formComponent.separatorColor, .yellow)
XCTAssertEqual(style.navigation.separatorColor, .yellow)

/*
To be able to restore the initial behavior
the `formComponent.separatorColor` and/or `navigation.separatorColor`
have to be nilled out
*/
style.formComponent.separatorColor = nil
style.navigation.separatorColor = nil

style.separatorColor = .green

XCTAssertEqual(style.formComponent.separatorColor, .green)
XCTAssertEqual(style.navigation.separatorColor, .green)
}

func testOpenDropInAsList() throws {
let config = DropInComponent.Configuration()

Expand Down Expand Up @@ -307,6 +343,96 @@ class DropInTests: XCTestCase {

wait(for: [waitExpectation], timeout: 30)
}

func testReload() throws {

let config = DropInComponent.Configuration()

let paymentMethods = try JSONDecoder().decode(
PaymentMethods.self,
from: XCTUnwrap(DropInTests.paymentMethods.data(using: .utf8))
)

let updatedPaymentMethods = try JSONDecoder().decode(
PaymentMethods.self,
from: XCTUnwrap(DropInTests.paymentMethodsWithSingleInstant.data(using: .utf8))
)

let expectation = expectation(description: "Api Client Called")

let apiClient = APIClientMock()
apiClient.mockedResults = [
.success(OrderStatusResponse(
remainingAmount: .init(value: 100, currencyCode: "EUR"),
paymentMethods: nil
))
]
apiClient.onExecute = {
XCTAssertTrue($0 is OrderStatusRequest)
expectation.fulfill()
}

let sut = DropInComponent(
paymentMethods: paymentMethods,
context: Dummy.context,
configuration: config,
apiClient: apiClient
)

try sut.reload(with: .init(pspReference: "", orderData: ""), updatedPaymentMethods)

wait(for: [expectation], timeout: 10)

XCTAssertEqual(sut.paymentMethods, updatedPaymentMethods)
}

func testReloadFailure() throws {

let config = DropInComponent.Configuration()

let paymentMethods = try JSONDecoder().decode(
PaymentMethods.self,
from: XCTUnwrap(DropInTests.paymentMethods.data(using: .utf8))
)

let updatedPaymentMethods = try JSONDecoder().decode(
PaymentMethods.self,
from: XCTUnwrap(DropInTests.paymentMethodsWithSingleInstant.data(using: .utf8))
)

let apiClientExpectation = expectation(description: "Api Client Called")
let failExpectation = expectation(description: "Delegate didFail Called")

let apiClient = APIClientMock()
apiClient.mockedResults = [
// Returning a random error so the reload fails
.failure(APIError(status: nil, errorCode: "", errorMessage: "", type: .internal))
]
apiClient.onExecute = {
XCTAssertTrue($0 is OrderStatusRequest)
apiClientExpectation.fulfill()
}

let sut = DropInComponent(
paymentMethods: paymentMethods,
context: Dummy.context,
configuration: config,
apiClient: apiClient
)

let delegateMock = DropInDelegateMock(
didFailHandler: { _, _ in
failExpectation.fulfill()
})

sut.delegate = delegateMock

try sut.reload(with: .init(pspReference: "", orderData: ""), updatedPaymentMethods)

wait(for: [apiClientExpectation, failExpectation], timeout: 10)

XCTAssertEqual(sut.paymentMethods, paymentMethods) // Should still be the old paymentMethods
}
}

extension UIViewController {
Expand Down
25 changes: 25 additions & 0 deletions Tests/Helpers/PaymentMethods+Equatable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Copyright (c) 2023 Adyen N.V.
//
// This file is open source and available under the MIT license. See the LICENSE file for more info.
//

import Adyen

extension PaymentMethods: Equatable {
public static func == (lhs: PaymentMethods, rhs: PaymentMethods) -> Bool {
guard lhs.regular.count == rhs.regular.count else { return false }
guard lhs.stored.count == rhs.stored.count else { return false }
for (paymentMethod1, paymentMethod2) in zip(lhs.regular, rhs.regular) {
if paymentMethod1 != paymentMethod2 {
return false
}
}
for (paymentMethod1, paymentMethod2) in zip(lhs.stored, rhs.stored) {
if paymentMethod1 != paymentMethod2 {
return false
}
}
return true
}
}
Loading

0 comments on commit 86fb191

Please sign in to comment.