Skip to content

Commit

Permalink
Merge pull request #24 from hotwired/fix-redirect-issue
Browse files Browse the repository at this point in the history
Get web view's URL at runtime
  • Loading branch information
joemasilotti authored Mar 1, 2024
2 parents e2e8a7c + b31d280 commit a44a86d
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 17 deletions.
15 changes: 7 additions & 8 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,23 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
on:
push:
branches:
- main
pull_request:

env:
XCODEBUILD_DESTINATION_IOS: 'platform=iOS Simulator,name=iPhone 14 Pro'

jobs:
build-and-test:
runs-on: macos-latest
runs-on: macos-13
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Select Xcode
run: sudo xcode-select -switch /Applications/Xcode_14.2.app && /usr/bin/xcodebuild -version
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable

- name: Run Tests
run: xcodebuild test -project Strada.xcodeproj -scheme Strada -destination "${{ env.XCODEBUILD_DESTINATION_IOS }}" -resultBundlePath TestResults
run: xcodebuild test -scheme Strada -destination "name=iPhone 15 Pro" | xcpretty && exit ${PIPESTATUS[0]}
15 changes: 9 additions & 6 deletions Source/BridgeDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,32 +75,32 @@ public final class BridgeDelegate: BridgingDelegate {
// MARK: - Destination lifecycle

public func onViewDidLoad() {
logger.debug("bridgeDestinationViewDidLoad: \(self.location)")
logger.debug("bridgeDestinationViewDidLoad: \(self.resolvedLocation)")
destinationIsActive = true
activeComponents.forEach { $0.viewDidLoad() }
}

public func onViewWillAppear() {
logger.debug("bridgeDestinationViewWillAppear: \(self.location)")
logger.debug("bridgeDestinationViewWillAppear: \(self.resolvedLocation)")
destinationIsActive = true
activeComponents.forEach { $0.viewWillAppear() }
}

public func onViewDidAppear() {
logger.debug("bridgeDestinationViewDidAppear: \(self.location)")
logger.debug("bridgeDestinationViewDidAppear: \(self.resolvedLocation)")
destinationIsActive = true
activeComponents.forEach { $0.viewDidAppear() }
}

public func onViewWillDisappear() {
activeComponents.forEach { $0.viewWillDisappear() }
logger.debug("bridgeDestinationViewWillDisappear: \(self.location)")
logger.debug("bridgeDestinationViewWillDisappear: \(self.resolvedLocation)")
}

public func onViewDidDisappear() {
activeComponents.forEach { $0.viewDidDisappear() }
destinationIsActive = false
logger.debug("bridgeDestinationViewDidDisappear: \(self.location)")
logger.debug("bridgeDestinationViewDidDisappear: \(self.resolvedLocation)")
}

// MARK: Retrieve component by type
Expand All @@ -125,7 +125,7 @@ public final class BridgeDelegate: BridgingDelegate {
@discardableResult
public func bridgeDidReceiveMessage(_ message: Message) -> Bool {
guard destinationIsActive,
location == message.metadata?.url else {
resolvedLocation == message.metadata?.url else {
logger.warning("bridgeDidIgnoreMessage: \(String(describing: message))")
return false
}
Expand All @@ -141,6 +141,9 @@ public final class BridgeDelegate: BridgingDelegate {
private var initializedComponents: [String: BridgeComponent] = [:]
private var destinationIsActive = false
private let componentTypes: [BridgeComponent.Type]
private var resolvedLocation: String {
webView?.url?.absoluteString ?? location
}

private var activeComponents: [BridgeComponent] {
return initializedComponents.values.filter { _ in destinationIsActive }
Expand Down
70 changes: 70 additions & 0 deletions Tests/BridgeDelegateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,55 @@ class BridgeDelegateTests: XCTestCase {
XCTAssertFalse(delegate.bridgeDidReceiveMessage(message))
}

// Web view URL takes precedence over the provided location.
func test_bridgeHandlesRedirectedWebViewURL() {
let redirectedLocation = "https://37signals.com/sign-in"
bridge.webView = RedirectedWebView(location: redirectedLocation)

let message = Message(id: "1",
component: "two",
event: "connect",
metadata: .init(url: redirectedLocation),
jsonData: json)

var component: BridgeComponentSpy? = delegate.component()

XCTAssertNil(component)
XCTAssertTrue(delegate.bridgeDidReceiveMessage(message))

component = delegate.component()

XCTAssertNotNil(component)
// Make sure the component has delegate set, and did receive the message.
XCTAssertTrue(component!.onReceiveMessageWasCalled)
XCTAssertEqual(component?.onReceiveMessageArg, message)
XCTAssertNotNil(component?.delegate)
}

// When web view URL is nil, the bride delegate falls back to the original location.
func test_bridgeFallsbackToOriginalDestination() {
bridge.webView = RedirectedWebView(location: nil)

let message = Message(id: "1",
component: "two",
event: "connect",
metadata: .init(url: "https://37signals.com"),
jsonData: json)

var component: BridgeComponentSpy? = delegate.component()

XCTAssertNil(component)
XCTAssertTrue(delegate.bridgeDidReceiveMessage(message))

component = delegate.component()

XCTAssertNotNil(component)
// Make sure the component has delegate set, and did receive the message.
XCTAssertTrue(component!.onReceiveMessageWasCalled)
XCTAssertEqual(component?.onReceiveMessageArg, message)
XCTAssertNotNil(component?.delegate)
}

func testBridgeIgnoresMessageForInactiveDestination() {
let message = Message(id: "1",
component: "one",
Expand Down Expand Up @@ -175,3 +224,24 @@ class BridgeDelegateTests: XCTestCase {
jsonData: json)
}
}

private final class RedirectedWebView: WKWebView {
init(location: String?) {
self.location = location
super.init(frame: .zero, configuration: WKWebViewConfiguration())
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override var url: URL? {
guard let location else { return nil }

return URL(string: location)
}

// MARK: Private

private let location: String?
}
15 changes: 12 additions & 3 deletions Tests/MessageTests.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import XCTest
import Strada
@testable import Strada

class MessageTests: XCTestCase {

Expand Down Expand Up @@ -184,7 +184,7 @@ class MessageTests: XCTestCase {

// MARK: Custom encoding

func test_encodingWithCustomEncoder() {
func test_encodingWithCustomEncoder() throws {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
Strada.config.jsonEncoder = encoder
Expand All @@ -204,6 +204,15 @@ class MessageTests: XCTestCase {

let newMessage = message.replacing(data: messageData)

XCTAssertEqual(message, newMessage)
XCTAssertEqual(message.id, newMessage.id)
XCTAssertEqual(message.event, newMessage.event)
XCTAssertEqual(message.metadata, newMessage.metadata)

// JSON as a string might have keys in a different order. Parse values to ensure equality.
let newMessageData = try XCTUnwrap(message.jsonData.jsonObject() as? [String: String])
XCTAssertEqual(newMessageData.keys.count, 3)
XCTAssertEqual(newMessageData["title"], "Page-title")
XCTAssertEqual(newMessageData["subtitle"], "Page-subtitle")
XCTAssertEqual(newMessageData["action_name"], "go")
}
}

0 comments on commit a44a86d

Please sign in to comment.