diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 52dd2d4c88..a8cec1f8ea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,20 +10,36 @@ on: jobs: tests: - runs-on: macos-12 + runs-on: macos-14-xlarge continue-on-error: true strategy: fail-fast: false matrix: include: - - destination: 'name=iPhone 11 Pro' - scheme: AdyenUIHost - - destination: 'name=iPhone-6,OS=11.4' - scheme: AdyenUIHost - - destination: 'name=iPhone-X,OS=12.4' - scheme: AdyenUIKitTests - - destination: 'name=iPhone 8,OS=13.7' - scheme: AdyenUIHost + + - version: '18.1' + runtime: 'iOS-18-1' + device: 'iPhone 16' + displayname: 'iPhone-16' + os: 'macos-14-xlarge' + xcode_version: '16.1' + needs_custom_sim: false # Takes the shipped simulator that comes with Xcode 16 + + - version: '18.1' + runtime: 'iOS-18-1' + device: 'iPad (10th generation)' + displayname: 'iPad-10th-generation' + os: 'macos-14-xlarge' + xcode_version: '16.1' + needs_custom_sim: false # Takes the shipped simulator that comes with Xcode 16 + + - version: '16.4' + runtime: 'iOS-16-4' + device: 'iPhone 14' + displayname: 'iPhone-14' + os: 'macos-14-xlarge' + xcode_version: '16.1' + needs_custom_sim: false # Takes the shipped simulator that comes with Xcode 16 steps: - uses: actions/checkout@v3 - uses: n1hility/cancel-previous-runs@v3 @@ -65,12 +81,12 @@ jobs: destination: ${{ matrix.destination }} sonar: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: '11' + java-version: '17' - name: Install Dependencies run: | @@ -84,7 +100,7 @@ jobs: project: 'Adyen.xcodeproj' params: '-derivedDataPath ./DerivedData -enableCodeCoverage YES' scheme: AdyenUIHost - destination: 'name=iPhone 11' + destination: 'name=iPhone 16' - name: Slather run: | diff --git a/.github/workflows/format_project.yml b/.github/workflows/format_project.yml index dfc27fea7d..43c2b7ae58 100644 --- a/.github/workflows/format_project.yml +++ b/.github/workflows/format_project.yml @@ -3,7 +3,7 @@ on: [workflow_dispatch] jobs: Update: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v4 with: @@ -15,7 +15,7 @@ jobs: - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Format project run: | diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 9e3acb8626..7cae0cc7a2 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -5,11 +5,14 @@ on: types: [opened, synchronize, reopened] jobs: - + build: env: sonarToken: ${{ secrets.SONAR_TOKEN }} - runs-on: macos-12 + destination: "name=iPhone 16 Pro,OS=18.1" + project: "Adyen.xcodeproj" + params: "-derivedDataPath ./DerivedData -skipPackagePluginValidation" + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v3 @@ -18,12 +21,12 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/setup-java@v1 with: - java-version: '11' + java-version: '17' - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Install Tools run: | @@ -43,11 +46,8 @@ jobs: xcodebuild -version xcodebuild clean build test -project "${project}" -scheme "${scheme}" ${params} -destination "${destination}" | xcpretty && exit ${PIPESTATUS[0]} env: - project: 'Adyen.xcodeproj' - params: '-derivedDataPath ./DerivedData -enableCodeCoverage YES' + params: '${{env.params}}' scheme: 'AdyenUIHost' - destination: 'name=iPhone 11' - - name: Slather run: | slather coverage --sonarqube-xml ${params} ${project} @@ -68,6 +68,7 @@ jobs: - name: SwiftLint run: | + brew install swiftlint fastlane run swiftlint output_file:"./reports/swiftlint.json" reporter:"json" ignore_exit_status:"true" - name: Run Sonar diff --git a/.github/workflows/publich_podspec.yml b/.github/workflows/publich_podspec.yml index a224683ee0..b49211eddd 100644 --- a/.github/workflows/publich_podspec.yml +++ b/.github/workflows/publich_podspec.yml @@ -3,14 +3,14 @@ on: [workflow_dispatch] jobs: publish: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v3 - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Publish Adyen.podspec run: | diff --git a/.github/workflows/publish-demo-app.yml b/.github/workflows/publish-demo-app.yml index 0525eac6b0..1c39030eb6 100644 --- a/.github/workflows/publish-demo-app.yml +++ b/.github/workflows/publish-demo-app.yml @@ -3,7 +3,7 @@ on: [workflow_dispatch] jobs: Publish: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v3 with: @@ -15,7 +15,7 @@ jobs: - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Install the Apple certificate and provisioning profile env: diff --git a/.github/workflows/regenerate-docs.yml b/.github/workflows/regenerate-docs.yml index ca331a10a9..aebc79c3c4 100644 --- a/.github/workflows/regenerate-docs.yml +++ b/.github/workflows/regenerate-docs.yml @@ -3,7 +3,7 @@ on: [workflow_dispatch] jobs: Generate: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v3 with: @@ -15,7 +15,7 @@ jobs: - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Generate Docs run: | diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index 2f6ab2dd1d..1087ce66db 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -12,7 +12,7 @@ on: jobs: setup: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v3 - uses: n1hility/cancel-previous-runs@v3 diff --git a/.github/workflows/test-SPM-integration.yml b/.github/workflows/test-SPM-integration.yml index 9449f72fb9..c618add167 100644 --- a/.github/workflows/test-SPM-integration.yml +++ b/.github/workflows/test-SPM-integration.yml @@ -12,7 +12,7 @@ on: jobs: SPM: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v3 - uses: n1hility/cancel-previous-runs@v3 @@ -22,7 +22,7 @@ jobs: - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Test Swift Package Manager Integration run: | diff --git a/.github/workflows/test-carthage-integration.yml b/.github/workflows/test-carthage-integration.yml index 885fcbe4a3..649326843e 100644 --- a/.github/workflows/test-carthage-integration.yml +++ b/.github/workflows/test-carthage-integration.yml @@ -12,9 +12,9 @@ on: jobs: carthage: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: n1hility/cancel-previous-runs@v3 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -22,12 +22,13 @@ jobs: - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Resolve dependencies run: | brew update brew install xcodegen + brew install carthage brew upgrade carthage - name: Test Carthage Integration @@ -35,4 +36,4 @@ jobs: GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | carthage version - Scripts/test-carthage-integration.sh + Scripts/test-carthage-integration.sh \ No newline at end of file diff --git a/.github/workflows/test_cocoapods_integration.yml b/.github/workflows/test_cocoapods_integration.yml index 29ef70e86e..32b0c107b4 100644 --- a/.github/workflows/test_cocoapods_integration.yml +++ b/.github/workflows/test_cocoapods_integration.yml @@ -12,9 +12,9 @@ on: jobs: pods: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: n1hility/cancel-previous-runs@v3 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -22,14 +22,17 @@ jobs: - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Lint Cocoapods run: | + brew update + brew install xcodegen gem install cocoapods -v 1.10.2 + pod repo update pod lib lint Adyen.podspec --allow-warnings --verbose - name: Test Cocoapods Integration run: | Scripts/test-CocoaPods-integration.sh -w - Scripts/test-CocoaPods-integration.sh + Scripts/test-CocoaPods-integration.sh \ No newline at end of file diff --git a/.github/workflows/update-version.yml b/.github/workflows/update-version.yml index d8e5d8a0fd..a712962e83 100644 --- a/.github/workflows/update-version.yml +++ b/.github/workflows/update-version.yml @@ -8,7 +8,7 @@ on: jobs: Update: - runs-on: macos-12 + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v3 with: @@ -20,7 +20,7 @@ jobs: - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: latest-stable + xcode-version: '16.1' - name: Update version number run: | diff --git a/Adyen.xcodeproj/project.pbxproj b/Adyen.xcodeproj/project.pbxproj index d210c7b9bc..395d8f0d2f 100644 --- a/Adyen.xcodeproj/project.pbxproj +++ b/Adyen.xcodeproj/project.pbxproj @@ -124,6 +124,7 @@ C978F5EF2732CD6A00F59B3C /* FormCardSecurityCodeItemViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C978F5EE2732CD6A00F59B3C /* FormCardSecurityCodeItemViewTests.swift */; }; C982FFD826946F0800AED849 /* AffirmComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C982FFD726946F0800AED849 /* AffirmComponent.swift */; }; C982FFDC2694792F00AED849 /* AffirmPaymentMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = C982FFDB2694792F00AED849 /* AffirmPaymentMethod.swift */; }; + C9B506C32D3E776200AAE686 /* JSONEncoder+SortedKeys.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B506C22D3E776200AAE686 /* JSONEncoder+SortedKeys.swift.swift */; }; C9BB460427622D9B00E6730B /* BACSConfirmationViewProtocolMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BB460327622D9B00E6730B /* BACSConfirmationViewProtocolMock.swift */; }; C9BB460627622E9600E6730B /* BACSConfirmationPresenterProtocolMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BB460527622E9600E6730B /* BACSConfirmationPresenterProtocolMock.swift */; }; C9BB460927622F4100E6730B /* BACSConfirmationPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BB460827622F4100E6730B /* BACSConfirmationPresenterTests.swift */; }; @@ -1066,6 +1067,7 @@ C978F5EE2732CD6A00F59B3C /* FormCardSecurityCodeItemViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormCardSecurityCodeItemViewTests.swift; sourceTree = ""; }; C982FFD726946F0800AED849 /* AffirmComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AffirmComponent.swift; sourceTree = ""; }; C982FFDB2694792F00AED849 /* AffirmPaymentMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AffirmPaymentMethod.swift; sourceTree = ""; }; + C9B506C22D3E776200AAE686 /* JSONEncoder+SortedKeys.swift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONEncoder+SortedKeys.swift.swift"; sourceTree = ""; }; C9BB460327622D9B00E6730B /* BACSConfirmationViewProtocolMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BACSConfirmationViewProtocolMock.swift; sourceTree = ""; }; C9BB460527622E9600E6730B /* BACSConfirmationPresenterProtocolMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BACSConfirmationPresenterProtocolMock.swift; sourceTree = ""; }; C9BB460827622F4100E6730B /* BACSConfirmationPresenterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BACSConfirmationPresenterTests.swift; sourceTree = ""; }; @@ -2661,6 +2663,7 @@ E736497E25277B6500AB76AE /* StringExtension.swift */, E736498125277B9100AB76AE /* DataExtension.swift */, E736498325277BAA00AB76AE /* IntegerExtension.swift */, + C9B506C22D3E776200AAE686 /* JSONEncoder+SortedKeys.swift.swift */, ); path = Extensions; sourceTree = ""; @@ -5461,6 +5464,7 @@ E74517A425FB834C000BDCCF /* EncryptedCard.swift in Sources */, F9F1A98F26CD15C30005CB1D /* RSAOAEP256Algorithm.swift in Sources */, A0414C342791D9EC00DF3FE9 /* BankDetailsEncryptor.swift in Sources */, + C9B506C32D3E776200AAE686 /* JSONEncoder+SortedKeys.swift.swift in Sources */, F9F1A98926CD0CCF0005CB1D /* CommonCryptoHelpers.swift in Sources */, E745179925FB8340000BDCCF /* Card.swift in Sources */, F92326BD25A366D9002C5BC4 /* CardPayload.swift in Sources */, diff --git a/Adyen/Core/Components/Base/Component.swift b/Adyen/Core/Components/Base/Component.swift index d21ae05c0a..1543093c97 100644 --- a/Adyen/Core/Components/Base/Component.swift +++ b/Adyen/Core/Components/Base/Component.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 Adyen N.V. +// Copyright (c) 2019 Adyen N.V. // // This file is open source and available under the MIT license. See the LICENSE file for more info. // @@ -78,9 +78,9 @@ public extension Component { } private enum AssociatedKeys { - internal static var isDropIn = "isDropInObject" + internal static var isDropIn: Void? - internal static var environment = "environmentObject" + internal static var environment: Void? - internal static var clientKey = "clientKeyObject" + internal static var clientKey: Void? } diff --git a/Adyen/Core/Components/Base/PaymentComponent.swift b/Adyen/Core/Components/Base/PaymentComponent.swift index 4a794899d9..b69741a883 100644 --- a/Adyen/Core/Components/Base/PaymentComponent.swift +++ b/Adyen/Core/Components/Base/PaymentComponent.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 Adyen N.V. +// Copyright (c) 2019 Adyen N.V. // // This file is open source and available under the MIT license. See the LICENSE file for more info. // @@ -96,7 +96,7 @@ extension PaymentAwareComponent { private enum AssociatedKeys { - internal static var payment = "paymentObject" + internal static var payment: Void? - internal static var order = "orderObject" + internal static var order: Void? } diff --git a/Adyen/Helpers/UIViewAnimation.swift b/Adyen/Helpers/UIViewAnimation.swift index 2f004819ad..4e94d497ad 100644 --- a/Adyen/Helpers/UIViewAnimation.swift +++ b/Adyen/Helpers/UIViewAnimation.swift @@ -7,7 +7,7 @@ import UIKit private enum AssociatedKeys { - internal static var animations = "animations" + internal static var animations: Void? } /// :nodoc: diff --git a/Adyen/UI/Form/Items/Address/AddressViewModel.swift b/Adyen/UI/Form/Items/Address/AddressViewModel.swift index 38219d8928..f87a93c46f 100644 --- a/Adyen/UI/Form/Items/Address/AddressViewModel.swift +++ b/Adyen/UI/Form/Items/Address/AddressViewModel.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 Adyen N.V. +// Copyright (c) 2021 Adyen N.V. // // This file is open source and available under the MIT license. See the LICENSE file for more info. // @@ -49,7 +49,7 @@ public struct AddressViewModel { /// :nodoc: public private(set) var schema: [FormScheme] - // swiftlint:disable function_body_length explicit_acl + // swiftlint:disable function_body_length internal static subscript(context: AddressViewModelBuilderContext) -> AddressViewModel { var viewModel = AddressViewModel(labels: [.city: .cityFieldTitle, .houseNumberOrName: .houseNumberFieldTitle, diff --git a/Adyen/Utilities/Coder.swift b/Adyen/Utilities/Coder.swift index d792f8203c..0ec714914e 100644 --- a/Adyen/Utilities/Coder.swift +++ b/Adyen/Utilities/Coder.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2021 Adyen N.V. +// Copyright (c) 2019 Adyen N.V. // // This file is open source and available under the MIT license. See the LICENSE file for more info. // @@ -70,7 +70,8 @@ public enum Coder { private static let encoder: JSONEncoder = { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .iso8601 - + encoder.outputFormatting = .sortedKeys + return encoder }() diff --git a/Adyen/Utilities/Observable/Observer.swift b/Adyen/Utilities/Observable/Observer.swift index c2d43ce675..14397e7f72 100644 --- a/Adyen/Utilities/Observable/Observer.swift +++ b/Adyen/Utilities/Observable/Observer.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2021 Adyen N.V. +// Copyright (c) 2019 Adyen N.V. // // This file is open source and available under the MIT license. See the LICENSE file for more info. // @@ -161,6 +161,6 @@ public extension Observer { private enum AssociatedKeys { /// The observation manager associated with the object. - public static var observationManager = "observationManager" + public static var observationManager: Void? } diff --git a/AdyenActions/Components/3DS2/ThreeDS2ComponentFingerprint.swift b/AdyenActions/Components/3DS2/ThreeDS2ComponentFingerprint.swift index 3995adc198..c4cf9ff157 100644 --- a/AdyenActions/Components/3DS2/ThreeDS2ComponentFingerprint.swift +++ b/AdyenActions/Components/3DS2/ThreeDS2ComponentFingerprint.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 Adyen N.V. +// Copyright (c) 2019 Adyen N.V. // // This file is open source and available under the MIT license. See the LICENSE file for more info. // @@ -9,8 +9,8 @@ import Foundation internal extension ThreeDS2Component { - struct Fingerprint: Encodable { // swiftlint:disable:this explicit_acl - + struct Fingerprint: Encodable, Equatable { // swiftlint:disable:this explicit_acl + private let deviceInformation: String? private let sdkEphemeralPublicKey: EphemeralPublicKey? private let sdkReferenceNumber: String? @@ -55,7 +55,7 @@ internal extension ThreeDS2Component { extension ThreeDS2Component.Fingerprint { - internal struct EphemeralPublicKey: Codable { + internal struct EphemeralPublicKey: Codable, Equatable { private let keyType: String private let curve: String diff --git a/AdyenEncryption/Extensions/JSONEncoder+SortedKeys.swift.swift b/AdyenEncryption/Extensions/JSONEncoder+SortedKeys.swift.swift new file mode 100644 index 0000000000..5e17e207a3 --- /dev/null +++ b/AdyenEncryption/Extensions/JSONEncoder+SortedKeys.swift.swift @@ -0,0 +1,19 @@ +// +// JSONEncoder+Extensions.swift +// AdyenEncryption +// +// Created by Naufal Aros on 20/01/2025. +// Copyright © 2025 Adyen. All rights reserved. +// + +import Foundation + +extension JSONEncoder { + internal static func encodeWithSortedKeys(_ encodable: Encodable) throws -> Data { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .iso8601 + encoder.outputFormatting = .sortedKeys + + return try encoder.encode(encodable) + } +} diff --git a/AdyenEncryption/JOSE/Encryption Algorithms/JSON Web Encryption/JSONWebEncryptionGenerator.swift b/AdyenEncryption/JOSE/Encryption Algorithms/JSON Web Encryption/JSONWebEncryptionGenerator.swift index 756290a457..f3ada2bb19 100644 --- a/AdyenEncryption/JOSE/Encryption Algorithms/JSON Web Encryption/JSONWebEncryptionGenerator.swift +++ b/AdyenEncryption/JOSE/Encryption Algorithms/JSON Web Encryption/JSONWebEncryptionGenerator.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2023 Adyen N.V. +// Copyright (c) 2025 Adyen N.V. // // This file is open source and available under the MIT license. See the LICENSE file for more info. // @@ -22,8 +22,8 @@ internal struct JSONWebEncryptionGenerator: AnyJSONWebEncryptionGenerator { let contentEncryptionKey = try generateRandomData(length: contentEncryptionAlgorithm.keyLength) let encryptedKey = try keyEncryptionAlgorithm.encrypt(contentEncryptionKey, withKey: publicRSAKey) - let encodedHeader = try JSONEncoder().encode(header) - + let encodedHeader = try JSONEncoder.encodeWithSortedKeys(header) + let initializationVector = try generateRandomData(length: contentEncryptionAlgorithm.initializationVectorLength) guard let additionalAuthenticationData = encodedHeader.base64URLString().data(using: .ascii) else { throw EncryptionError.encryptionFailed diff --git a/AdyenEncryption/Payload/Payload.swift b/AdyenEncryption/Payload/Payload.swift index 088ac7b824..eae6bc3310 100644 --- a/AdyenEncryption/Payload/Payload.swift +++ b/AdyenEncryption/Payload/Payload.swift @@ -12,6 +12,6 @@ internal protocol Payload: Encodable { extension Payload { internal func jsonData() throws -> Data { - try JSONEncoder().encode(self) + try JSONEncoder.encodeWithSortedKeys(self) } } diff --git a/Demo/Common/Configuration/ConfigurationView.swift b/Demo/Common/Configuration/ConfigurationView.swift index 336205b918..fb372383ff 100644 --- a/Demo/Common/Configuration/ConfigurationView.swift +++ b/Demo/Common/Configuration/ConfigurationView.swift @@ -152,10 +152,10 @@ private struct ListItemView: View { }.tag(viewModel.tag) } - fileprivate struct ViewModel { + fileprivate struct ViewModel { let title: String let subtitle: String - let tag: T + let tag: U } } diff --git a/Demo/Common/Helpers/APIClientHelper.swift b/Demo/Common/Helpers/APIClientHelper.swift index dc3ae6c08c..c8132337ab 100644 --- a/Demo/Common/Helpers/APIClientHelper.swift +++ b/Demo/Common/Helpers/APIClientHelper.swift @@ -48,5 +48,5 @@ extension APIClientAware { } private enum AssociatedKeys { - internal static var apiClient = "apiClient" + internal static var apiClient: Void? } diff --git a/Scripts/carthage.sh b/Scripts/carthage.sh index 92d70d58f7..1c0ac240f5 100755 --- a/Scripts/carthage.sh +++ b/Scripts/carthage.sh @@ -31,4 +31,18 @@ export XCODE_XCCONFIG_FILE="$xcconfig" IS_STATIC_ARGUMENT="--static" ALL_ARGUMENTS="$@" ARGUMENTS=$(echo $ALL_ARGUMENTS | sed -e "s/$IS_STATIC_ARGUMENT//") -/usr/local/bin/carthage $ARGUMENTS + + +# Find the Carthage binary +CARTHAGE_PATH=$(which carthage) + +if [ -z "$CARTHAGE_PATH" ]; then + echo "Carthage is not installed or not in the PATH." + exit 1 +fi + +# Use the found Carthage binary to run commands +echo "Using Carthage located at: $CARTHAGE_PATH" + +# Example: Running Carthage update +"$CARTHAGE_PATH" $ARGUMENTS \ No newline at end of file diff --git a/Scripts/test-CocoaPods-integration.sh b/Scripts/test-CocoaPods-integration.sh index 7e837fc8ec..05a0308bdb 100755 --- a/Scripts/test-CocoaPods-integration.sh +++ b/Scripts/test-CocoaPods-integration.sh @@ -41,41 +41,43 @@ rm -rf $PROJECT_NAME mkdir -p $PROJECT_NAME && cd $PROJECT_NAME -# Create a new Xcode project. -swift package init - -# Create the Package.swift. -echo "// swift-tools-version:5.3 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription - -let package = Package( - name: \"TempProject\", - platforms: [ - .iOS(.v12) - ], - products: [ - .library( - name: \"TempProject\", - targets: [\"TempProject\"]), - ], - dependencies: [], - targets: [ - .target( - name: \"TempProject\", - dependencies: []), - .testTarget( - name: \"TempProjectTests\", - dependencies: [\"TempProject\"]), - ] -) - -" > Package.swift - -swift package update - -swift package generate-xcodeproj +echo " +name: $PROJECT_NAME +targets: + $PROJECT_NAME: + type: application + platform: iOS + sources: Source + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: com.adyen.$PROJECT_NAME + Tests: + type: bundle.ui-testing + platform: iOS + sources: Tests +schemes: + TempProject-Package: + build: + targets: + $PROJECT_NAME: all + Tests: [tests] + test: + targets: + - Tests +" > project.yml + +mkdir -p Source + +echo " +import Foundation +import Adyen +@main +class EmptyClass {static func main() {}} +" > Source/EmptyClass.swift + +mkdir -p Tests + +xcodegen generate # Create a Podfile with our pod as dependency. @@ -89,6 +91,16 @@ then pod 'Adyen', :path => '../' pod 'Adyen/SwiftUI', :path => '../' end + + post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = \"\" + config.build_settings['CODE_SIGNING_REQUIRED'] = \"NO\" + config.build_settings['CODE_SIGNING_ALLOWED'] = \"NO\" + end + end + end " >> Podfile else echo "platform :ios, '12.0' @@ -100,6 +112,16 @@ else pod 'Adyen/WeChatPay', :path => '../' pod 'Adyen/SwiftUI', :path => '../' end + + post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = \"\" + config.build_settings['CODE_SIGNING_REQUIRED'] = \"NO\" + config.build_settings['CODE_SIGNING_ALLOWED'] = \"NO\" + end + end + end " >> Podfile fi @@ -108,16 +130,16 @@ pod install # Archive for generic iOS device echo '############# Archive for generic iOS device ###############' -xcodebuild archive -scheme TempProject-Package -workspace TempProject.xcworkspace -destination 'generic/platform=iOS' +xcodebuild -quiet archive -scheme TempProject-Package -workspace TempProject.xcworkspace -destination 'generic/platform=iOS' CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO GENERATE_INFOPLIST_FILE=YES # Build for generic iOS device echo '############# Build for generic iOS device ###############' -xcodebuild clean build -scheme TempProject-Package -workspace TempProject.xcworkspace -destination 'generic/platform=iOS' +xcodebuild -quiet clean build -scheme TempProject-Package -workspace TempProject.xcworkspace -destination 'generic/platform=iOS' CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO GENERATE_INFOPLIST_FILE=YES # Archive for x86_64 simulator echo '############# Archive for simulator ###############' -xcodebuild archive -scheme TempProject-Package -workspace TempProject.xcworkspace -destination 'generic/platform=iOS Simulator' +xcodebuild -quiet archive -scheme TempProject-Package -workspace TempProject.xcworkspace -destination 'generic/platform=iOS Simulator' CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO GENERATE_INFOPLIST_FILE=YES # Build for x86_64 simulator echo '############# Build for simulator ###############' -xcodebuild clean build -scheme TempProject-Package -workspace TempProject.xcworkspace -destination 'generic/platform=iOS Simulator' +xcodebuild -quiet clean build -scheme TempProject-Package -workspace TempProject.xcworkspace -destination 'generic/platform=iOS Simulator' CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO GENERATE_INFOPLIST_FILE=YES \ No newline at end of file diff --git a/Scripts/test-carthage-integration.sh b/Scripts/test-carthage-integration.sh index 5f3f8be50e..0207168350 100755 --- a/Scripts/test-carthage-integration.sh +++ b/Scripts/test-carthage-integration.sh @@ -125,7 +125,7 @@ cp "../Demo/Configuration.swift" Source/Configuration.swift xcodegen generate echo_header "Run Tests" -xcodebuild build test -project $PROJECT_NAME.xcodeproj -scheme App -destination "name=iPhone 13" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO | xcpretty && exit ${PIPESTATUS[0]} +xcodebuild build test -project $PROJECT_NAME.xcodeproj -scheme App -destination "name=iPhone 16" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO | xcpretty && exit ${PIPESTATUS[0]} if [ "$NEED_CLEANUP" == true ] then diff --git a/Tests/AdyenTests/Adyen Tests/Utilities/CoderTests.swift b/Tests/AdyenTests/Adyen Tests/Utilities/CoderTests.swift index fba2e15c48..25e28c9662 100644 --- a/Tests/AdyenTests/Adyen Tests/Utilities/CoderTests.swift +++ b/Tests/AdyenTests/Adyen Tests/Utilities/CoderTests.swift @@ -27,31 +27,31 @@ class CoderTests: XCTestCase { XCTAssertEqual(sampleObject.date.description, "2015-02-28 21:30:00 +0000") XCTAssertEqual(sampleObject.nestedObject.nestedValue, "value") } - - func testEncodeToString() { - let encodedString = try! Coder.encode(sampleObject) as String - + + func testEncodeToString() throws { + let encodedString = try Coder.encode(sampleObject) as String + XCTAssertEqual(encodedString, sampleObjectRawString) } - - func testEncodeToData() { - let encodedData = try! Coder.encode(sampleObject) as Data + + func testEncodeToData() throws { + let encodedData = try Coder.encode(sampleObject) as Data let expectedData = sampleObjectRawString.data(using: .utf8) - + XCTAssertEqual(encodedData, expectedData) } - + // MARK: - Private - - private let sampleObjectRawString = "{\"nested\":{\"nestedValue\":\"value\"},\"string\":\"someString\",\"some_integer\":99,\"date\":\"2015-02-28T21:30:00Z\"}" - + + private let sampleObjectRawString = "{\"date\":\"2015-02-28T21:30:00Z\",\"nested\":{\"nestedValue\":\"value\"},\"some_integer\":99,\"string\":\"someString\"}" + private lazy var sampleObject: SampleObject = { let nestedObject = NestedObject(nestedValue: "value") let date = Date(timeIntervalSince1970: 1425159000) return SampleObject(string: "someString", integer: 99, date: date, nestedObject: nestedObject) }() - private struct SampleObject: Decodable, Encodable { + private struct SampleObject: Codable { var string: String var integer: Int var date: Date @@ -65,7 +65,7 @@ class CoderTests: XCTestCase { } } - private struct NestedObject: Decodable, Encodable { + private struct NestedObject: Codable { var nestedValue: String enum CodingKeys: String, CodingKey { diff --git a/Tests/AdyenTests/Card Tests/3DS2 Component/ThreeDS2ClassicActionHandlerTests.swift b/Tests/AdyenTests/Card Tests/3DS2 Component/ThreeDS2ClassicActionHandlerTests.swift index c5058096e3..04d38a78ac 100644 --- a/Tests/AdyenTests/Card Tests/3DS2 Component/ThreeDS2ClassicActionHandlerTests.swift +++ b/Tests/AdyenTests/Card Tests/3DS2 Component/ThreeDS2ClassicActionHandlerTests.swift @@ -44,7 +44,7 @@ class ThreeDS2ClassicActionHandlerTests: XCTestCase { func testWrappedComponent() { let sut = ThreeDS2ClassicActionHandler(apiContext: Dummy.context, appearanceConfiguration: ADYAppearanceConfiguration()) XCTAssertEqual(sut.wrappedComponent.apiContext.clientKey, Dummy.context.clientKey) - + XCTAssertEqual(sut.wrappedComponent.apiContext.environment.baseURL, Dummy.context.environment.baseURL) sut._isDropIn = false @@ -55,15 +55,15 @@ class ThreeDS2ClassicActionHandlerTests: XCTestCase { } func testFingerprintFlowSuccess() throws { - + let service = AnyADYServiceMock() service.authenticationRequestParameters = authenticationRequestParameters - + let fingerprint = try ThreeDS2Component.Fingerprint( authenticationRequestParameters: authenticationRequestParameters ) let expectedFingerprint = try Coder.encodeBase64(fingerprint) - + let resultExpectation = expectation(description: "Expect ThreeDS2ActionHandler completion closure to be called.") let sut = ThreeDS2ClassicActionHandler(apiContext: Dummy.context, service: service) sut.handle(fingerprintAction) { fingerprintResult in @@ -87,7 +87,7 @@ class ThreeDS2ClassicActionHandlerTests: XCTestCase { } resultExpectation.fulfill() } - + waitForExpectations(timeout: 2, handler: nil) } @@ -268,5 +268,4 @@ class ThreeDS2ClassicActionHandlerTests: XCTestCase { waitForExpectations(timeout: 2, handler: nil) } - } diff --git a/Tests/AdyenTests/Card Tests/CardComponentTests.swift b/Tests/AdyenTests/Card Tests/CardComponentTests.swift index e5dfd8a8a3..bf26c07e11 100644 --- a/Tests/AdyenTests/Card Tests/CardComponentTests.swift +++ b/Tests/AdyenTests/Card Tests/CardComponentTests.swift @@ -1101,9 +1101,9 @@ class CardComponentTests: XCTestCase { XCTAssertTrue(component === sut) let paymentDetails = data.paymentMethod as? CardDetails XCTAssertNotNil(paymentDetails) - + XCTAssertNotEqual(paymentDetails?.password, "12") - XCTAssertTrue(paymentDetails!.password!.starts(with: "eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiUlNBLU9BRVAtMjU2IiwidmVyc2lvbiI6IjEifQ")) + XCTAssertTrue(paymentDetails!.password!.starts(with: "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwidmVyc2lvbiI6IjEifQ")) XCTAssertEqual(paymentDetails?.taxNumber, "121212") sut.stopLoadingIfNeeded() diff --git a/Tests/AdyenTests/Card Tests/Utilities/CardEncryptorCardTests.swift b/Tests/AdyenTests/Card Tests/Utilities/CardEncryptorCardTests.swift index c6a501c1b7..0ad6358cfe 100644 --- a/Tests/AdyenTests/Card Tests/Utilities/CardEncryptorCardTests.swift +++ b/Tests/AdyenTests/Card Tests/Utilities/CardEncryptorCardTests.swift @@ -185,9 +185,8 @@ class CardEncryptorCardTests: XCTestCase { } } - func testEncryptBIN() { - let encrypted = try! CardEncryptor.encrypt(bin: "55000000", with: Dummy.publicKey) - XCTAssertNotNil(encrypted) - XCTAssertTrue(encrypted.hasPrefix("eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiUlNBLU9BRVAtMjU2IiwidmVyc2lvbiI6IjEifQ")) + func testEncryptBIN() throws { + let encrypted = try XCTUnwrap(CardEncryptor.encrypt(bin: "55000000", with: Dummy.publicKey)) + XCTAssertTrue(encrypted.hasPrefix("eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwidmVyc2lvbiI6IjEifQ")) } }