Skip to content

Commit dbeda88

Browse files
authored
Fix race between local updates and setting up API request waiting in send message tests in Chat (#3887)
1 parent 3adc76b commit dbeda88

2 files changed

Lines changed: 37 additions & 38 deletions

File tree

Sources/StreamChat/StateLayer/Chat.swift

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,9 @@ public class Chat {
406406
/// - Returns: An instance of `ChatMessage` which was resent.
407407
@discardableResult public func resendMessage(_ messageId: MessageId) async throws -> ChatMessage {
408408
let messageSender = try client.backgroundWorker(of: MessageSender.self)
409+
async let resentMessage = try await messageSender.waitForAPIRequest(messageId: messageId)
409410
try await messageUpdater.resendMessage(with: messageId)
410-
return try await messageSender.waitForAPIRequest(messageId: messageId)
411+
return try await resentMessage
411412
}
412413

413414
/// Downloads the specified attachment and stores it locally on the device.
@@ -509,9 +510,11 @@ public class Chat {
509510
) async throws -> ChatMessage {
510511
Task { try await stopTyping() } // errors explicitly ignored
511512
let cid = try await self.cid
513+
let newMessageId = messageId ?? .newUniqueId
514+
async let sentMessage = waitForMessageSender(messageId: newMessageId)
512515
let localMessage = try await channelUpdater.createNewMessage(
513516
in: cid,
514-
messageId: messageId,
517+
messageId: newMessageId,
515518
text: text,
516519
pinning: pinning,
517520
isSilent: silent,
@@ -526,8 +529,6 @@ public class Chat {
526529
restrictedVisibility: restrictedVisibility,
527530
extraData: extraData
528531
)
529-
// Important to set up the waiter immediately
530-
async let sentMessage = try await waitForAPIRequest(localMessage: localMessage)
531532
eventNotificationCenter.process(NewMessagePendingEvent(message: localMessage, cid: cid))
532533
return try await sentMessage
533534
}
@@ -547,9 +548,11 @@ public class Chat {
547548
extraData: [String: RawJSON] = [:]
548549
) async throws -> ChatMessage {
549550
let cid = try await self.cid
551+
let newMessageId = messageId ?? .newUniqueId
552+
async let sentMessage = waitForMessageSender(messageId: newMessageId)
550553
let localMessage = try await channelUpdater.createNewMessage(
551554
in: cid,
552-
messageId: messageId,
555+
messageId: newMessageId,
553556
text: text,
554557
pinning: nil,
555558
isSilent: false,
@@ -564,8 +567,6 @@ public class Chat {
564567
restrictedVisibility: restrictedVisibility,
565568
extraData: extraData
566569
)
567-
// Important to set up the waiter immediately
568-
async let sentMessage = try await waitForAPIRequest(localMessage: localMessage)
569570
eventNotificationCenter.process(NewMessagePendingEvent(message: localMessage, cid: cid))
570571
return try await sentMessage
571572
}
@@ -593,7 +594,8 @@ public class Chat {
593594
skipPush: Bool = false
594595
) async throws -> ChatMessage {
595596
Task { try await stopTyping() } // errors explicitly ignored
596-
let localMessage = try await messageUpdater.editMessage(
597+
async let updatedMessage = waitForMessageEditor(messageId: messageId)
598+
_ = try await messageUpdater.editMessage(
597599
messageId: messageId,
598600
text: text,
599601
skipEnrichUrl: skipEnrichURL,
@@ -602,7 +604,7 @@ public class Chat {
602604
restrictedVisibility: restrictedVisibility,
603605
extraData: extraData
604606
)
605-
return try await waitForAPIRequest(localMessage: localMessage)
607+
return try await updatedMessage
606608
}
607609

608610
// MARK: - Message Pagination
@@ -992,9 +994,11 @@ public class Chat {
992994
) async throws -> ChatMessage {
993995
Task { try await stopTyping() } // errors explicitly ignored
994996
let cid = try await self.cid
997+
let newMessageId = messageId ?? .newUniqueId
998+
async let sentMessage = waitForMessageSender(messageId: newMessageId)
995999
let localMessage = try await messageUpdater.createNewReply(
9961000
in: cid,
997-
messageId: messageId,
1001+
messageId: newMessageId,
9981002
text: text,
9991003
pinning: pinning,
10001004
command: nil,
@@ -1009,7 +1013,6 @@ public class Chat {
10091013
skipEnrichUrl: skipEnrichURL,
10101014
extraData: extraData
10111015
)
1012-
async let sentMessage = try await waitForAPIRequest(localMessage: localMessage)
10131016
eventNotificationCenter.process(NewMessagePendingEvent(message: localMessage, cid: cid))
10141017
return try await sentMessage
10151018
}
@@ -1536,18 +1539,14 @@ extension Chat {
15361539
}
15371540
}
15381541

1539-
/// Depending on the local state we use different workers.
1540-
func waitForAPIRequest(localMessage: ChatMessage) async throws -> ChatMessage {
1541-
switch localMessage.localState {
1542-
case .pendingSend:
1543-
let messageSender = try client.backgroundWorker(of: MessageSender.self)
1544-
return try await messageSender.waitForAPIRequest(messageId: localMessage.id)
1545-
case .pendingSync:
1546-
let messageEditor = try client.backgroundWorker(of: MessageEditor.self)
1547-
return try await messageEditor.waitForAPIRequest(messageId: localMessage.id)
1548-
default:
1549-
return localMessage
1550-
}
1542+
func waitForMessageEditor(messageId: MessageId) async throws -> ChatMessage {
1543+
let messageEditor = try client.backgroundWorker(of: MessageEditor.self)
1544+
return try await messageEditor.waitForAPIRequest(messageId: messageId)
1545+
}
1546+
1547+
func waitForMessageSender(messageId: MessageId) async throws -> ChatMessage {
1548+
let messageSender = try client.backgroundWorker(of: MessageSender.self)
1549+
return try await messageSender.waitForAPIRequest(messageId: messageId)
15511550
}
15521551
}
15531552

Tests/StreamChatTests/StateLayer/Chat_Tests.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -673,12 +673,6 @@ final class Chat_Tests: XCTestCase {
673673
func test_sendMessage_whenAPIRequestSucceeds_thenSendMessageSucceeds() async throws {
674674
try await setUpChat(usesMockedUpdaters: false)
675675
await XCTAssertEqual(0, chat.state.messages.count)
676-
677-
let notificationExpectation = expectation(
678-
forNotification: .NewEventReceived,
679-
object: nil,
680-
notificationCenter: env.client.eventNotificationCenter
681-
)
682676

683677
let typingIndicatorResponse = EmptyResponse()
684678
env.client.mockAPIClient.test_mockResponseResult(.success(typingIndicatorResponse))
@@ -696,8 +690,6 @@ final class Chat_Tests: XCTestCase {
696690
messageId: apiResponse.message.id
697691
)
698692

699-
await fulfillment(of: [notificationExpectation], timeout: defaultTimeout)
700-
701693
XCTAssertEqual(text, message.text)
702694
await XCTAssertEqual(1, chat.state.messages.count)
703695
let messages = await chat.state.messages
@@ -735,21 +727,29 @@ final class Chat_Tests: XCTestCase {
735727
XCTAssertEqual(LocalMessageState.sendingFailed, stateMessage.localState)
736728
}
737729

738-
func test_sendSystemMessage_thenCallsChannelUpdaterWithIsSystemTrue() async throws {
739-
try await setUpChat(usesMockedUpdaters: true)
730+
func test_sendSystemMessage_whenAPIRequestSucceeds_thenSendMessageSucceeds() async throws {
731+
try await setUpChat(usesMockedUpdaters: false)
740732
await XCTAssertEqual(0, chat.state.messages.count)
741733

742734
let text = "Text"
743-
env.channelUpdaterMock.createNewMessage_completion_result = .success((
744-
.mock(id: "0", text: text, type: .system)
745-
))
735+
let apiResponse = MessagePayload.Boxed(
736+
message: .dummy(
737+
type: .system,
738+
messageId: "0",
739+
text: text
740+
)
741+
)
742+
env.client.mockAPIClient.test_mockResponseResult(.success(apiResponse))
743+
746744
let message = try await chat.sendSystemMessage(
747745
with: text,
748746
messageId: "0"
749747
)
750748

751-
XCTAssertEqual(env.typingEventsSenderMock.stopTyping_cid, nil)
752-
XCTAssertEqual(env.channelUpdaterMock.createNewMessage_isSystem, true)
749+
let body = env.client.mockAPIClient.request_endpoint?.body?.encodable as? [String: AnyEncodable]
750+
let messageRequestBody = body?["message"]?.encodable as? MessageRequestBody
751+
XCTAssertEqual(messageRequestBody?.type, MessageType.system.rawValue)
752+
753753
XCTAssertEqual(text, message.text)
754754
XCTAssertEqual(.system, message.type)
755755
}

0 commit comments

Comments
 (0)