Skip to content

Commit 4ebf243

Browse files
authored
fix: use IssueReporting (#826)
* fix: use IssueReporting * drop test * fix: disable reportIssue in tests * test: revert broadcast with HTTP test
1 parent de8419e commit 4ebf243

File tree

4 files changed

+53
-43
lines changed

4 files changed

+53
-43
lines changed

Sources/Auth/AuthClient.swift

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ConcurrencyExtras
22
import Foundation
3+
import IssueReporting
34

45
#if canImport(AuthenticationServices)
56
import AuthenticationServices
@@ -1410,17 +1411,21 @@ public actor AuthClient {
14101411
let session = try? await session
14111412
eventEmitter.emit(.initialSession, session: session, token: token)
14121413

1413-
logger?.warning(
1414-
"""
1415-
Initial session emitted after attempting to refresh the local stored session.
1416-
This is incorrect behavior and will be fixed in the next major release since it’s a breaking change.
1417-
For now, if you want to opt-in to the new behavior, add the trait `EmitLocalSessionAsInitialSession` to your Package.swift file when importing the Supabase dependency.
1418-
The new behavior ensures that the locally stored session is always emitted, regardless of its validity or expiration.
1419-
If you rely on the initial session to opt users in, you need to add an additional check for `session.isExpired` in the session.
1420-
1421-
Check https://github.com/supabase/supabase-swift/pull/822 for more information.
1422-
"""
1423-
)
1414+
// Properly expecting issues during tests isn't working as expected, I think because the reportIssue is usually triggered inside an unstructured Task
1415+
// because of this I'm disabling issue reporting during tests, so we can use it only for advising developers when running their applications.
1416+
if !isTesting {
1417+
reportIssue(
1418+
"""
1419+
Initial session emitted after attempting to refresh the local stored session.
1420+
This is incorrect behavior and will be fixed in the next major release since it’s a breaking change.
1421+
For now, if you want to opt-in to the new behavior, add the trait `EmitLocalSessionAsInitialSession` to your Package.swift file when importing the Supabase dependency.
1422+
The new behavior ensures that the locally stored session is always emitted, regardless of its validity or expiration.
1423+
If you rely on the initial session to opt users in, you need to add an additional check for `session.isExpired` in the session.
1424+
1425+
Check https://github.com/supabase/supabase-swift/pull/822 for more information.
1426+
"""
1427+
)
1428+
}
14241429
#endif
14251430
}
14261431

Sources/Helpers/Codable.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import ConcurrencyExtras
99
import Foundation
10+
import XCTestDynamicOverlay
1011

1112
extension JSONDecoder {
1213
/// Default `JSONDecoder` for decoding types from Supabase.
@@ -21,7 +22,8 @@ extension JSONDecoder {
2122
}
2223

2324
throw DecodingError.dataCorruptedError(
24-
in: container, debugDescription: "Invalid date format: \(string)"
25+
in: container,
26+
debugDescription: "Invalid date format: \(string)"
2527
)
2628
}
2729
return decoder
@@ -36,6 +38,13 @@ extension JSONEncoder {
3638
let string = date.iso8601String
3739
try container.encode(string)
3840
}
41+
42+
#if DEBUG
43+
if isTesting {
44+
encoder.outputFormatting = [.sortedKeys]
45+
}
46+
#endif
47+
3948
return encoder
4049
}
4150
}

Sources/Realtime/RealtimeChannelV2.swift

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ public final class RealtimeChannelV2: Sendable, RealtimeChannelProtocol {
295295
}
296296
headers[.authorization] = "Bearer \(accessToken)"
297297

298-
let body = try await JSONEncoder().encode(
298+
let body = try await JSONEncoder.supabase().encode(
299299
BroadcastMessagePayload(
300300
messages: [
301301
BroadcastMessagePayload.Message(
@@ -315,7 +315,8 @@ public final class RealtimeChannelV2: Sendable, RealtimeChannelProtocol {
315315
body: body
316316
)
317317

318-
let response = try await withTimeout(interval: timeout ?? socket.options.timeoutInterval) { [self] in
318+
let response = try await withTimeout(interval: timeout ?? socket.options.timeoutInterval) {
319+
[self] in
319320
await Result {
320321
try await socket.http.send(request)
321322
}
@@ -346,11 +347,17 @@ public final class RealtimeChannelV2: Sendable, RealtimeChannelProtocol {
346347
@MainActor
347348
public func broadcast(event: String, message: JSONObject) async {
348349
if status != .subscribed {
349-
logger?.warning(
350-
"Realtime broadcast() is automatically falling back to REST API. "
351-
+ "This behavior will be deprecated in the future. "
352-
+ "Please use httpSend() explicitly for REST delivery."
353-
)
350+
// Properly expecting issues during tests isn't working as expected, I think because the reportIssue is usually triggered inside an unstructured Task
351+
// because of this I'm disabling issue reporting during tests, so we can use it only for advising developers when running their applications.
352+
if !isTesting {
353+
reportIssue(
354+
"""
355+
Realtime broadcast() is automatically falling back to REST API.
356+
This behavior will be deprecated in the future.
357+
Please use httpSend() explicitly for REST delivery.
358+
"""
359+
)
360+
}
354361

355362
var headers: HTTPFields = [.contentType: "application/json"]
356363
if let apiKey = socket.options.apikey {
@@ -366,7 +373,7 @@ public final class RealtimeChannelV2: Sendable, RealtimeChannelProtocol {
366373
url: socket.broadcastURL,
367374
method: .post,
368375
headers: headers,
369-
body: JSONEncoder().encode(
376+
body: JSONEncoder.supabase().encode(
370377
BroadcastMessagePayload(
371378
messages: [
372379
BroadcastMessagePayload.Message(
@@ -751,4 +758,3 @@ public final class RealtimeChannelV2: Sendable, RealtimeChannelProtocol {
751758
push?.didReceive(status: PushStatus(rawValue: status) ?? .ok)
752759
}
753760
}
754-

Tests/RealtimeTests/RealtimeTests.swift

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ final class RealtimeTests: XCTestCase {
241241

242242
// Wait for the timeout for rejoining.
243243
await testClock.advance(by: .seconds(timeoutInterval))
244-
244+
245245
// Wait for the retry delay (base delay is 1.0s, but we need to account for jitter)
246246
// The retry delay is calculated as: baseDelay * pow(2, attempt-1) + jitter
247247
// For attempt 2: 1.0 * pow(2, 1) = 2.0s + jitter (up to ±25% = ±0.5s)
@@ -443,7 +443,7 @@ final class RealtimeTests: XCTestCase {
443443

444444
await testClock.advance(by: .seconds(timeoutInterval))
445445
subscribeTask.cancel()
446-
446+
447447
do {
448448
try await subscribeTask.value
449449
XCTFail("Expected cancellation error but got success")
@@ -597,26 +597,16 @@ final class RealtimeTests: XCTestCase {
597597
try await channel.broadcast(event: "test", message: ["value": 42])
598598

599599
let request = await http.receivedRequests.last
600-
assertInlineSnapshot(of: request?.urlRequest, as: .raw(pretty: true)) {
601-
"""
602-
POST http://localhost:54321/realtime/v1/api/broadcast
603-
Authorization: Bearer custom.access.token
604-
Content-Type: application/json
605-
apiKey: anon.api.key
606-
607-
{
608-
"messages" : [
609-
{
610-
"event" : "test",
611-
"payload" : {
612-
"value" : 42
613-
},
614-
"private" : false,
615-
"topic" : "realtime:public:messages"
616-
}
617-
]
618-
}
619-
"""
600+
assertInlineSnapshot(of: request?.urlRequest, as: .curl) {
601+
#"""
602+
curl \
603+
--request POST \
604+
--header "Authorization: Bearer custom.access.token" \
605+
--header "Content-Type: application/json" \
606+
--header "apiKey: anon.api.key" \
607+
--data "{\"messages\":[{\"event\":\"test\",\"payload\":{\"value\":42},\"private\":false,\"topic\":\"realtime:public:messages\"}]}" \
608+
"http://localhost:54321/realtime/v1/api/broadcast"
609+
"""#
620610
}
621611
}
622612

0 commit comments

Comments
 (0)