diff --git a/LocalPackage/Sources/HometeDomain/Cohabitant/Housework/HouseworkListStore.swift b/LocalPackage/Sources/HometeDomain/Cohabitant/Housework/HouseworkListStore.swift index adc918eb..5ffe132d 100644 --- a/LocalPackage/Sources/HometeDomain/Cohabitant/Housework/HouseworkListStore.swift +++ b/LocalPackage/Sources/HometeDomain/Cohabitant/Housework/HouseworkListStore.swift @@ -199,7 +199,8 @@ public final class HouseworkListStore { /// 完了した家事に「ありがとう」を記録し、コメントが初めて付いたときだけ相手に通知する /// /// 1人が1つの家事に送れるありがとうは1件で、送信済みの家事に対して呼ぶとコメントの編集になる(最初に送った日時は変えない)。 - /// 通知はコメント付きで送ったときと、コメントなしで送った後に書き足したときだけ送る。呼び出し元に返すのは記録の失敗だけ。 + /// 通知はコメント付きで送ったときと、コメントなしで送った後に書き足したときだけ送る。 + /// 呼び出し元に返すのは記録の失敗だけで、通知の送信は待たない。 /// - Parameter comment: 添えるコメント。コメントなしで送る場合は`nil` // swiftlint:disable:next function_parameter_count public func sendThanks( @@ -230,15 +231,10 @@ public final class HouseworkListStore { guard let comment, currentThanks?.comment == nil else { return } - // 記録できた後に通知だけ失敗しても、送り直すと編集扱いになり通知は送られないため、失敗として返さない - do { - try await cohabitantPushNotificationClient.send( - cohabitantId, - .thanksMessage(senderName: sender.userName, houseworkTitle: target.title, comment: comment) - ) - } catch { - print("failed to notify cohabitants of thanks: \(error)") - } + notifyThanks( + cohabitantId: cohabitantId, + content: .thanksMessage(senderName: sender.userName, houseworkTitle: target.title, comment: comment) + ) } public func returnToIncomplete( @@ -384,6 +380,20 @@ private extension HouseworkListStore { : .sendThanks(step: step, isSuccess: isSuccess) } + /// ありがとうに添えたコメントを同居人へ知らせる + /// + /// 送信は待たずに行い、失敗しても記録は失敗扱いにしない。 + /// 送り直しても編集扱いになって通知は送られないが、ありがとう自体は記録できているため。 + func notifyThanks(cohabitantId: String, content: PushNotificationContent) { + Task.detached { + do { + try await self.cohabitantPushNotificationClient.send(cohabitantId, content) + } catch { + print("failed to notify cohabitants of thanks: \(error)") + } + } + } + /// コメントを添えた完了通知を、1日1回の制限に関係なく送る /// /// ふりかえり通知の予約用データは、`notifyCompleted`と同じ条件のときだけ付ける。 diff --git a/LocalPackage/Tests/HometeDomainTests/Housework/HouseworkListStoreTest.swift b/LocalPackage/Tests/HometeDomainTests/Housework/HouseworkListStoreTest.swift index ae2893ef..f01c9b13 100644 --- a/LocalPackage/Tests/HometeDomainTests/Housework/HouseworkListStoreTest.swift +++ b/LocalPackage/Tests/HometeDomainTests/Housework/HouseworkListStoreTest.swift @@ -640,7 +640,7 @@ extension HouseworkListStoreTest.UpdateStatusCase { } @Test("コメント付きで初めてありがとうを伝えると、ありがとうを記録してパートナーに通知を送る") - func sendThanks_firstWithComment_recordsAndNotifies() async throws { + func sendThanks_firstWithComment_recordsAndNotifies() async { // Arrange let inputNow = Date(timeIntervalSince1970: 1000) @@ -658,39 +658,44 @@ extension HouseworkListStoreTest.UpdateStatusCase { message: inputComment ) - try await confirmation(expectedCount: 2) { confirmation in - let store = HouseworkListStore( - houseworkClient: .init( - upsertThanksHandler: { houseworkId, senderId, thanks, cohabitantId in + await confirmation(expectedCount: 2) { confirmation in + let _: Void = await withCheckedContinuation { continuation in + let store = HouseworkListStore( + houseworkClient: .init( + upsertThanksHandler: { houseworkId, senderId, thanks, cohabitantId in + // Assert + + #expect(houseworkId == inputHouseworkItem.id) + #expect(senderId == inputSender.id) + #expect(thanks == expectedThanks) + #expect(cohabitantId == inputCohabitantId) + confirmation() + } + ), + cohabitantPushNotificationClient: .init { id, content in // Assert - #expect(houseworkId == inputHouseworkItem.id) - #expect(senderId == inputSender.id) - #expect(thanks == expectedThanks) - #expect(cohabitantId == inputCohabitantId) + #expect(id == inputCohabitantId) + #expect(content == expectedNotificationContent) confirmation() - } - ), - cohabitantPushNotificationClient: .init { id, content in - // Assert - - #expect(id == inputCohabitantId) - #expect(content == expectedNotificationContent) - confirmation() - }, - items: [.makeForTest(items: [inputHouseworkItem])] - ) + continuation.resume() + }, + items: [.makeForTest(items: [inputHouseworkItem])] + ) - // Act + // Act - try await store.sendThanks( - target: inputHouseworkItem, - sender: inputSender, - comment: inputComment, - now: inputNow, - cohabitantId: inputCohabitantId, - step: .thanks - ) + Task { + try? await store.sendThanks( + target: inputHouseworkItem, + sender: inputSender, + comment: inputComment, + now: inputNow, + cohabitantId: inputCohabitantId, + step: .thanks + ) + } + } } } @@ -738,7 +743,7 @@ extension HouseworkListStoreTest.UpdateStatusCase { } @Test("コメントなしで送ったありがとうにコメントを書き足すと、最初に送った日時のまま記録し、通知を送る") - func sendThanks_addCommentToThanksWithoutComment_keepsSentAtAndNotifies() async throws { + func sendThanks_addCommentToThanksWithoutComment_keepsSentAtAndNotifies() async { // Arrange let inputSentAt = Date(timeIntervalSince1970: 500) @@ -757,35 +762,40 @@ extension HouseworkListStoreTest.UpdateStatusCase { message: inputComment ) - try await confirmation(expectedCount: 2) { confirmation in - let store = HouseworkListStore( - houseworkClient: .init( - upsertThanksHandler: { _, _, thanks, _ in + await confirmation(expectedCount: 2) { confirmation in + let _: Void = await withCheckedContinuation { continuation in + let store = HouseworkListStore( + houseworkClient: .init( + upsertThanksHandler: { _, _, thanks, _ in + // Assert + + #expect(thanks == expectedThanks) + confirmation() + } + ), + cohabitantPushNotificationClient: .init { _, content in // Assert - #expect(thanks == expectedThanks) + #expect(content == expectedNotificationContent) confirmation() - } - ), - cohabitantPushNotificationClient: .init { _, content in - // Assert - - #expect(content == expectedNotificationContent) - confirmation() - }, - items: [.makeForTest(items: [inputHouseworkItem])] - ) + continuation.resume() + }, + items: [.makeForTest(items: [inputHouseworkItem])] + ) - // Act + // Act - try await store.sendThanks( - target: inputHouseworkItem, - sender: inputSender, - comment: inputComment, - now: Date(timeIntervalSince1970: 1000), - cohabitantId: inputCohabitantId, - step: .thanks - ) + Task { + try? await store.sendThanks( + target: inputHouseworkItem, + sender: inputSender, + comment: inputComment, + now: Date(timeIntervalSince1970: 1000), + cohabitantId: inputCohabitantId, + step: .thanks + ) + } + } } } @@ -915,7 +925,7 @@ extension HouseworkListStoreTest.UpdateStatusCase { } @Test("ありがとうを記録できた後に通知の送信だけ失敗しても、失敗として返さない") - func sendThanks_notificationFailed_doesNotThrow() async throws { + func sendThanks_notificationFailed_doesNotThrow() async { // Arrange let inputHouseworkItem = HouseworkItem.makeForTest( @@ -926,30 +936,39 @@ extension HouseworkListStoreTest.UpdateStatusCase { ) let inputSender = Account(id: "senderId", userName: "おくりぬし", fcmToken: nil, cohabitantId: inputCohabitantId) - try await confirmation(expectedCount: 2) { confirmation in - let store = HouseworkListStore( - houseworkClient: .init( - upsertThanksHandler: { _, _, _, _ in + await confirmation(expectedCount: 2) { confirmation in + let _: Void = await withCheckedContinuation { continuation in + let store = HouseworkListStore( + houseworkClient: .init( + upsertThanksHandler: { _, _, _, _ in + confirmation() + } + ), + cohabitantPushNotificationClient: .init { _, _ in confirmation() - } - ), - cohabitantPushNotificationClient: .init { _, _ in - confirmation() - throw DomainError.other - }, - items: [.makeForTest(items: [inputHouseworkItem])] - ) + continuation.resume() + throw DomainError.other + }, + items: [.makeForTest(items: [inputHouseworkItem])] + ) - // Act & Assert + // Act & Assert - try await store.sendThanks( - target: inputHouseworkItem, - sender: inputSender, - comment: "お疲れ様でした!", - now: Date(timeIntervalSince1970: 1000), - cohabitantId: inputCohabitantId, - step: .thanks - ) + Task { + do { + try await store.sendThanks( + target: inputHouseworkItem, + sender: inputSender, + comment: "お疲れ様でした!", + now: Date(timeIntervalSince1970: 1000), + cohabitantId: inputCohabitantId, + step: .thanks + ) + } catch { + Issue.record("ありがとうの記録は成功として返るべき: \(error)") + } + } + } } }