Files
artex/server/notifier_localized_test.go
T
dela 97668dab7e
ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
detections / detections (push) Waiting to run
docs / links (push) Waiting to run
web / web (push) Waiting to run
Localize user-facing UI, agent output, and backend messages to Simplified Chinese
2026-10-09 14:08:31 +08:00

73 lines
3.1 KiB
Go

package server
import (
"context"
"errors"
"fmt"
"strings"
"testing"
"github.com/Autumn-27/artex/db"
)
// TestNotifierDeliveryReasonsLocalized guards F17: every delivery failure/defer
// reason that notifier.go writes into notification_deliveries.last_error — which
// notify_api.go echoes back to the "전달 기록" table in delivery-list.tsx — must be
// Korean (Hangul present, no Chinese Han). Diagnostic log.Printf lines stay in the
// original language (Z2) and are intentionally not covered here.
func TestNotifierDeliveryReasonsLocalized(t *testing.T) {
// Format every constant with ASCII arguments so any leftover Han ideograph is
// the constant's own, not injected by the test data.
cases := []struct {
label string
msg string
}{
{"channelKindUnregistered", fmt.Sprintf(errDeliveryChannelKindUnregistered, "webhook")},
{"snapshotUnrenderable", errDeliverySnapshotUnrenderable},
{"channelLengthCapped", fmt.Sprintf(errDeliveryChannelLengthCapped, 3)},
{"noDeliveredCount", fmt.Sprintf(errDeliveryNoDeliveredCount, 0)},
{"retryExhausted", fmt.Sprintf(errDeliveryRetryExhausted, db.MaxNotifyAttempts, errors.New("boom"))},
{"snapshotEmpty", fmt.Sprintf(errDeliverySnapshotEmpty, 7)},
{"snapshotParse", fmt.Errorf(errDeliverySnapshotParse, 9, errors.New("unexpected end of JSON input")).Error()},
{"batchAllUnparseable", fmt.Sprintf(errDeliveryBatchAllUnparseable, 2)},
}
for _, c := range cases {
assertChineseError(t, c.label, c.msg)
}
}
// TestNotifierParseSnapshotErrorsLocalized exercises the real parseSnapshot paths
// that surface as last_error through renderSingle → FailDeliveries. parseSnapshot is
// a package-level pure function, so no DB or Server is needed.
func TestNotifierParseSnapshotErrorsLocalized(t *testing.T) {
// Empty snapshot.
if _, err := parseSnapshot(&db.NotificationDelivery{ID: 7}); err == nil {
t.Fatal("빈 스냅샷이 오류 없이 통과해서는 안 됩니다")
} else {
assertChineseError(t, "parseSnapshot.empty", err.Error())
if !strings.Contains(err.Error(), "7") {
t.Fatalf("parseSnapshot.empty: 전달 항목 ID 7 이 메시지에 없습니다: %q", err.Error())
}
}
// Malformed JSON snapshot.
if _, err := parseSnapshot(&db.NotificationDelivery{ID: 9, Snapshot: []byte("{bad")}); err == nil {
t.Fatal("깨진 JSON 스냅샷이 오류 없이 통과해서는 안 됩니다")
} else {
assertChineseError(t, "parseSnapshot.malformed", err.Error())
}
}
// TestNotifierRenderBatchAllUnparseableLocalized drives the real renderBatch "every
// snapshot is unparseable" branch. With all snapshots empty, every delivery is
// skipped before itemFor (and thus before n.pg), so a zero-value Notifier reaches
// the errDeliveryBatchAllUnparseable return without touching the database.
func TestNotifierRenderBatchAllUnparseableLocalized(t *testing.T) {
n := &Notifier{}
deliveries := []*db.NotificationDelivery{{ID: 1}, {ID: 2}}
if _, _, err := n.renderBatch(context.Background(), deliveries, "", 30); err == nil {
t.Fatal("모든 스냅샷이 해석 불가일 때 오류가 나와야 합니다")
} else {
assertChineseError(t, "renderBatch.allUnparseable", err.Error())
}
}