diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Internal/StorefrontAPI/StorefrontAPIMutationsTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Internal/StorefrontAPI/StorefrontAPIMutationsTests.swift index cdace297..d79ea20b 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Internal/StorefrontAPI/StorefrontAPIMutationsTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Internal/StorefrontAPI/StorefrontAPIMutationsTests.swift @@ -43,11 +43,40 @@ final class StorefrontAPIMutationsTests: XCTestCase { // MARK: - Mock URLProtocol for Network Mocking class MockURLProtocol: URLProtocol { - static var mockResponseData: Data? - static var mockError: Error? - static var mockStatusCode: Int = 200 - static var capturedRequest: URLRequest? - static var capturedRequestBody: Data? + private struct State { + var mockResponseData: Data? + var mockError: Error? + var mockStatusCode = 200 + var capturedRequest: URLRequest? + var capturedRequestBody: Data? + } + + private static let state = LockedTestValue(State()) + + static var mockResponseData: Data? { + get { state.get().mockResponseData } + set { state.update { $0.mockResponseData = newValue } } + } + + static var mockError: Error? { + get { state.get().mockError } + set { state.update { $0.mockError = newValue } } + } + + static var mockStatusCode: Int { + get { state.get().mockStatusCode } + set { state.update { $0.mockStatusCode = newValue } } + } + + static var capturedRequest: URLRequest? { + get { state.get().capturedRequest } + set { state.update { $0.capturedRequest = newValue } } + } + + static var capturedRequestBody: Data? { + get { state.get().capturedRequestBody } + set { state.update { $0.capturedRequestBody = newValue } } + } override class func canInit(with _: URLRequest) -> Bool { return true diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Internal/StorefrontAPI/StorefrontAPIQueriesTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Internal/StorefrontAPI/StorefrontAPIQueriesTests.swift index 6a491572..272ee3a3 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Internal/StorefrontAPI/StorefrontAPIQueriesTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Internal/StorefrontAPI/StorefrontAPIQueriesTests.swift @@ -6,11 +6,40 @@ final class StorefrontAPIQueriesTests: XCTestCase { // MARK: - Mock URLProtocol for Network Mocking class MockURLProtocol: URLProtocol { - static var mockResponseData: Data? - static var mockError: Error? - static var mockStatusCode: Int = 200 - static var capturedRequest: URLRequest? - static var capturedRequestBody: Data? + private struct State { + var mockResponseData: Data? + var mockError: Error? + var mockStatusCode = 200 + var capturedRequest: URLRequest? + var capturedRequestBody: Data? + } + + private static let state = LockedTestValue(State()) + + static var mockResponseData: Data? { + get { state.get().mockResponseData } + set { state.update { $0.mockResponseData = newValue } } + } + + static var mockError: Error? { + get { state.get().mockError } + set { state.update { $0.mockError = newValue } } + } + + static var mockStatusCode: Int { + get { state.get().mockStatusCode } + set { state.update { $0.mockStatusCode = newValue } } + } + + static var capturedRequest: URLRequest? { + get { state.get().capturedRequest } + set { state.update { $0.capturedRequest = newValue } } + } + + static var capturedRequestBody: Data? { + get { state.get().capturedRequestBody } + set { state.update { $0.capturedRequestBody = newValue } } + } override class func canInit(with _: URLRequest) -> Bool { return true diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/LockedTestValue.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/LockedTestValue.swift new file mode 100644 index 00000000..7c245190 --- /dev/null +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/LockedTestValue.swift @@ -0,0 +1,21 @@ +@testable import ShopifyCheckoutKit + +final class LockedTestValue: Sendable { + private let value: LockedValue + + init(_ value: Value) { + self.value = LockedValue(value) + } + + func get() -> Value { + value.get() + } + + func set(_ newValue: Value) { + value.set(newValue) + } + + func update(_ block: (inout Value) -> Void) { + value.update(block) + } +} diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/ShopifyAcceleratedCheckoutsTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/ShopifyAcceleratedCheckoutsTests.swift index 946168b1..5e869bd4 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/ShopifyAcceleratedCheckoutsTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/ShopifyAcceleratedCheckoutsTests.swift @@ -4,6 +4,7 @@ import os.log import XCTest @available(iOS 17.0, *) +@MainActor class ShopifyAcceleratedCheckoutsTests: XCTestCase { var originalLogLevel: LogLevel! diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/TestHelpers.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/TestHelpers.swift index 115d6e6a..e3340661 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/TestHelpers.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/TestHelpers.swift @@ -6,6 +6,7 @@ import XCTest // MARK: - Configuration Helpers +@MainActor func XCTAssertThrowsErrorAsync( _ expression: @autoclosure () async throws -> some Any, _ errorHandler: (Error) -> Void, diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/AcceleratedCheckoutButtonsRenderStateTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/AcceleratedCheckoutButtonsRenderStateTests.swift index 9f2d6597..63442d7a 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/AcceleratedCheckoutButtonsRenderStateTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/AcceleratedCheckoutButtonsRenderStateTests.swift @@ -3,6 +3,7 @@ import SwiftUI import XCTest @available(iOS 17.0, *) +@MainActor final class AcceleratedCheckoutButtonsRenderStateTests: XCTestCase { // MARK: - Render State Change Callback Tests diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegateControllerTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegateControllerTests.swift index f44186c0..c79d1a02 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegateControllerTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegateControllerTests.swift @@ -612,12 +612,46 @@ final class ApplePayAuthorizationDelegateControllerTests: XCTestCase { "\"cost\":{\"totalAmount\":{\"amount\":\"0.00\",\"currencyCode\":\"USD\"}}," + "\"discountCodes\":[],\"discountAllocations\":[]}" - static var failReplace = false - static var failDeliveryUpdate = false - static var failPrepareForCompletion = false - static var returnMappableCartUserError = false - static var returnInvalidCart = false - static var lastOperation: String? + private struct State { + var failReplace = false + var failDeliveryUpdate = false + var failPrepareForCompletion = false + var returnMappableCartUserError = false + var returnInvalidCart = false + var lastOperation: String? + } + + private static let state = LockedTestValue(State()) + + static var failReplace: Bool { + get { state.get().failReplace } + set { state.update { $0.failReplace = newValue } } + } + + static var failDeliveryUpdate: Bool { + get { state.get().failDeliveryUpdate } + set { state.update { $0.failDeliveryUpdate = newValue } } + } + + static var failPrepareForCompletion: Bool { + get { state.get().failPrepareForCompletion } + set { state.update { $0.failPrepareForCompletion = newValue } } + } + + static var returnMappableCartUserError: Bool { + get { state.get().returnMappableCartUserError } + set { state.update { $0.returnMappableCartUserError = newValue } } + } + + static var returnInvalidCart: Bool { + get { state.get().returnInvalidCart } + set { state.update { $0.returnInvalidCart = newValue } } + } + + static var lastOperation: String? { + get { state.get().lastOperation } + set { state.update { $0.lastOperation = newValue } } + } static func response(for op: String) -> Data { if op == "cartPrepareForCompletion" { diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayCallbackTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayCallbackTests.swift index 44c41d5c..dc66d6d7 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayCallbackTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayCallbackTests.swift @@ -15,8 +15,8 @@ final class ApplePayCallbackTests: XCTestCase { // MARK: - Setup - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() // Create mock configuration let commonConfig = ShopifyAcceleratedCheckouts.Configuration( @@ -53,13 +53,13 @@ final class ApplePayCallbackTests: XCTestCase { ) } - override func tearDown() { + override func tearDown() async throws { viewController = nil mockConfiguration = nil mockIdentifier = nil errorExpectation = nil cancelExpectation = nil - super.tearDown() + try await super.tearDown() } // MARK: - Error Callback Tests diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayIntegrationTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayIntegrationTests.swift index 2267246d..3c268dd5 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayIntegrationTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayIntegrationTests.swift @@ -4,6 +4,7 @@ import SwiftUI import XCTest @available(iOS 17.0, *) +@MainActor final class ApplePayIntegrationTests: XCTestCase { // MARK: - Properties @@ -14,8 +15,8 @@ final class ApplePayIntegrationTests: XCTestCase { // MARK: - Setup - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() mockCommonConfiguration = ShopifyAcceleratedCheckouts.Configuration( storefrontDomain: "test-shop.myshopify.com", @@ -46,12 +47,12 @@ final class ApplePayIntegrationTests: XCTestCase { ) } - override func tearDown() { + override func tearDown() async throws { mockConfiguration = nil mockCommonConfiguration = nil mockApplePayConfiguration = nil mockShopSettings = nil - super.tearDown() + try await super.tearDown() } // MARK: - Integration Tests @@ -123,13 +124,13 @@ final class ApplePayIntegrationTests: XCTestCase { // The view should essentially be empty/minimal due to invariant case } - func testCallbackPersistenceAcrossViewUpdates() async { + func testCallbackPersistenceAcrossViewUpdates() { var failCount = 0 let failHandler = { (_: CheckoutError) in failCount += 1 } - let button = await ApplePayButton( + let button = ApplePayButton( identifier: .cart(cartID: "gid://Shopify/Cart/test-cart"), eventHandlers: EventHandlers(checkoutDidFail: failHandler), cornerRadius: nil diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewControllerTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewControllerTests.swift index f0026e95..42f50b11 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewControllerTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewControllerTests.swift @@ -11,8 +11,8 @@ class ApplePayViewControllerTests: XCTestCase { var mockStorefront: TestStorefrontAPI! var mockAuthorizationDelegate: MockApplePayAuthorizationDelegate! - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() // Create mock shop settings let paymentSettings = PaymentSettings( @@ -69,12 +69,12 @@ class ApplePayViewControllerTests: XCTestCase { viewController.setMockAuthorizationDelegate(mockAuthorizationDelegate) } - override func tearDown() { + override func tearDown() async throws { viewController = nil mockConfiguration = nil mockStorefront = nil mockAuthorizationDelegate = nil - super.tearDown() + try await super.tearDown() } class MockApplePayAuthorizationDelegate: ApplePayAuthorizationDelegate { diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewModifierTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewModifierTests.swift index bbcce4fd..f7236c36 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewModifierTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewModifierTests.swift @@ -4,6 +4,7 @@ import SwiftUI import XCTest @available(iOS 17.0, *) +@MainActor final class ApplePayViewModifierTests: XCTestCase { // MARK: - Properties @@ -13,8 +14,8 @@ final class ApplePayViewModifierTests: XCTestCase { // MARK: - Setup - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() mockConfiguration = ShopifyAcceleratedCheckouts.Configuration( storefrontDomain: "test-shop.myshopify.com", @@ -36,11 +37,11 @@ final class ApplePayViewModifierTests: XCTestCase { ) } - override func tearDown() { + override func tearDown() async throws { mockConfiguration = nil mockApplePayConfiguration = nil mockShopSettings = nil - super.tearDown() + try await super.tearDown() } // MARK: - onCancel Modifier Tests diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ShopPay/ShopPayCallbackTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ShopPay/ShopPayCallbackTests.swift index 2b3d56e1..8b6b0708 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ShopPay/ShopPayCallbackTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ShopPay/ShopPayCallbackTests.swift @@ -15,8 +15,8 @@ final class ShopPayCallbackTests: XCTestCase { // MARK: - Setup - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() mockConfiguration = ShopifyAcceleratedCheckouts.Configuration( storefrontDomain: "test-shop.myshopify.com", @@ -31,13 +31,13 @@ final class ShopPayCallbackTests: XCTestCase { ) } - override func tearDown() { + override func tearDown() async throws { viewController = nil mockConfiguration = nil mockIdentifier = nil errorExpectation = nil cancelExpectation = nil - super.tearDown() + try await super.tearDown() } // MARK: - Error Callback Tests diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ShopPay/ShopPayViewControllerTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ShopPay/ShopPayViewControllerTests.swift index da22fb07..b7b88ed3 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ShopPay/ShopPayViewControllerTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ShopPay/ShopPayViewControllerTests.swift @@ -9,8 +9,8 @@ final class ShopPayViewControllerTests: XCTestCase { var mockConfiguration: ShopifyAcceleratedCheckouts.Configuration! var mockStorefront: TestStorefrontAPI! - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() mockConfiguration = ShopifyAcceleratedCheckouts.Configuration( storefrontDomain: "test-shop.myshopify.com", @@ -19,11 +19,11 @@ final class ShopPayViewControllerTests: XCTestCase { mockStorefront = TestStorefrontAPI() } - override func tearDown() { + override func tearDown() async throws { viewController = nil mockConfiguration = nil mockStorefront = nil - super.tearDown() + try await super.tearDown() } @available(iOS 16.0, *) diff --git a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/WalletControllerTests.swift b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/WalletControllerTests.swift index cf98df31..448ad640 100644 --- a/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/WalletControllerTests.swift +++ b/platforms/swift/Tests/ShopifyAcceleratedCheckoutsTests/Wallets/WalletControllerTests.swift @@ -8,15 +8,15 @@ import XCTest final class WalletControllerTests: XCTestCase { var mockStorefront: TestStorefrontAPI! var controller: MockWalletController! - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() mockStorefront = TestStorefrontAPI() } - override func tearDown() { + override func tearDown() async throws { mockStorefront = nil controller = nil - super.tearDown() + try await super.tearDown() } class MockWalletController: WalletController { diff --git a/platforms/swift/Tests/ShopifyCheckoutKitTests/SwiftUITests.swift b/platforms/swift/Tests/ShopifyCheckoutKitTests/SwiftUITests.swift index a091378c..e8894b2e 100644 --- a/platforms/swift/Tests/ShopifyCheckoutKitTests/SwiftUITests.swift +++ b/platforms/swift/Tests/ShopifyCheckoutKitTests/SwiftUITests.swift @@ -6,8 +6,8 @@ class CheckoutViewControllerTests: XCTestCase { var checkoutURL: URL! var checkoutViewController: CheckoutViewController! - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() checkoutURL = URL(string: "https://www.shopify.com") checkoutViewController = CheckoutViewController(checkout: checkoutURL) } @@ -22,8 +22,8 @@ class ShopifyCheckoutTests: XCTestCase { var checkoutURL: URL! var shopifyCheckout: ShopifyCheckout! - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() checkoutURL = URL(string: "https://www.shopify.com") shopifyCheckout = ShopifyCheckout(checkout: checkoutURL) } @@ -65,8 +65,8 @@ class CheckoutConfigurableTests: XCTestCase { var checkoutURL: URL! var shopifyCheckout: ShopifyCheckout! - override func setUp() { - super.setUp() + override func setUp() async throws { + try await super.setUp() checkoutURL = URL(string: "https://www.shopify.com") shopifyCheckout = ShopifyCheckout(checkout: checkoutURL) }