-
Notifications
You must be signed in to change notification settings - Fork 192
/
Copy pathRelayClientEndToEndTests.swift
162 lines (137 loc) · 6.19 KB
/
RelayClientEndToEndTests.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import Foundation
import Combine
import XCTest
import WalletConnectUtils
import Starscream
@testable import WalletConnectRelay
private class RelayKeychainStorageMock: KeychainStorageProtocol {
func add<T>(_ item: T, forKey key: String) throws where T : WalletConnectKMS.GenericPasswordConvertible {}
func read<T>(key: String) throws -> T where T : WalletConnectKMS.GenericPasswordConvertible {
return try T(rawRepresentation: Data())
}
func delete(key: String) throws {}
func deleteAll() throws {}
}
class WebSocketFactoryMock: WebSocketFactory {
private let webSocket: WebSocket
init(webSocket: WebSocket) {
self.webSocket = webSocket
}
func create(with url: URL) -> WebSocketConnecting {
return webSocket
}
}
final class RelayClientEndToEndTests: XCTestCase {
private var publishers = Set<AnyCancellable>()
func makeRelayClient(prefix: String) -> RelayClient {
let keyValueStorage = RuntimeKeyValueStorage()
let logger = ConsoleLogger(prefix: prefix, loggingLevel: .debug)
let clientIdStorage = ClientIdStorage(defaults: keyValueStorage, keychain: KeychainStorageMock(), logger: logger)
let socketAuthenticator = ClientIdAuthenticator(
clientIdStorage: clientIdStorage
)
let urlFactory = RelayUrlFactory(
relayHost: InputConfig.relayHost,
projectId: InputConfig.projectId,
socketAuthenticator: socketAuthenticator
)
let socket = WebSocket(url: urlFactory.create())
let webSocketFactory = WebSocketFactoryMock(webSocket: socket)
let networkMonitor = NetworkMonitor()
let relayUrlFactory = RelayUrlFactory(
relayHost: "relay.walletconnect.com",
projectId: "1012db890cf3cfb0c1cdc929add657ba",
socketAuthenticator: socketAuthenticator
)
let socketStatusProvider = SocketStatusProvider(socket: socket, logger: logger)
let socketConnectionHandler = AutomaticSocketConnectionHandler(socket: socket, subscriptionsTracker: SubscriptionsTracker(), logger: logger, socketStatusProvider: socketStatusProvider)
let dispatcher = Dispatcher(
socketFactory: webSocketFactory,
relayUrlFactory: urlFactory,
networkMonitor: networkMonitor,
socket: socket,
logger: logger,
socketConnectionHandler: socketConnectionHandler,
socketStatusProvider: socketStatusProvider
)
let keychain = KeychainStorageMock()
let relayClient = RelayClientFactory.create(
relayHost: InputConfig.relayHost,
projectId: InputConfig.projectId,
keyValueStorage: keyValueStorage,
keychainStorage: keychain,
socketFactory: DefaultSocketFactory(),
socketConnectionType: .manual,
networkMonitor: networkMonitor,
logger: logger
)
let clientId = try! relayClient.getClientId()
logger.debug("My client id is: \(clientId)")
return relayClient
}
func testSubscribe() {
let relayClient = makeRelayClient(prefix: "")
try! relayClient.connect()
let subscribeExpectation = expectation(description: "subscribe call succeeds")
subscribeExpectation.assertForOverFulfill = true
relayClient.socketConnectionStatusPublisher.sink { status in
if status == .connected {
Task(priority: .high) { try await relayClient.subscribe(topic: "ecb78f2df880c43d3418ddbf871092b847801932e21765b250cc50b9e96a9131") }
subscribeExpectation.fulfill()
}
}.store(in: &publishers)
wait(for: [subscribeExpectation], timeout: InputConfig.defaultTimeout)
}
func testEndToEndPayload() {
let relayA = makeRelayClient(prefix: "⚽️ A ")
let relayB = makeRelayClient(prefix: "🏀 B ")
try! relayA.connect()
try! relayB.connect()
let randomTopic = String.randomTopic()
let payloadA = "A"
let payloadB = "B"
var subscriptionATopic: String!
var subscriptionBTopic: String!
var subscriptionAPayload: String!
var subscriptionBPayload: String!
let expectationA = expectation(description: "publish payloads send and receive successfuly")
let expectationB = expectation(description: "publish payloads send and receive successfuly")
expectationA.assertForOverFulfill = false
expectationB.assertForOverFulfill = false
relayA.messagePublisher.sink { topic, payload, _, _ in
(subscriptionATopic, subscriptionAPayload) = (topic, payload)
expectationA.fulfill()
}.store(in: &publishers)
relayB.messagePublisher.sink { topic, payload, _, _ in
(subscriptionBTopic, subscriptionBPayload) = (topic, payload)
Task(priority: .high) {
sleep(1)
try await relayB.publish(topic: randomTopic, payload: payloadB, tag: 0, prompt: false, ttl: 60)
}
expectationB.fulfill()
}.store(in: &publishers)
relayA.socketConnectionStatusPublisher.sink { status in
guard status == .connected else {return}
Task(priority: .high) {
try await relayA.subscribe(topic: randomTopic)
try await relayA.publish(topic: randomTopic, payload: payloadA, tag: 0, prompt: false, ttl: 60)
}
}.store(in: &publishers)
relayB.socketConnectionStatusPublisher.sink { status in
guard status == .connected else {return}
Task(priority: .high) {
try await relayB.subscribe(topic: randomTopic)
}
}.store(in: &publishers)
wait(for: [expectationA, expectationB], timeout: InputConfig.defaultTimeout)
XCTAssertEqual(subscriptionATopic, randomTopic)
XCTAssertEqual(subscriptionBTopic, randomTopic)
XCTAssertEqual(subscriptionBPayload, payloadA)
XCTAssertEqual(subscriptionAPayload, payloadB)
}
}
extension String {
static func randomTopic() -> String {
"\(UUID().uuidString)\(UUID().uuidString)".replacingOccurrences(of: "-", with: "").lowercased()
}
}