From 9ebbac84a613c31cbe828af330dd5f6f95138e5e Mon Sep 17 00:00:00 2001 From: Astrid Gealer Date: Sun, 25 Oct 2026 18:46:34 +0000 Subject: [PATCH] test(purchase): expect #1245's failure alert in the post-CAS safeFail race test main is red since #1111 merged (6c84280b): Integration Tests (purchase) panics in TestPostCASSave_ConcurrentStatusChangeSurvives/safeFail stamp after a late recovery. #1245, merged an hour earlier, made safeFail send SendPurchaseFailedNotification as a terminal-failure writer, and #1111's new test was written before that, so its email mock had no expectation for the call. The panic also killed the rest of the purchase integration package. Each PR was green on its own. Register the existing failedEmailRecorder in that subtest only and assert the race never alerts twice for one row. A fixture-wide .Maybe() stub would shadow the recorder in #1245's own TestRecoverStrandedApprovals_ClaimedRowTurnedUnsafeIsFailedNotBought, because testify matches the first registered expectation. The test's row assertions are unchanged. Co-Authored-By: Claude Opus 5.5 --- .../purchase/post_cas_guarded_save_integration_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/internal/purchase/post_cas_guarded_save_integration_test.go b/internal/purchase/post_cas_guarded_save_integration_test.go index bf6612b16..9e907a94d 100644 --- a/internal/purchase/post_cas_guarded_save_integration_test.go +++ b/internal/purchase/post_cas_guarded_save_integration_test.go @@ -91,9 +91,18 @@ func TestPostCASSave_ConcurrentStatusChangeSurvives(t *testing.T) { require.NoError(t, f.store.RecoverReapedExecution(ctx, late)) }) + // safeFail's flip to failed lands before the late recovery, so it alerts + // as a terminal-failure writer (#1245). The rows below are what this test + // pins; the alert's content is pinned in failure_notify*_test.go. + sender, ok := f.manager.email.(*MockEmailSender) + require.True(t, ok) + failedMail := &failedEmailRecorder{} + failedMail.expect(sender) + counted, err := f.manager.safeFail(ctx, rowStatusCopy(row)) require.NoError(t, err) + assert.LessOrEqual(t, len(failedMail.all()), 1, "the race must not alert twice for one row") assert.True(t, counted, "the flip to failed landed, so the sweep still counts it") got := rowStatus(ctx, t, f, row.ExecutionID) assert.Equal(t, config.StatusCompleted, got.Status, "the recovered purchase must not be reverted to failed")