From 4683f07489e003827c78e202587a49fc69d9c8b3 Mon Sep 17 00:00:00 2001 From: vladimir Date: Mon, 13 May 2024 16:59:58 +0200 Subject: [PATCH 1/3] chore: add UI tests --- .../AdyenExample.xcodeproj/project.pbxproj | 35 ++++ .../DropInNativeModuleTests.swift | 170 ++++++++++++++++++ .../ios/AdyenExampleTests/UIView+Search.swift | 37 ++++ .../UIViewController+Search.swift | 44 +++++ .../ios/AdyenExampleTests/Wait+UIKit.swift | 60 +++++++ example/ios/AdyenExampleTests/Wait.swift | 62 +++++++ example/ios/Podfile.lock | 42 ++--- 7 files changed, 429 insertions(+), 21 deletions(-) create mode 100644 example/ios/AdyenExampleTests/DropInNativeModuleTests.swift create mode 100644 example/ios/AdyenExampleTests/UIView+Search.swift create mode 100644 example/ios/AdyenExampleTests/UIViewController+Search.swift create mode 100644 example/ios/AdyenExampleTests/Wait+UIKit.swift create mode 100644 example/ios/AdyenExampleTests/Wait.swift diff --git a/example/ios/AdyenExample.xcodeproj/project.pbxproj b/example/ios/AdyenExample.xcodeproj/project.pbxproj index 5d7946d25..caba86e54 100644 --- a/example/ios/AdyenExample.xcodeproj/project.pbxproj +++ b/example/ios/AdyenExample.xcodeproj/project.pbxproj @@ -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 = ""; }; E773B1082BE3B48900638431 /* DropInConfigurationParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropInConfigurationParserTests.swift; sourceTree = ""; }; E79C3ACF2BE161F100FACBCA /* ThreeDSConfigurationParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreeDSConfigurationParserTests.swift; sourceTree = ""; }; + E7ED1EBD2BF25F6C00B5F080 /* DropInNativeModuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropInNativeModuleTests.swift; sourceTree = ""; }; + E7ED1EBE2BF25F6C00B5F080 /* Wait+UIKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Wait+UIKit.swift"; sourceTree = ""; }; + E7ED1EBF2BF25F6C00B5F080 /* UIViewController+Search.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Search.swift"; sourceTree = ""; }; + E7ED1EC02BF25F6C00B5F080 /* Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wait.swift; sourceTree = ""; }; + E7ED1EC12BF25F6C00B5F080 /* UIView+Search.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Search.swift"; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; @@ -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; diff --git a/example/ios/AdyenExampleTests/DropInNativeModuleTests.swift b/example/ios/AdyenExampleTests/DropInNativeModuleTests.swift new file mode 100644 index 000000000..5e1c8f4c1 --- /dev/null +++ b/example/ios/AdyenExampleTests/DropInNativeModuleTests.swift @@ -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]) + } + +} diff --git a/example/ios/AdyenExampleTests/UIView+Search.swift b/example/ios/AdyenExampleTests/UIView+Search.swift new file mode 100644 index 000000000..40ff4a34b --- /dev/null +++ b/example/ios/AdyenExampleTests/UIView+Search.swift @@ -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(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(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 + } +} diff --git a/example/ios/AdyenExampleTests/UIViewController+Search.swift b/example/ios/AdyenExampleTests/UIViewController+Search.swift new file mode 100644 index 000000000..9b46274e1 --- /dev/null +++ b/example/ios/AdyenExampleTests/UIViewController+Search.swift @@ -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(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) + } +} diff --git a/example/ios/AdyenExampleTests/Wait+UIKit.swift b/example/ios/AdyenExampleTests/Wait+UIKit.swift new file mode 100644 index 000000000..4dc0b84f4 --- /dev/null +++ b/example/ios/AdyenExampleTests/Wait+UIKit.swift @@ -0,0 +1,60 @@ + // + // 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 + + extension XCTestCase { + + /// Waits for a viewController of a certain type to become a child of another viewController + /// + /// Instead of waiting for a specific amount of time it polls if the expecation is returning true in time intervals of 10ms until the timeout is reached. + /// Use it whenever a value change is not guaranteed to be instant or happening after a short amount of time. + /// + /// - Parameters: + /// - ofType: the type of the expected child viewController + /// - viewController: the parent viewController + /// - timeout: the maximum time (in seconds) to wait. + @discardableResult + func waitForViewController( + ofType: T.Type, + toBecomeChildOf viewController: UIViewController, + timeout: TimeInterval = 60 + ) throws -> T { + + wait( + until: { viewController.firstChild(of: T.self) != nil }, + timeout: timeout, + message: "\(String(describing: T.self)) should appear on \(String(describing: viewController.self)) before timeout \(timeout)s" + ) + + return try XCTUnwrap(viewController.firstChild(of: T.self)) + } + + /// Waits for a viewController of a certain type to become a child of another viewController + /// + /// Instead of waiting for a specific amount of time it polls if the expecation is returning true in time intervals of 10ms until the timeout is reached. + /// Use it whenever a value change is not guaranteed to be instant or happening after a short amount of time. + /// + /// - Parameters: + /// - ofType: the type of the expected child viewController + /// - viewController: the parent viewController + /// - timeout: the maximum time (in seconds) to wait. + @discardableResult + func waitUntilTopPresenter( + isOfType: T.Type, + timeout: TimeInterval = 60 + ) throws -> T { + + wait( + until: { (try? UIViewController.topPresenter() is T) ?? false }, + timeout: timeout, + message: "\(String(describing: T.self)) should become top presenter before timeout \(timeout)s" + ) + + return try XCTUnwrap(UIViewController.topPresenter() as? T) + } + } diff --git a/example/ios/AdyenExampleTests/Wait.swift b/example/ios/AdyenExampleTests/Wait.swift new file mode 100644 index 000000000..b769147a7 --- /dev/null +++ b/example/ios/AdyenExampleTests/Wait.swift @@ -0,0 +1,62 @@ + // + // 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 XCTest + + extension XCTestCase { + + /// Waits until a certain condition is met + /// + /// Instead of waiting for a specific amount of time it polls if the expecation is returning true in time intervals of 10ms until the timeout is reached. + /// Use it whenever a value change is not guaranteed to be instant or happening after a short amount of time. + /// + /// - Parameters: + /// - expectation: the condition that is waited on + /// - timeout: the maximum time (in seconds) to wait. + /// - retryInterval: the waiting time inbetween retries + /// - message: an optional message on failure + func wait( + until expectation: () -> Bool, + timeout: TimeInterval = 60, + retryInterval: DispatchTimeInterval = .seconds(1), + message: String? = nil + ) { + let thresholdDate = Date().addingTimeInterval(timeout) + + var isMatchingExpectation = expectation() + + while thresholdDate.timeIntervalSinceNow > 0, !isMatchingExpectation { + wait(for: retryInterval) + isMatchingExpectation = expectation() + } + + XCTAssertTrue(isMatchingExpectation, message ?? "Expectation should be met before timeout \(timeout)s") + } + + /// Waits until a keyPath of a target matches an expected value + /// + /// Instead of waiting for a specific amount of time it polls if the expecation is returning true in time intervals of 10ms until the timeout is reached. + /// Use it whenever a value change is not guaranteed to be instant or happening after a short amount of time. + /// + /// - Parameters: + /// - target: the target to observe + /// - keyPath: the keyPath to check + /// - expectedValue: the value to check against + /// - timeout: the maximum time (in seconds) to wait. + func wait( + until target: Target, + at keyPath: KeyPath, + is expectedValue: Value, + timeout: TimeInterval = 60, + line: Int = #line + ) { + wait( + until: { target[keyPath: keyPath] == expectedValue }, + timeout: timeout, + message: "Value of \(keyPath) (\(target[keyPath: keyPath])) should become \(String(describing: expectedValue)) within \(timeout)s [line:\(line)]" + ) + } + } diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 2ee6879ac..fa6ca7ee9 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,38 +1,38 @@ PODS: - - Adyen (5.7.0): - - Adyen/Actions (= 5.7.0) - - Adyen/Card (= 5.7.0) - - Adyen/Components (= 5.7.0) - - Adyen/Core (= 5.7.0) - - Adyen/DropIn (= 5.7.0) - - Adyen/Encryption (= 5.7.0) - - Adyen/Session (= 5.7.0) + - Adyen (5.7.1): + - Adyen/Actions (= 5.7.1) + - Adyen/Card (= 5.7.1) + - Adyen/Components (= 5.7.1) + - Adyen/Core (= 5.7.1) + - Adyen/DropIn (= 5.7.1) + - Adyen/Encryption (= 5.7.1) + - Adyen/Session (= 5.7.1) - adyen-react-native (2.0.0-local.1): - - Adyen (= 5.7.0) + - Adyen (= 5.7.1) - React-Core - - Adyen/Actions (5.7.0): + - Adyen/Actions (5.7.1): - Adyen/Core - - Adyen3DS2 (= 2.4.1) - - Adyen/Card (5.7.0): + - Adyen3DS2 (= 2.4.2) + - Adyen/Card (5.7.1): - Adyen/Core - Adyen/Encryption - - Adyen/Components (5.7.0): + - Adyen/Components (5.7.1): - Adyen/Core - Adyen/Encryption - - Adyen/Core (5.7.0): + - Adyen/Core (5.7.1): - AdyenNetworking (= 2.0.0) - - Adyen/DropIn (5.7.0): + - Adyen/DropIn (5.7.1): - Adyen/Actions - Adyen/Card - Adyen/Components - Adyen/Core - Adyen/Encryption - - Adyen/Encryption (5.7.0): + - Adyen/Encryption (5.7.1): - Adyen/Core - - Adyen/Session (5.7.0): + - Adyen/Session (5.7.1): - Adyen/Actions - Adyen/Core - - Adyen3DS2 (2.4.1) + - Adyen3DS2 (2.4.2) - AdyenNetworking (2.0.0) - boost (1.76.0) - DoubleConversion (1.1.6) @@ -482,9 +482,9 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - Adyen: 48550990ad15ccde06ca6f8dc3143fc8c44719b6 - adyen-react-native: f45e5095ed4711680eeb9d95afa93d5c1d664b5b - Adyen3DS2: 6e1e6c7369118377feabe59706fc4a06dcfa848b + Adyen: 61b166d1412eec226e8aa00727b7dc25d25008bb + adyen-react-native: 2f82afdab97be28fbe926a9cdfa8bf87b1c81c1b + Adyen3DS2: aaa0a86c89f4f5d482d20894b2f91e91a63aee6b AdyenNetworking: 49e447632b542e08c6dd06bb47ea1077a8adecb7 boost: 57d2868c099736d80fcd648bf211b4431e51a558 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 From 619308b88807060b8898d740b67e53b0713e63e2 Mon Sep 17 00:00:00 2001 From: Vladimir Abramichev <2648655+descorp@users.noreply.github.com> Date: Mon, 13 May 2024 19:08:47 +0200 Subject: [PATCH 2/3] chore: prebuild project and run metro --- .github/workflows/ios_tests.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ios_tests.yml b/.github/workflows/ios_tests.yml index 1361f206a..9cd359f17 100644 --- a/.github/workflows/ios_tests.yml +++ b/.github/workflows/ios_tests.yml @@ -41,7 +41,6 @@ jobs: key: temp-node-${{ github.sha }} - name: Build dependency if needed - if: steps.yarn-cache.outputs.cache-hit != 'true' run: yarn - uses: actions/cache@v4 @@ -54,6 +53,12 @@ jobs: working-directory: example/ios run: pod update + - name: Run Metro + working-directory: example + run: | + yarn + npx react-native start + - name: Run tests working-directory: example/ios run: | From 1cf200162875be848d15aaf937eda442454c5a38 Mon Sep 17 00:00:00 2001 From: vladimir Date: Tue, 14 May 2024 16:42:02 +0200 Subject: [PATCH 3/3] chore: try osascript --- .github/workflows/ios_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ios_tests.yml b/.github/workflows/ios_tests.yml index 9cd359f17..195863d88 100644 --- a/.github/workflows/ios_tests.yml +++ b/.github/workflows/ios_tests.yml @@ -56,8 +56,8 @@ jobs: - name: Run Metro working-directory: example run: | - yarn - npx react-native start + yarn + osascript -e 'tell application "Terminal" to do script "'"cd $(pwd) && npx react-native start"'"' - name: Run tests working-directory: example/ios