Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions platforms/swift/Sources/ShopifyCheckoutKit/CheckoutBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,24 @@ enum CheckoutBridge: CheckoutBridgeProtocol {
)
}

static var recoveryAgent: String {
return recoveryAgent(entryPoint: nil)
}

static func recoveryAgent(entryPoint: MetaData.EntryPoint?) -> String {
let colorScheme = ShopifyCheckoutKit.configuration.colorScheme
let platform = mapPlatform(ShopifyCheckoutKit.configuration.platform)

return UserAgent.string(
type: .recovery,
colorScheme: colorScheme,
platform: platform,
entryPoint: entryPoint
)
}
// Recovery mode disabled — not supported under UCP.
/*
static var recoveryAgent: String {
return recoveryAgent(entryPoint: nil)
}

static func recoveryAgent(entryPoint: MetaData.EntryPoint?) -> String {
let colorScheme = ShopifyCheckoutKit.configuration.colorScheme
let platform = mapPlatform(ShopifyCheckoutKit.configuration.platform)

return UserAgent.string(
type: .recovery,
colorScheme: colorScheme,
platform: platform,
entryPoint: entryPoint
)
}
*/

private static func mapPlatform(_ platform: Platform?) -> MetaData.Platform? {
guard let platform else { return nil }
Expand Down
46 changes: 25 additions & 21 deletions platforms/swift/Sources/ShopifyCheckoutKit/CheckoutWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ class CheckoutWebView: WKWebView {
static func `for`(checkout url: URL, recovery: Bool = false, entryPoint: MetaData.EntryPoint? = nil) -> CheckoutWebView {
OSLogger.shared.debug("Creating webview for URL: \(url.absoluteString), recovery: \(recovery)")

if recovery {
CheckoutWebView.invalidate()
return CheckoutWebView(recovery: true, entryPoint: entryPoint)
}
// Recovery mode disabled — not supported under UCP.
// if recovery {
// CheckoutWebView.invalidate()
// return CheckoutWebView(recovery: true, entryPoint: entryPoint)
// }

let cacheKey = "\(url.absoluteString)_\(entryPoint?.rawValue ?? "nil")"

Expand Down Expand Up @@ -134,14 +135,15 @@ class CheckoutWebView: WKWebView {
configuration.allowsInlineMediaPlayback = true
self.entryPoint = entryPoint

if recovery {
configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent()
configuration.applicationNameForUserAgent = CheckoutBridge.recoveryAgent(entryPoint: entryPoint)
} else {
configuration.applicationNameForUserAgent = CheckoutBridge.applicationName(entryPoint: entryPoint)
}
// Recovery mode disabled — not supported under UCP.
// if recovery {
// configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent()
// configuration.applicationNameForUserAgent = CheckoutBridge.recoveryAgent(entryPoint: entryPoint)
// } else {
configuration.applicationNameForUserAgent = CheckoutBridge.applicationName(entryPoint: entryPoint)
// }

isRecovery = recovery
// isRecovery = recovery
super.init(frame: frame, configuration: configuration)

#if DEBUG
Expand All @@ -156,21 +158,23 @@ class CheckoutWebView: WKWebView {

setBackgroundColor()

if recovery {
observeNavigationChanges()
} else {
connectBridge()
}
// Recovery mode disabled — not supported under UCP.
// if recovery {
// observeNavigationChanges()
// } else {
connectBridge()
// }
}

deinit {
OSLogger.shared.debug("De-allocating webview")

if isRecovery {
navigationObserver?.invalidate()
} else {
detachBridge()
}
// Recovery mode disabled — not supported under UCP.
// if isRecovery {
// navigationObserver?.invalidate()
// } else {
detachBridge()
// }
}

@available(*, unavailable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,38 +184,41 @@ class CheckoutWebViewController: UIViewController, UIAdaptivePresentationControl
onCancel?()
}

package func presentFallbackViewController(url: URL) {
progressObserver?.invalidate()
checkoutView.removeFromSuperview()

checkoutView = CheckoutWebView.for(checkout: url, recovery: true)
checkoutView.translatesAutoresizingMaskIntoConstraints = false
checkoutView.scrollView.contentInsetAdjustmentBehavior = .never
checkoutView.viewDelegate = self
checkoutView.alpha = 1

view.addSubview(checkoutView)
NSLayoutConstraint.activate([
checkoutView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
checkoutView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
checkoutView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
checkoutView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])

view.addSubview(progressBar)
progressBar.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
progressBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
progressBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
progressBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
progressBar.heightAnchor.constraint(equalToConstant: 1)
])
view.bringSubviewToFront(checkoutView)
view.bringSubviewToFront(progressBar)

observeProgressChanges(checkoutView)
checkoutView.load(checkout: url)
progressBar.startAnimating()
package func presentFallbackViewController(url _: URL) {
// Recovery mode disabled — not supported under UCP.
/*
progressObserver?.invalidate()
checkoutView.removeFromSuperview()

checkoutView = CheckoutWebView.for(checkout: url, recovery: true)
checkoutView.translatesAutoresizingMaskIntoConstraints = false
checkoutView.scrollView.contentInsetAdjustmentBehavior = .never
checkoutView.viewDelegate = self
checkoutView.alpha = 1

view.addSubview(checkoutView)
NSLayoutConstraint.activate([
checkoutView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
checkoutView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
checkoutView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
checkoutView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])

view.addSubview(progressBar)
progressBar.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
progressBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
progressBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
progressBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
progressBar.heightAnchor.constraint(equalToConstant: 1)
])
view.bringSubviewToFront(checkoutView)
view.bringSubviewToFront(progressBar)

observeProgressChanges(checkoutView)
checkoutView.load(checkout: url)
progressBar.startAnimating()
*/
}
}

Expand All @@ -235,16 +238,19 @@ extension CheckoutWebViewController: CheckoutWebViewDelegate {
CheckoutWebView.invalidate()
onFail?(error)

if shouldAttemptRecovery(for: error) {
presentFallbackViewController(url: checkoutURL)
} else {
dismiss(animated: true)
}
// Recovery mode disabled — not supported under UCP.
// if shouldAttemptRecovery(for: error) {
// presentFallbackViewController(url: checkoutURL)
// } else {
dismiss(animated: true)
// }
}

func shouldAttemptRecovery(for error: CheckoutError) -> Bool {
let isWithinRetryLimit = checkoutViewDidFailWithErrorCount < 2
return isRecoverableError() && isWithinRetryLimit && error.isRecoverable
func shouldAttemptRecovery(for _: CheckoutError) -> Bool {
// Recovery mode disabled — not supported under UCP.
return false
// let isWithinRetryLimit = checkoutViewDidFailWithErrorCount < 2
// return isRecoverableError() && isWithinRetryLimit && error.isRecoverable
}

func checkoutViewDidClickLink(url: URL) {
Expand All @@ -253,7 +259,8 @@ extension CheckoutWebViewController: CheckoutWebViewDelegate {
}
}

private func isRecoverableError() -> Bool {
return !CheckoutURL(from: checkoutURL).isMultipassURL()
}
// Recovery mode disabled — not supported under UCP.
// private func isRecoverableError() -> Bool {
// return !CheckoutURL(from: checkoutURL).isMultipassURL()
// }
}
8 changes: 5 additions & 3 deletions platforms/swift/Sources/ShopifyCheckoutKit/UserAgent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public enum UserAgent {

package enum CheckoutType {
case standard
case recovery
// Recovery mode disabled — not supported under UCP.
// case recovery
}

private static let baseUserAgent = "ShopifyCheckoutKit/\(MetaData.version)"
Expand All @@ -54,8 +55,9 @@ public enum UserAgent {
switch type {
case .standard:
parameters = "\(MetaData.schemaVersion);\(colorScheme.rawValue);standard"
case .recovery:
parameters = "noconnect;\(colorScheme.rawValue);standard_recovery"
// Recovery mode disabled — not supported under UCP.
// case .recovery:
// parameters = "noconnect;\(colorScheme.rawValue);standard_recovery"
}

var userAgentString = "\(baseUserAgent) (\(parameters))"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,31 @@ class CheckoutBridgeTests: XCTestCase {
XCTAssertEqual(CheckoutBridge.applicationName, "ShopifyCheckoutKit/\(version) (\(schemaVersion);automatic;standard)")
}

func testReturnsRecoveryUserAgent() {
let version = ShopifyCheckoutKit.version
XCTAssertEqual(CheckoutBridge.recoveryAgent, "ShopifyCheckoutKit/\(version) (noconnect;automatic;standard_recovery)")
func testReturnsRecoveryUserAgent() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
// let version = ShopifyCheckoutKit.version
// XCTAssertEqual(CheckoutBridge.recoveryAgent, "ShopifyCheckoutKit/\(version) (noconnect;automatic;standard_recovery)")
}

func testReturnsUserAgentWithCustomPlatformSuffix() {
let version = ShopifyCheckoutKit.version
let schemaVersion = MetaData.schemaVersion
ShopifyCheckoutKit.configuration.platform = Platform.reactNative
XCTAssertEqual(CheckoutBridge.applicationName, "ShopifyCheckoutKit/\(version) (\(schemaVersion);automatic;standard) ReactNative")
XCTAssertEqual(CheckoutBridge.recoveryAgent, "ShopifyCheckoutKit/\(version) (noconnect;automatic;standard_recovery) ReactNative")
// Recovery mode disabled — not supported under UCP.
// XCTAssertEqual(CheckoutBridge.recoveryAgent, "ShopifyCheckoutKit/\(version) (noconnect;automatic;standard_recovery) ReactNative")
ShopifyCheckoutKit.configuration.platform = nil
}

func testReturnsUserAgentWithEntryPoint() {
let version = ShopifyCheckoutKit.version
let schemaVersion = MetaData.schemaVersion
let applicationNameWithEntryPoint = CheckoutBridge.applicationName(entryPoint: .acceleratedCheckouts)
let recoveryAgentWithEntryPoint = CheckoutBridge.recoveryAgent(entryPoint: .acceleratedCheckouts)
// Recovery mode disabled — not supported under UCP.
// let recoveryAgentWithEntryPoint = CheckoutBridge.recoveryAgent(entryPoint: .acceleratedCheckouts)

XCTAssertEqual(applicationNameWithEntryPoint, "ShopifyCheckoutKit/\(version) (\(schemaVersion);automatic;standard) AcceleratedCheckouts")
XCTAssertEqual(recoveryAgentWithEntryPoint, "ShopifyCheckoutKit/\(version) (noconnect;automatic;standard_recovery) AcceleratedCheckouts")
// XCTAssertEqual(recoveryAgentWithEntryPoint, "ShopifyCheckoutKit/\(version) (noconnect;automatic;standard_recovery) AcceleratedCheckouts")
}

func testReturnsUserAgentWithEntryPointAndPlatform() {
Expand All @@ -62,10 +65,11 @@ class CheckoutBridgeTests: XCTestCase {
ShopifyCheckoutKit.configuration.platform = Platform.reactNative

let applicationNameWithEntryPoint = CheckoutBridge.applicationName(entryPoint: .acceleratedCheckouts)
let recoveryAgentWithEntryPoint = CheckoutBridge.recoveryAgent(entryPoint: .acceleratedCheckouts)
// Recovery mode disabled — not supported under UCP.
// let recoveryAgentWithEntryPoint = CheckoutBridge.recoveryAgent(entryPoint: .acceleratedCheckouts)

XCTAssertEqual(applicationNameWithEntryPoint, "ShopifyCheckoutKit/\(version) (\(schemaVersion);automatic;standard) ReactNative AcceleratedCheckouts")
XCTAssertEqual(recoveryAgentWithEntryPoint, "ShopifyCheckoutKit/\(version) (noconnect;automatic;standard_recovery) ReactNative AcceleratedCheckouts")
// XCTAssertEqual(recoveryAgentWithEntryPoint, "ShopifyCheckoutKit/\(version) (noconnect;automatic;standard_recovery) ReactNative AcceleratedCheckouts")

ShopifyCheckoutKit.configuration.platform = nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ class CheckoutViewDelegateTests: XCTestCase {
XCTAssertTrue(viewController.dismissCalled)
}

func testInstantiatesRecoveryWebviewOnRecoverableError() {
func testInstantiatesRecoveryWebviewOnRecoverableError() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
let view = CheckoutWebView.for(checkout: checkoutURL)

viewController.checkoutViewDidFailWithError(error: .checkoutUnavailable(message: "error", code: CheckoutUnavailable.httpError(statusCode: 500), recoverable: true))
Expand All @@ -86,7 +87,8 @@ class CheckoutViewDelegateTests: XCTestCase {
XCTAssertEqual(viewController.checkoutView.scrollView.contentInsetAdjustmentBehavior, .never)
}

func testDoesNotInstantiateRecoveryWebviewOnNonRecoverableError() {
func testDoesNotInstantiateRecoveryWebviewOnNonRecoverableError() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
_ = CheckoutWebView.for(checkout: checkoutURL)

viewController.checkoutViewDidFailWithError(error: .checkoutUnavailable(message: "error", code: CheckoutUnavailable.httpError(statusCode: 500), recoverable: false))
Expand All @@ -95,6 +97,7 @@ class CheckoutViewDelegateTests: XCTestCase {
}

func testDoesNotInstantiateRecoveryForMultipassURL() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
let controller = try MockCheckoutWebViewController(
checkoutURL: XCTUnwrap(URL(string: "https://checkout-sdk.myshopify.com/account/login/multipass/token"))
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ class CheckoutWebViewControllerTests: XCTestCase {
XCTAssertTrue(failCalled)
}

func test_checkoutViewDidFailWithError_attemptsRecoveryWhenRecoverable() {
func test_checkoutViewDidFailWithError_attemptsRecoveryWhenRecoverable() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
let viewController = TestableCheckoutWebViewController(checkoutURL: url, entryPoint: nil)

viewController.checkoutViewDidFailWithError(error: recoverableError)
Expand All @@ -92,7 +93,8 @@ class CheckoutWebViewControllerTests: XCTestCase {
XCTAssertFalse(viewController.dismissCalled)
}

func test_checkoutViewDidFailWithError_doesNotAttemptRecoveryWhenCountReachesTwo() {
func test_checkoutViewDidFailWithError_doesNotAttemptRecoveryWhenCountReachesTwo() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
let viewController = TestableCheckoutWebViewController(checkoutURL: url, entryPoint: nil)

viewController.checkoutViewDidFailWithError(error: recoverableError)
Expand All @@ -107,7 +109,8 @@ class CheckoutWebViewControllerTests: XCTestCase {
XCTAssertTrue(viewController.dismissAnimated)
}

func test_checkoutViewDidFailWithError_doesNotAttemptRecoveryWhenErrorIsNotRecoverable() {
func test_checkoutViewDidFailWithError_doesNotAttemptRecoveryWhenErrorIsNotRecoverable() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
let viewController = TestableCheckoutWebViewController(checkoutURL: url, entryPoint: nil)

viewController.checkoutViewDidFailWithError(error: nonRecoverableError)
Expand All @@ -118,7 +121,8 @@ class CheckoutWebViewControllerTests: XCTestCase {
XCTAssertFalse(viewController.presentFallbackViewControllerCalled)
}

func test_checkoutViewDidFailWithError_doesNotAttemptRecoveryForMultipassURL() {
func test_checkoutViewDidFailWithError_doesNotAttemptRecoveryForMultipassURL() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
let viewController = TestableCheckoutWebViewController(checkoutURL: multipassURL, entryPoint: nil)

viewController.checkoutViewDidFailWithError(error: recoverableError)
Expand All @@ -129,7 +133,8 @@ class CheckoutWebViewControllerTests: XCTestCase {
XCTAssertFalse(viewController.presentFallbackViewControllerCalled)
}

func test_checkoutViewDidFailWithError_attemptsRecoveryForFirstFailureThenDismisses() {
func test_checkoutViewDidFailWithError_attemptsRecoveryForFirstFailureThenDismisses() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
let viewController = TestableCheckoutWebViewController(checkoutURL: url, entryPoint: nil)

viewController.checkoutViewDidFailWithError(error: recoverableError)
Expand All @@ -146,7 +151,8 @@ class CheckoutWebViewControllerTests: XCTestCase {
XCTAssertTrue(viewController.dismissAnimated)
}

func test_checkoutViewDidFailWithError_respectsErrorRecoverableProperty() {
func test_checkoutViewDidFailWithError_respectsErrorRecoverableProperty() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
struct TestCase {
let name: String
let error: CheckoutError
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class CheckoutWebViewTests: XCTestCase {
XCTAssertTrue(view.configuration.allowsInlineMediaPlayback)
}

func testUsesRecoveryAgent() {
func testUsesRecoveryAgent() throws {
try XCTSkipIf(true, "Recovery mode disabled — not supported under UCP.")
let backgroundColor: UIColor = .systemRed
ShopifyCheckoutKit.configuration.backgroundColor = backgroundColor
ShopifyCheckoutKit.configuration.colorScheme = .automatic
Expand Down
Loading
Loading