package recovery import ( "bytes" "context" "log" "strings" "testing" "git.k6n.net/mats/go-cart-actor/pkg/cart" ) // captureLog writes log output to an in-memory buffer for inspection. func captureLog(t *testing.T) *bytes.Buffer { t.Helper() buf := &bytes.Buffer{} orig := log.Writer() flags := log.Flags() prefix := log.Prefix() log.SetOutput(buf) log.SetFlags(0) log.SetPrefix("") t.Cleanup(func() { log.SetOutput(orig) log.SetFlags(flags) log.SetPrefix(prefix) }) return buf } func TestLoggingNotifier_LogsPlatformsNotTokens(t *testing.T) { buf := captureLog(t) n := LoggingNotifier{} err := n.NotifyAbandoned(context.Background(), RecoveryCandidate{ CartID: 1, Email: "doc@example.com", PushTokens: []cart.PushToken{{Platform: "fcm", Token: "SECRET-TOKEN-MUST-NOT-LEAK"}, {Platform: "apns", Token: "ALSO-SECRET-2"}}, }) if err != nil { t.Fatalf("NotifyAbandoned: %v", err) } out := buf.String() if !strings.Contains(out, "doc@example.com") { t.Errorf("expected email in log: %s", out) } if !strings.Contains(out, "[fcm apns]") { t.Errorf("expected bracketed platform list in log: %s", out) } for _, leak := range []string{"SECRET-TOKEN-MUST-NOT-LEAK", "ALSO-SECRET-2"} { if strings.Contains(out, leak) { t.Errorf("token leaked into log: %s line=%s", leak, out) } } } func TestLoggingNotifier_ClassifiesChannel(t *testing.T) { buf := captureLog(t) n := LoggingNotifier{} cases := []struct { name string cand RecoveryCandidate wantSub string }{ { name: "email+push", cand: RecoveryCandidate{Email: "a@b.c", PushTokens: []cart.PushToken{{Platform: "fcm"}}}, wantSub: "channel=email+push", }, { name: "email only", cand: RecoveryCandidate{Email: "a@b.c"}, wantSub: "channel=email", }, { name: "push only", cand: RecoveryCandidate{PushTokens: []cart.PushToken{{Platform: "fcm"}}}, wantSub: "channel=push", }, { name: "no contact", cand: RecoveryCandidate{}, wantSub: "channel=none", }, } for _, tc := range cases { buf.Reset() if err := n.NotifyAbandoned(context.Background(), tc.cand); err != nil { t.Fatalf("%s: %v", tc.name, err) } if !strings.Contains(buf.String(), tc.wantSub) { t.Errorf("%s: log missing %q; got: %s", tc.name, tc.wantSub, buf.String()) } } }