diff --git a/Sources/ShopifyCheckout/CheckoutBridge.swift b/Sources/ShopifyCheckout/CheckoutBridge.swift index 61507817..72b637f6 100644 --- a/Sources/ShopifyCheckout/CheckoutBridge.swift +++ b/Sources/ShopifyCheckout/CheckoutBridge.swift @@ -57,6 +57,7 @@ extension CheckoutBridge { case checkoutComplete case checkoutExpired case checkoutUnavailable + case checkoutModalToggled(modalVisible: Bool) case unsupported(String) enum CodingKeys: String, CodingKey { @@ -75,6 +76,9 @@ extension CheckoutBridge { case "error": // needs to support .checkoutUnavailable by parsing error payload on body self = .checkoutExpired + case "checkoutBlockingEvent": + let modalVisible = try container.decode(String.self, forKey: .body) + self = .checkoutModalToggled(modalVisible: Bool(modalVisible)!) default: self = .unsupported(name) } diff --git a/Sources/ShopifyCheckout/CheckoutView.swift b/Sources/ShopifyCheckout/CheckoutView.swift index ae357a90..3a5dd4c1 100644 --- a/Sources/ShopifyCheckout/CheckoutView.swift +++ b/Sources/ShopifyCheckout/CheckoutView.swift @@ -30,6 +30,7 @@ protocol CheckoutViewDelegate: AnyObject { func checkoutViewDidFinishNavigation() func checkoutViewDidClickLink(url: URL) func checkoutViewDidFailWithError(error: CheckoutError) + func checkoutViewDidToggleModal(modalVisible: Bool) } class CheckoutView: WKWebView { @@ -104,6 +105,8 @@ extension CheckoutView: WKScriptMessageHandler { case .checkoutUnavailable: CheckoutView.cache = nil viewDelegate?.checkoutViewDidFailWithError(error: .checkoutUnavailable(message: "Checkout unavailable.")) + case let .checkoutModalToggled(modalVisible): + viewDelegate?.checkoutViewDidToggleModal(modalVisible: modalVisible) default: () } diff --git a/Sources/ShopifyCheckout/CheckoutViewController.swift b/Sources/ShopifyCheckout/CheckoutViewController.swift index fa132672..f1cd4e93 100644 --- a/Sources/ShopifyCheckout/CheckoutViewController.swift +++ b/Sources/ShopifyCheckout/CheckoutViewController.swift @@ -151,4 +151,9 @@ extension CheckoutViewController: CheckoutViewDelegate { func checkoutViewDidClickLink(url: URL) { delegate?.checkoutDidClickLink(url: url) } + + func checkoutViewDidToggleModal(modalVisible: Bool) { + guard let navigationController = self.navigationController else { return } + navigationController.setNavigationBarHidden(modalVisible, animated: true) + } } diff --git a/Tests/ShopifyCheckoutTests/CheckoutBridgeTests.swift b/Tests/ShopifyCheckoutTests/CheckoutBridgeTests.swift index e6a605d3..91eea5e9 100644 --- a/Tests/ShopifyCheckoutTests/CheckoutBridgeTests.swift +++ b/Tests/ShopifyCheckoutTests/CheckoutBridgeTests.swift @@ -97,4 +97,19 @@ class CheckoutBridgeTests: XCTestCase { return XCTFail("expected CheckoutScriptMessage.checkoutExpired, got \(result)") } } + + func testDecodeSupportsCheckoutBlockingEvent() throws { + let mock = WKScriptMessageMock(body: """ + { + "name": "checkoutBlockingEvent", + "body": "true" + } + """) + + let result = try CheckoutBridge.decode(mock) + + guard case CheckoutBridge.WebEvent.checkoutModalToggled = result else { + return XCTFail("expected CheckoutScriptMessage.checkoutModalToggled, got \(result)") + } + } } diff --git a/Tests/ShopifyCheckoutTests/CheckoutViewControllerTests.swift b/Tests/ShopifyCheckoutTests/CheckoutViewControllerTests.swift index 43605e90..d8141fa8 100644 --- a/Tests/ShopifyCheckoutTests/CheckoutViewControllerTests.swift +++ b/Tests/ShopifyCheckoutTests/CheckoutViewControllerTests.swift @@ -29,6 +29,7 @@ class CheckoutViewDelegateTests: XCTestCase { private let checkoutURL = URL(string: "https://checkout-sdk.myshopify.com")! private var viewController: CheckoutViewController! + private var navigationController: UINavigationController! override func setUp() { ShopifyCheckout.configure { @@ -36,6 +37,8 @@ class CheckoutViewDelegateTests: XCTestCase { } viewController = CheckoutViewController( checkoutURL: checkoutURL, delegate: ExampleDelegate()) + + navigationController = UINavigationController(rootViewController: viewController) } func testTitleIsSetToCheckout() { @@ -97,4 +100,14 @@ class CheckoutViewDelegateTests: XCTestCase { let three = CheckoutView.for(checkout: checkoutURL) XCTAssertEqual(two, three) } + + func testCheckoutViewDidToggleModalAddsAndRemovesNavigationBar() { + XCTAssertFalse(viewController.navigationController!.isNavigationBarHidden) + + viewController.checkoutViewDidToggleModal(modalVisible: true) + XCTAssertTrue(viewController.navigationController!.isNavigationBarHidden) + + viewController.checkoutViewDidToggleModal(modalVisible: false) + XCTAssertFalse(viewController.navigationController!.isNavigationBarHidden) + } } diff --git a/Tests/ShopifyCheckoutTests/Mocks/MockCheckoutViewDelegate.swift b/Tests/ShopifyCheckoutTests/Mocks/MockCheckoutViewDelegate.swift index 12da4a20..2cbb6293 100644 --- a/Tests/ShopifyCheckoutTests/Mocks/MockCheckoutViewDelegate.swift +++ b/Tests/ShopifyCheckoutTests/Mocks/MockCheckoutViewDelegate.swift @@ -37,6 +37,8 @@ class MockCheckoutViewDelegate: CheckoutViewDelegate { var didFailWithErrorExpectation: XCTestExpectation? + var didToggleModalExpectation: XCTestExpectation? + func checkoutViewDidStartNavigation() { didStartNavigationExpectation?.fulfill() } @@ -60,4 +62,8 @@ class MockCheckoutViewDelegate: CheckoutViewDelegate { func checkoutViewDidFailWithError(error: CheckoutError) { didFailWithErrorExpectation?.fulfill() } + + func checkoutViewDidToggleModal() { + didToggleModalExpectation?.fulfill() + } }