Skip to content

Commit

Permalink
chore: add UI tests
Browse files Browse the repository at this point in the history
  • Loading branch information
descorp committed May 13, 2024
1 parent e0100aa commit 4683f07
Showing 7 changed files with 429 additions and 21 deletions.
35 changes: 35 additions & 0 deletions example/ios/AdyenExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -18,6 +18,11 @@
B6CB27F7E4011E633F2A25A7 /* libPods-AdyenExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 74FF1EDD8A3337F905F9FF61 /* libPods-AdyenExample.a */; };
E773B1092BE3B48900638431 /* DropInConfigurationParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E773B1082BE3B48900638431 /* DropInConfigurationParserTests.swift */; };
E79C3AD02BE161F100FACBCA /* ThreeDSConfigurationParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E79C3ACF2BE161F100FACBCA /* ThreeDSConfigurationParserTests.swift */; };
E7ED1EC22BF25F6C00B5F080 /* DropInNativeModuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ED1EBD2BF25F6C00B5F080 /* DropInNativeModuleTests.swift */; };
E7ED1EC32BF25F6C00B5F080 /* Wait+UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ED1EBE2BF25F6C00B5F080 /* Wait+UIKit.swift */; };
E7ED1EC42BF25F6C00B5F080 /* UIViewController+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ED1EBF2BF25F6C00B5F080 /* UIViewController+Search.swift */; };
E7ED1EC52BF25F6C00B5F080 /* Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ED1EC02BF25F6C00B5F080 /* Wait.swift */; };
E7ED1EC62BF25F6C00B5F080 /* UIView+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ED1EC12BF25F6C00B5F080 /* UIView+Search.swift */; };
F5C555F429F6C9F5008E7AA8 /* AdyenAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C555F329F6C9F5008E7AA8 /* AdyenAppearance.swift */; };
/* End PBXBuildFile section */

@@ -53,6 +58,11 @@
E757C9D727737E6700B62256 /* AdyenExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = AdyenExample.entitlements; path = AdyenExample/AdyenExample.entitlements; sourceTree = "<group>"; };
E773B1082BE3B48900638431 /* DropInConfigurationParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropInConfigurationParserTests.swift; sourceTree = "<group>"; };
E79C3ACF2BE161F100FACBCA /* ThreeDSConfigurationParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreeDSConfigurationParserTests.swift; sourceTree = "<group>"; };
E7ED1EBD2BF25F6C00B5F080 /* DropInNativeModuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropInNativeModuleTests.swift; sourceTree = "<group>"; };
E7ED1EBE2BF25F6C00B5F080 /* Wait+UIKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Wait+UIKit.swift"; sourceTree = "<group>"; };
E7ED1EBF2BF25F6C00B5F080 /* UIViewController+Search.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Search.swift"; sourceTree = "<group>"; };
E7ED1EC02BF25F6C00B5F080 /* Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wait.swift; sourceTree = "<group>"; };
E7ED1EC12BF25F6C00B5F080 /* UIView+Search.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Search.swift"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
F5C555F329F6C9F5008E7AA8 /* AdyenAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdyenAppearance.swift; sourceTree = "<group>"; };
F6D60E250285EB5A965E4921 /* Pods-AdyenExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AdyenExample.debug.xcconfig"; path = "Target Support Files/Pods-AdyenExample/Pods-AdyenExample.debug.xcconfig"; sourceTree = "<group>"; };
@@ -81,6 +91,11 @@
00E356EF1AD99517003FC87E /* AdyenExampleTests */ = {
isa = PBXGroup;
children = (
E7ED1EBD2BF25F6C00B5F080 /* DropInNativeModuleTests.swift */,
E7ED1EC12BF25F6C00B5F080 /* UIView+Search.swift */,
E7ED1EBF2BF25F6C00B5F080 /* UIViewController+Search.swift */,
E7ED1EC02BF25F6C00B5F080 /* Wait.swift */,
E7ED1EBE2BF25F6C00B5F080 /* Wait+UIKit.swift */,
E773B10A2BE3B5B000638431 /* Parsers */,
00E356F01AD99517003FC87E /* Supporting Files */,
948B9B012A83D269003D15B4 /* DropInTest.swift */,
@@ -431,9 +446,14 @@
buildActionMask = 2147483647;
files = (
94FC2FEC2AF28DAE009F6FC1 /* CardConfigurationTests.swift in Sources */,
E7ED1EC52BF25F6C00B5F080 /* Wait.swift in Sources */,
E7ED1EC62BF25F6C00B5F080 /* UIView+Search.swift in Sources */,
945936B12AE185B700F3E676 /* ApplePayConfigurationTests.swift in Sources */,
E773B1092BE3B48900638431 /* DropInConfigurationParserTests.swift in Sources */,
948B9B022A83D269003D15B4 /* DropInTest.swift in Sources */,
E7ED1EC22BF25F6C00B5F080 /* DropInNativeModuleTests.swift in Sources */,
E7ED1EC32BF25F6C00B5F080 /* Wait+UIKit.swift in Sources */,
E7ED1EC42BF25F6C00B5F080 /* UIViewController+Search.swift in Sources */,
E79C3AD02BE161F100FACBCA /* ThreeDSConfigurationParserTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -618,6 +638,7 @@
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -638,6 +659,11 @@
);
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
"-Wl",
"-ld_classic",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
};
@@ -680,6 +706,10 @@
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
@@ -697,6 +727,11 @@
"\"$(inherited)\"",
);
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = (
"$(inherited)",
"-Wl",
"-ld_classic",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
170 changes: 170 additions & 0 deletions example/ios/AdyenExampleTests/DropInNativeModuleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
//
// Copyright (c) 2024 Adyen N.V.
//
// This file is open source and available under the MIT license. See the LICENSE file for more info.
//

import Adyen
@testable import adyen_react_native
import XCTest

final class DropInNativeModuleTests: XCTestCase {

let shortPaymentMethods: NSDictionary = ["paymentMethods": [
[
"type": "scheme",
"name": "Cards"
],
[
"type": "klarna",
"name": "Klarna"
],
]]

let fullPaymentMethods: NSDictionary = [
"paymentMethods": [
[
"type": "scheme",
"name": "Cards"
],
[
"type": "klarna",
"name": "Klarna"
],
],
"storedPaymentMethods": [
[
"brand": "visa",
"expiryMonth": "03",
"expiryYear": "30",
"id": "J469JCZC5KPBGP65",
"lastFour": "6746",
"name": "VISA",
"supportedShopperInteractions": [
"Ecommerce",
"ContAuth"
],
"type": "scheme"
],
]
]


func testSimpleList() throws {
// GIVEN
let sut = DropInModule()
let config: NSDictionary = ["clientKey": "live_XXXXXXXXXX"]


// WHEN
sut.open(shortPaymentMethods, configuration: config)

// THEN
XCTAssertTrue(try isPresentingDropIn())

let topView = try XCTUnwrap(getDropInView() as? UITableViewController)
XCTAssertEqual(getNumberOfElement(in: topView.tableView, section: 0), 2)
XCTAssertEqual(topView.title, "Payment Methods")

// TEAR DOWN
dissmissDropIn()
}

func testStoredList() throws {
// GIVEN
let sut = DropInModule()
let config: NSDictionary = [
"clientKey": "live_XXXXXXXXXX",
]

// WHEN
sut.open(fullPaymentMethods, configuration: config)

// THEN
XCTAssertTrue(try isPresentingDropIn())

let topView = try XCTUnwrap(getDropInView())
XCTAssertEqual(topView.title, "AdyenExample")

// TEAR DOWN
dissmissDropIn()
}

func testTitleSetter() throws {
// GIVEN
let sut = DropInModule()
let config: NSDictionary = [
"clientKey": "live_XXXXXXXXXX",
"dropin": [
"title": "MY_TITLE"
]
]

// WHEN
sut.open(fullPaymentMethods, configuration: config)

// THEN
XCTAssertTrue(try isPresentingDropIn())

let topView = try XCTUnwrap(getDropInView())
XCTAssertEqual(topView.title, "MY_TITLE")

// TEAR DOWN
dissmissDropIn()
}

func testSkipingPreset() throws {
// GIVEN
let sut = DropInModule()
let config: NSDictionary = [
"clientKey": "live_XXXXXXXXXX",
"dropin": [
"showPreselectedStoredPaymentMethod": false
]
]

// WHEN
sut.open(fullPaymentMethods, configuration: config)

// THEN
XCTAssertTrue(try isPresentingDropIn())

let topView = try XCTUnwrap(getDropInView() as? UITableViewController)
XCTAssertEqual(getNumberOfElement(in: topView.tableView, section: 0), 1)
XCTAssertEqual(getNumberOfElement(in: topView.tableView, section: 1), 2)
XCTAssertEqual(topView.title, "Payment Methods")

// TEAR DOWN
dissmissDropIn()
}

func isPresentingDropIn() throws -> Bool {
let dropin = try waitUntilTopPresenter(isOfType: UINavigationController.self)
return dropin is AdyenObserver
}

func getDropInView() -> UIViewController? {

var controller: UIViewController?
var nextController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController?.presentedViewController

while nextController != nil {
controller = nextController
nextController = nextController?.children.first
}
return controller
}

func getNumberOfElement(in tableView: UITableView, section: Int) -> Int? {
tableView.dataSource?.tableView(tableView, numberOfRowsInSection: section)
}

func dissmissDropIn() {
let expectation = expectation(description: "DropIn closing")
UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: false, completion: {
expectation.fulfill()
})
wait(for: [expectation])
}

}
37 changes: 37 additions & 0 deletions example/ios/AdyenExampleTests/UIView+Search.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Copyright (c) 2024 Adyen N.V.
//
// This file is open source and available under the MIT license. See the LICENSE file for more info.
//

import UIKit

internal extension UIView {
func findView<T: UIView>(with accessibilityIdentifier: String) -> T? {
if self.accessibilityIdentifier == accessibilityIdentifier {
return self as? T
}

for subview in subviews {
if let v = subview.findView(with: accessibilityIdentifier) {
return v as? T
}
}

return nil
}

func findView<T: UIView>(by lastAccessibilityIdentifierComponent: String) -> T? {
if self.accessibilityIdentifier?.hasSuffix(lastAccessibilityIdentifierComponent) == true {
return self as? T
}

for subview in subviews {
if let v = subview.findView(by: lastAccessibilityIdentifierComponent) {
return v as? T
}
}

return nil
}
}
44 changes: 44 additions & 0 deletions example/ios/AdyenExampleTests/UIViewController+Search.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright (c) 2024 Adyen N.V.
//
// This file is open source and available under the MIT license. See the LICENSE file for more info.
//

import UIKit
import XCTest
@_spi(AdyenInternal) @testable import Adyen

public extension UIViewController {

/// Returns the first child of the viewControllers children that matches the type
///
/// - Parameters:
/// - type: The type of the viewController
func firstChild<T: UIViewController>(of type: T.Type) -> T? {
if let result = self as? T {
return result
}

for child in self.children {
if let result = child.firstChild(of: T.self) {
return result
}
}

return nil
}

/// Returns the current top viewController
///
/// - Throws: if there is no rootViewController can be found on the window
static func topPresenter() throws -> UIViewController {
let rootViewController = try XCTUnwrap(UIApplication.shared.adyen.mainKeyWindow?.rootViewController)
return rootViewController.adyen.topPresenter
}
}

extension UIViewController: PresentationDelegate {
public func present(component: PresentableComponent) {
self.present(component.viewController, animated: false, completion: nil)
}
}
Loading

0 comments on commit 4683f07

Please sign in to comment.