Skip to content

Commit e3a1a13

Browse files
test: Adds subscription init failure test
1 parent 1cdb507 commit e3a1a13

1 file changed

Lines changed: 101 additions & 0 deletions

File tree

Tests/GraphQLVaporTests/WebSocketTests.swift

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,107 @@ struct WebSocketTests {
8888
}
8989
}
9090

91+
@Test func subscriptionWithInitPayloadError() async throws {
92+
try await withApp { app in
93+
let pubsub = SimplePubSub<String>()
94+
let schema = try GraphQLSchema(
95+
subscription: GraphQLObjectType(
96+
name: "Subscription",
97+
fields: [
98+
"hello": GraphQLField(
99+
type: GraphQLString,
100+
resolve: { source, _, _, _ in
101+
source as! String
102+
},
103+
subscribe: { _, _, _, _ in
104+
await pubsub.subscribe()
105+
}
106+
),
107+
]
108+
)
109+
)
110+
111+
struct InitPayload: Equatable, Codable, Sendable {
112+
let code: String
113+
}
114+
let acceptedCode = "abc"
115+
116+
app.graphql(
117+
schema: schema,
118+
config: .init(
119+
subscriptionProtocols: [.websocket],
120+
websocket: .init(
121+
onWebSocketInit: { (initPayload: InitPayload, _) in
122+
initPayload.code == acceptedCode
123+
}
124+
)
125+
)
126+
) { inputs in
127+
// If the codes don't match, this will fail on the subscribe/execute request
128+
guard let codeIsValid = inputs.websocketInitResult, codeIsValid else {
129+
throw GraphQLError(message: "Unauthorized")
130+
}
131+
return EmptyContext()
132+
}
133+
134+
app.http.server.configuration.port = 0
135+
app.environment.arguments = ["serve"]
136+
try await app.startup()
137+
let port = try #require(app.http.server.shared.localAddress?.port)
138+
try await WebSocket.connect(
139+
to: "ws://localhost:\(port)/graphql",
140+
headers: ["Connection": "Upgrade"],
141+
on: MultiThreadedEventLoopGroup(numberOfThreads: 1)
142+
) { websocket in
143+
let decoder = JSONDecoder()
144+
websocket.onText { websocket, message in
145+
do {
146+
#expect(!message.starts(with: "44"))
147+
let response = try #require(message.data(using: .utf8))
148+
if let _ = try? decoder.decode(GraphQLTransportWS.ConnectionAckResponse.self, from: response) {
149+
try await websocket.send(#"""
150+
{
151+
"type": "subscribe",
152+
"payload": {
153+
"query": "subscription { hello }"
154+
},
155+
"id": "1"
156+
}
157+
"""#)
158+
// Must wait for a few milliseconds for the subscription to get set up.
159+
try await Task.sleep(for: .milliseconds(10))
160+
await pubsub.emit(event: "World")
161+
} else if let _ = try? decoder.decode(GraphQLTransportWS.NextResponse.self, from: response) {
162+
Issue.record("Expected Error: \(message)")
163+
await pubsub.cancel()
164+
} else if let _ = try? decoder.decode(GraphQLTransportWS.CompleteResponse.self, from: response) {
165+
Issue.record("Expected Error: \(message)")
166+
try await websocket.close()
167+
} else if let errorResult = try? decoder.decode(GraphQLTransportWS.ErrorResponse.self, from: response) {
168+
#expect(errorResult.payload[0].message == "Unauthorized")
169+
await pubsub.cancel()
170+
try await websocket.close()
171+
} else {
172+
Issue.record("Unrecognized message: \(message)")
173+
return
174+
}
175+
} catch {
176+
Issue.record("WebSocket error: \(error)")
177+
return
178+
}
179+
}
180+
do {
181+
// Send incorrect code, expect an "Unauthorized" error on the subscribe call
182+
try await websocket.send(#"{"type": "connection_init", "payload": {"code": "def"}}"#)
183+
try await websocket.onClose.get()
184+
} catch {
185+
Issue.record("WebSocket error: \(error)")
186+
return
187+
}
188+
}
189+
}
190+
}
191+
91192
@Test func subscription_GraphQLWS() async throws {
92193
try await withApp { app in
93194
let pubsub = SimplePubSub<String>()

0 commit comments

Comments
 (0)