Skip to content

Commit

Permalink
improvement Enable library evolution (#1482)
Browse files Browse the repository at this point in the history
## Summary
- Adds default implementation for protocol `@_spi` properties
- Adds tests to guarantee `assertionFailure` on unimplemented protocol
conformance
- Fixes unrelated warnings
- Adds a [github
workflow](https://github.com/Adyen/adyen-ios/actions/workflows/test_library_evolution.yml)
that ensures the compatibility with `BUILD_LIBRARY_FOR_DISTRIBUTION=YES`

See: #1354
  • Loading branch information
goergisn authored Dec 5, 2023
2 parents ab72952 + f3bcdde commit 448f904
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 5 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/test_library_evolution.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: 📚 Library Evolution Compatibility

on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- develop

jobs:

build:
name: Verify
runs-on: macos-13-xl

steps:
- uses: actions/checkout@v4
- uses: n1hility/cancel-previous-runs@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Select latest Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '14.3'

- name: "xcodebuild clean archive BUILD_LIBRARY_FOR_DISTRIBUTION=YES"
run: |
xcodebuild -version
xcodebuild clean archive -project "${project}" -scheme "${scheme}" ${params} -destination "${destination}" | xcpretty --utf --color && exit ${PIPESTATUS[0]}
env:
project: 'Adyen.xcodeproj'
params: '-archivePath "archives/Adyen-iphoneos.xcarchive" -skipPackagePluginValidation SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES'
scheme: 'Adyen'
destination: 'generic/platform=iOS'
3 changes: 1 addition & 2 deletions Adyen/Core/APIClient/APIContext.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2022 Adyen N.V.
// Copyright (c) 2023 Adyen N.V.
//
// This file is open source and available under the MIT license. See the LICENSE file for more info.
//
Expand All @@ -11,7 +11,6 @@ import Foundation
public protocol AdyenContextAware: AnyObject {

/// The context object for this component.
@_spi(AdyenInternal)
var context: AdyenContext { get }
}

Expand Down
24 changes: 23 additions & 1 deletion Adyen/Core/Core Protocols/Details.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2022 Adyen N.V.
// Copyright (c) 2023 Adyen N.V.
//
// This file is open source and available under the MIT license. See the LICENSE file for more info.
//
Expand All @@ -16,5 +16,27 @@ public protocol PaymentMethodDetails: Details {
var checkoutAttemptId: String? { get set }
}

public extension PaymentMethodDetails {

/// This default implementation has to be provided to be able to build with `BUILD_LIBRARY_FOR_DISTRIBUTION` enabled
///
/// - Warning: Access will cause an failure in debug mode to assure the correct implementation of the `PaymentMethodDetails` protocol
@_spi(AdyenInternal)
var checkoutAttemptId: String? {
get {
AdyenAssertion.assertionFailure(
message: "`@_spi(AdyenInternal) var checkoutAttemptId: String?` needs to be provided on `\(String(describing: Self.self))`"
)

return "do-not-track"
}
set {
AdyenAssertion.assertionFailure(
message: "`@_spi(AdyenInternal) var checkoutAttemptId: String?` needs to be provided on `\(String(describing: Self.self))`"
)
}
}
}

/// Contains additional details that were retrieved to complete a payment.
public protocol AdditionalDetails: Details {}
17 changes: 16 additions & 1 deletion Adyen/Core/Core Protocols/PaymentMethod.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2022 Adyen N.V.
// Copyright (c) 2023 Adyen N.V.
//
// This file is open source and available under the MIT license. See the LICENSE file for more info.
//
Expand Down Expand Up @@ -30,6 +30,21 @@ public protocol PaymentMethod: Decodable {
func buildComponent(using builder: PaymentComponentBuilder) -> PaymentComponent?
}

public extension PaymentMethod {

/// This default implementation has to be provided to be able to build with `BUILD_LIBRARY_FOR_DISTRIBUTION` enabled
///
/// - Warning: Access will cause an failure in debug mode to assure the correct implementation of the `PaymentMethod` protocol
@_spi(AdyenInternal)
func buildComponent(using builder: PaymentComponentBuilder) -> PaymentComponent? {
AdyenAssertion.assertionFailure(
message: "`@_spi(AdyenInternal) \(#function)` needs to be implemented on `\(String(describing: Self.self))`"
)

return nil
}
}

/// A protocol to define any partial payment method such as gift cards, `MealVoucher` etc.
public protocol PartialPaymentMethod: PaymentMethod {}

Expand Down
29 changes: 29 additions & 0 deletions Tests/Adyen Tests/Core/PaymentMethodTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ class PaymentMethodTests: XCTestCase {

var paymentMethods: PaymentMethods!

override func tearDown() {
super.tearDown()
AdyenAssertion.listener = nil
}

override func setUpWithError() throws {
paymentMethods = try getPaymentMethods()
}
Expand Down Expand Up @@ -896,6 +901,30 @@ class PaymentMethodTests: XCTestCase {
XCTAssertEqual(paymentMethod.bankAccountNumber, "123456789")
}

// MARK: - PaymentMethodDetails

func testMissingImplementationPaymentMethodDetails() throws {

class DummyPaymentMethodDetails: PaymentMethodDetails {}

var dummy = DummyPaymentMethodDetails()

let expectation = expectation(description: "Access expectation")
expectation.expectedFulfillmentCount = 2

AdyenAssertion.listener = { assertion in
XCTAssertEqual(assertion, "`@_spi(AdyenInternal) var checkoutAttemptId: String?` needs to be provided on `DummyPaymentMethodDetails`")
expectation.fulfill()
}

// set
dummy.checkoutAttemptId = ""
// get
let _ = dummy.checkoutAttemptId

wait(for: [expectation], timeout: 1)
}

// MARK: - Accessibility

func testPaymentMethodTypeName() throws {
Expand Down
2 changes: 1 addition & 1 deletion Tests/Card Tests/CardComponentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ class CardComponentTests: XCTestCase {

let supportedCardLogosItemId = "AdyenCard.CardComponent.numberContainerItem.supportedCardLogosItem"

var supportedCardLogosItem: FormCardLogosItemView = try XCTUnwrap(sut.viewController.view.findView(with: supportedCardLogosItemId))
let supportedCardLogosItem: FormCardLogosItemView = try XCTUnwrap(sut.viewController.view.findView(with: supportedCardLogosItemId))
XCTAssertFalse(supportedCardLogosItem.isHidden)

// Valid input
Expand Down
35 changes: 35 additions & 0 deletions Tests/DropIn Tests/ComponentManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class ComponentManagerTests: XCTestCase {
}

override func tearDownWithError() throws {
AdyenAssertion.listener = nil
presentationDelegate = nil
context = nil
configuration = nil
Expand Down Expand Up @@ -464,6 +465,40 @@ class ComponentManagerTests: XCTestCase {
XCTAssertFalse(achComponent.configuration.showsBillingAddress)
XCTAssertEqual(achComponent.configuration.billingAddressCountryCodes, ["US", "UK"])
}

func testMissingImplementationBuildComponent() throws {

struct DummyPaymentMethod: PaymentMethod {
var type: PaymentMethodType = .achDirectDebit
var name: String = ""
var merchantProvidedDisplayInformation: MerchantCustomDisplayInformation? = nil

init() {}
init(from decoder: Decoder) throws {}
}

var dummy = DummyPaymentMethod()

let expectation = expectation(description: "Access expectation")
expectation.expectedFulfillmentCount = 1

AdyenAssertion.listener = { assertion in
XCTAssertEqual(assertion, "`@_spi(AdyenInternal) buildComponent(using:)` needs to be implemented on `DummyPaymentMethod`")
expectation.fulfill()
}

let componentManager = ComponentManager(
paymentMethods: .init(regular: [], stored: []),
context: Dummy.context,
configuration: .init(),
order: nil,
presentationDelegate: presentationDelegate
)

let _ = dummy.buildComponent(using: componentManager)

wait(for: [expectation], timeout: 1)
}

// MARK: - Private

Expand Down

0 comments on commit 448f904

Please sign in to comment.