From 64b17d7398ad16c693f89fd5fdd7cf2cefd8d593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C5=A0vara?= Date: Wed, 28 Feb 2024 11:17:20 +0100 Subject: [PATCH 1/2] Add all missing non async versions of `reply(to:,with:)`. --- Source/BridgeComponent.swift | 51 ++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/Source/BridgeComponent.swift b/Source/BridgeComponent.swift index 1351398..1e48c33 100644 --- a/Source/BridgeComponent.swift +++ b/Source/BridgeComponent.swift @@ -58,7 +58,10 @@ open class BridgeComponent: BridgingComponent { /// Replies to the web with a received message, optionally replacing its `event` or `jsonData`. /// - /// - Parameter message: The message to be replied with. + /// - Parameters: + /// - message: The message to be replied with. + /// - completion: An optional completion handler to be called when the reply attempt completes. + /// It includes a result indicating whether the reply was successful or not. public func reply(with message: Message, completion: ReplyCompletionHandler? = nil) { Task { do { @@ -90,7 +93,10 @@ open class BridgeComponent: BridgingComponent { /// /// NOTE: If a message has not been received for the given `event`, the reply will be ignored. /// - /// - Parameter event: The `event` for which a reply should be sent. + /// - Parameters: + /// - event: The `event` for which a reply should be sent. + /// - completion: An optional completion handler to be called when the reply attempt completes. + /// It includes a result indicating whether the reply was successful or not. public func reply(to event: String, completion: ReplyCompletionHandler? = nil) { Task { do { @@ -121,6 +127,26 @@ open class BridgeComponent: BridgingComponent { return try await reply(with: messageReply) } + /// Replies to the web with the last received message for a given `event`, replacing its `jsonData`. + /// + /// NOTE: If a message has not been received for the given `event`, the reply will be ignored. + /// + /// - Parameters: + /// - event: The `event` for which a reply should be sent. + /// - jsonData: The `jsonData` to be included in the reply message. + /// - completion: An optional completion handler to be called when the reply attempt completes. + /// It includes a result indicating whether the reply was successful or not. + public func reply(to event: String, with jsonData: String, completion: ReplyCompletionHandler? = nil) { + Task { + do { + let result = try await reply(to: event, with: jsonData) + completion?(.success((result))) + } catch { + completion?(.failure(error)) + } + } + } + @discardableResult /// Replies to the web with the last received message for a given `event`, replacing its `jsonData` /// with the provided `Encodable` object. @@ -141,6 +167,27 @@ open class BridgeComponent: BridgingComponent { return try await reply(with: messageReply) } + /// Replies to the web with the last received message for a given `event`, replacing its `jsonData` + /// with the provided `Encodable` object. + /// + /// NOTE: If a message has not been received for the given `event`, the reply will be ignored. + /// + /// - Parameters: + /// - event: The `event` for which a reply should be sent. + /// - data: An instance conforming to `Encodable` to be included as `jsonData` in the reply message. + /// - completion: An optional completion handler to be called when the reply attempt completes. + /// It includes a result indicating whether the reply was successful or not. + public func reply(to event: String, with data: T, completion: ReplyCompletionHandler? = nil) { + Task { + do { + let result = try await reply(to: event, with: data) + completion?(.success((result))) + } catch { + completion?(.failure(error)) + } + } + } + /// Returns the last received message for a given `event`, if available. /// - Parameter event: The event name. /// - Returns: The last received message, or nil. From 86ea6f5d77ff5211c46576ef8b8fb5cd96b61d05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C5=A0vara?= Date: Wed, 28 Feb 2024 11:18:40 +0100 Subject: [PATCH 2/2] Add tests for non async version of `reply(to:, with:)`.` --- Tests/BridgeComponentTests.swift | 76 ++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/Tests/BridgeComponentTests.swift b/Tests/BridgeComponentTests.swift index 0f77ed5..3460827 100644 --- a/Tests/BridgeComponentTests.swift +++ b/Tests/BridgeComponentTests.swift @@ -109,6 +109,82 @@ class BridgeComponentTest: XCTestCase { wait(for: [expectation], timeout: .expectationTimeout) } + + func test_replyToReceivedMessageWithACodableObjectSucceeds() { + let messageData = MessageData(title: "hey", subtitle: "", actionName: "tap") + let newJsonData = "{\"title\":\"hey\",\"subtitle\":\"\",\"actionName\":\"tap\"}" + let newMessage = message.replacing(jsonData: newJsonData) + let expectation = expectation(description: "Wait for completion.") + + component.reply(to: "connect", with: messageData) { [unowned self] result in + switch result { + case .success(let success): + XCTAssertTrue(success) + XCTAssertTrue(delegate.replyWithMessageWasCalled) + XCTAssertEqual(delegate.replyWithMessageArg, newMessage) + case .failure(let error): + XCTFail("Failed with error: \(error)") + } + expectation.fulfill() + } + + wait(for: [expectation], timeout: .expectationTimeout) + } + + func test_replyToMessageNotReceivedWithACodableObjectIgnoresTheReply() { + let messageData = MessageData(title: "hey", subtitle: "", actionName: "tap") + let expectation = expectation(description: "Wait for completion.") + + component.reply(to: "disconnect", with: messageData) { [unowned self] result in + switch result { + case .success(let success): + XCTAssertFalse(success) + XCTAssertFalse(delegate.replyWithMessageWasCalled) + XCTAssertNil(delegate.replyWithMessageArg) + case .failure(let error): + XCTFail("Failed with error: \(error)") + } + expectation.fulfill() + } + + wait(for: [expectation], timeout: .expectationTimeout) + } + + func test_replyToMessageNotReceivedIgnoresTheReply() { + let expectation = expectation(description: "Wait for completion.") + + component.reply(to: "disconnect") { [unowned self] result in + switch result { + case .success(let success): + XCTAssertFalse(success) + XCTAssertFalse(delegate.replyWithMessageWasCalled) + XCTAssertNil(delegate.replyWithMessageArg) + case .failure(let error): + XCTFail("Failed with error: \(error)") + } + expectation.fulfill() + } + + wait(for: [expectation], timeout: .expectationTimeout) + } + + func test_replyToMessageNotReceivedWithJsonDataIgnoresTheReply() { + let expectation = expectation(description: "Wait for completion.") + + component.reply(to: "disconnect", with: "{\"title\":\"Page-title\"}") { [unowned self] result in + switch result { + case .success(let success): + XCTAssertFalse(success) + XCTAssertFalse(delegate.replyWithMessageWasCalled) + XCTAssertNil(delegate.replyWithMessageArg) + case .failure(let error): + XCTFail("Failed with error: \(error)") + } + expectation.fulfill() + } + + wait(for: [expectation], timeout: .expectationTimeout) + } // MARK: reply(with:)