Report errors in SocketData to users. Resolves #677

This commit is contained in:
Erik 2017-05-07 14:40:39 -04:00
parent 8e25c6c417
commit dd2167a09f
No known key found for this signature in database
GPG Key ID: 4930B7C5FBC1A69D
3 changed files with 72 additions and 5 deletions

View File

@ -254,6 +254,48 @@ class SocketSideEffectTest: XCTestCase {
waitForExpectations(timeout: 2) waitForExpectations(timeout: 2)
} }
func testErrorInCustomSocketDataCallsErrorHandler() {
let expect = expectation(description: "The client should call the error handler for emit errors because of " +
"custom data")
socket.on(clientEvent: .error) {data, ack in
guard data.count == 3, data[0] as? String == "myEvent",
data[2] is ThrowingData.ThrowingError else {
XCTFail("Incorrect error call")
return
}
expect.fulfill()
}
socket.emit("myEvent", ThrowingData())
waitForExpectations(timeout: 0.2)
}
func testErrorInCustomSocketDataCallsErrorHandler_ack() {
let expect = expectation(description: "The client should call the error handler for emit errors because of " +
"custom data")
socket.on(clientEvent: .error) {data, ack in
guard data.count == 3, data[0] as? String == "myEvent",
data[2] is ThrowingData.ThrowingError else {
XCTFail("Incorrect error call")
return
}
expect.fulfill()
}
socket.emitWithAck("myEvent", ThrowingData()).timingOut(after: 1, callback: {_ in
XCTFail("Ack callback should not be called")
})
waitForExpectations(timeout: 0.2)
}
let data = "test".data(using: String.Encoding.utf8)! let data = "test".data(using: String.Encoding.utf8)!
let data2 = "test2".data(using: String.Encoding.utf8)! let data2 = "test2".data(using: String.Encoding.utf8)!
private var socket: SocketIOClient! private var socket: SocketIOClient!
@ -264,3 +306,14 @@ class SocketSideEffectTest: XCTestCase {
socket.setTestable() socket.setTestable()
} }
} }
struct ThrowingData : SocketData {
enum ThrowingError : Error {
case error
}
func socketRepresentation() throws -> SocketData {
throw ThrowingError.error
}
}

View File

@ -98,7 +98,7 @@ public final class OnAckCallback : NSObject {
/// - parameter callback: The callback called when an ack is received, or when a timeout happens. /// - parameter callback: The callback called when an ack is received, or when a timeout happens.
/// To check for timeout, use `SocketAckStatus`'s `noAck` case. /// To check for timeout, use `SocketAckStatus`'s `noAck` case.
public func timingOut(after seconds: Int, callback: @escaping AckCallback) { public func timingOut(after seconds: Int, callback: @escaping AckCallback) {
guard let socket = self.socket else { return } guard let socket = self.socket, ackNumber != -1 else { return }
socket.ackHandlers.addAck(ackNumber, callback: callback) socket.ackHandlers.addAck(ackNumber, callback: callback)
socket._emit(items, ack: ackNumber) socket._emit(items, ack: ackNumber)

View File

@ -230,13 +230,19 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
/// Send an event to the server, with optional data items. /// Send an event to the server, with optional data items.
/// ///
/// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error`
/// will be emitted. The structure of the error data is `[eventName, items, theError]`
///
/// - parameter event: The event to send. /// - parameter event: The event to send.
/// - parameter items: The items to send with this event. May be left out. /// - parameter items: The items to send with this event. May be left out.
open func emit(_ event: String, _ items: SocketData...) { open func emit(_ event: String, _ items: SocketData...) {
do { do {
emit(event, with: try items.map({ try $0.socketRepresentation() })) emit(event, with: try items.map({ try $0.socketRepresentation() }))
} catch { } catch let err {
fatalError("Error creating socketRepresentation for emit: \(event), \(items)") DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
type: logType)
handleClientEvent(.error, data: [event, items, err])
} }
} }
@ -258,6 +264,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
/// **NOTE**: It is up to the server send an ack back, just calling this method does not mean the server will ack. /// **NOTE**: It is up to the server send an ack back, just calling this method does not mean the server will ack.
/// Check that your server's api will ack the event being sent. /// Check that your server's api will ack the event being sent.
/// ///
/// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error`
/// will be emitted. The structure of the error data is `[eventName, items, theError]`
///
/// Example: /// Example:
/// ///
/// ```swift /// ```swift
@ -272,8 +281,13 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback { open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback {
do { do {
return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() })) return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() }))
} catch { } catch let err {
fatalError("Error creating socketRepresentation for emit: \(event), \(items)") DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
type: logType)
handleClientEvent(.error, data: [event, items, err])
return OnAckCallback(ackNumber: -1, items: [], socket: self)
} }
} }