Files
artex/server/sync_scopesentry_localized_test.go
T
dela 0335d572de
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
web / web (push) Waiting to run
docs / links (push) Canceled after 0s
detections / detections (push) Canceled after 0s
First Commit
2026-10-09 08:38:16 +08:00

106 lines
4.2 KiB
Go

package server
import (
"encoding/json"
"errors"
"fmt"
"strings"
"testing"
)
// TestSyncScopeSentryConstantsLocalized guards F3b (sync_scopesentry.go): every
// user-facing message constant — surfaced either as a writeErr HTTP body or inside
// the sync result's warnings/errors JSON arrays — must be Korean (Hangul present,
// no Chinese Han). Reverting any literal to Chinese fails this test.
func TestSyncScopeSentryConstantsLocalized(t *testing.T) {
cases := []struct {
label string
msg string
}{
{"errSSDataSourceMissingFmt", errSSDataSourceMissingFmt},
{"errSSDataSourceNoURLFmt", errSSDataSourceNoURLFmt},
{"errSSListProjectsPrefix", errSSListProjectsPrefix},
{"errSSParseProjectsPrefix", errSSParseProjectsPrefix},
{"errSSListTasksPrefix", errSSListTasksPrefix},
{"errSSParseTasksPrefix", errSSParseTasksPrefix},
{"errSSDimension", errSSDimension},
{"errSSTargetsEmpty", errSSTargetsEmpty},
{"warnSSProjectMetaFmt", warnSSProjectMetaFmt},
{"warnSSCompanyCreateFmt", warnSSCompanyCreateFmt},
{"warnSSUnknownAssetPrefix", warnSSUnknownAssetPrefix},
{"errSSFetchFmt", errSSFetchFmt},
{"warnSSTruncatedFmt", warnSSTruncatedFmt},
{"errSSParseSubdomainPrefix", errSSParseSubdomainPrefix},
{"errSSParseAppPrefix", errSSParseAppPrefix},
{"errSSParseServicePrefix", errSSParseServicePrefix},
}
for _, c := range cases {
assertKoreanError(t, c.label, c.msg)
}
// dimension/targets validation keep their JSON field names and enum values.
if !strings.Contains(errSSDimension, "project") || !strings.Contains(errSSDimension, "task") {
t.Fatalf("errSSDimension 이 enum 값을 잃었습니다: %q", errSSDimension)
}
}
// TestSyncScopeSentryFormattedLocalized exercises the exact Sprintf/Errorf format
// strings used by the sync handler so a verb mismatch or a reverted literal is
// caught by running the real format operation (not just inspecting the constant).
func TestSyncScopeSentryFormattedLocalized(t *testing.T) {
ds := fmt.Errorf(errSSDataSourceMissingFmt, scopeSentryMCPName).Error()
assertKoreanError(t, "scopeSentryClient/missing", ds)
if !strings.Contains(ds, "ScopeSentry") {
t.Fatalf("데이터 소스 이름이 사라졌습니다: %q", ds)
}
noURL := fmt.Errorf(errSSDataSourceNoURLFmt, scopeSentryMCPName).Error()
assertKoreanError(t, "scopeSentryClient/noURL", noURL)
if !strings.Contains(noURL, "URL") {
t.Fatalf("URL 토큰이 사라졌습니다: %q", noURL)
}
meta := fmt.Sprintf(warnSSProjectMetaFmt, "proj-1", errors.New("boom"))
assertKoreanError(t, "warnSSProjectMetaFmt", meta)
if !strings.Contains(meta, "proj-1") || !strings.Contains(meta, "boom") {
t.Fatalf("프로젝트/원본 오류가 치환되지 않았습니다: %q", meta)
}
company := fmt.Sprintf(warnSSCompanyCreateFmt, "ACME", errors.New("boom"))
assertKoreanError(t, "warnSSCompanyCreateFmt", company)
if !strings.Contains(company, "ACME") {
t.Fatalf("회사 이름이 치환되지 않았습니다: %q", company)
}
fetch := fmt.Sprintf(errSSFetchFmt, "subdomain", "t1", errors.New("boom"))
assertKoreanError(t, "errSSFetchFmt", fetch)
if !strings.Contains(fetch, "subdomain") || !strings.Contains(fetch, "t1") {
t.Fatalf("자산 유형/대상이 치환되지 않았습니다: %q", fetch)
}
truncated := fmt.Sprintf(warnSSTruncatedFmt, "app", "t1", syncMaxPerType)
assertKoreanError(t, "warnSSTruncatedFmt", truncated)
if !strings.Contains(truncated, "5000") {
t.Fatalf("상한 건수가 치환되지 않았습니다: %q", truncated)
}
}
// TestSyncScopeSentryIngestParseErrorsLocalized runs ssIngest on malformed JSON for
// each asset kind. The unmarshal failure returns before any store access, so this is
// a real code path (nil AssetStore never dereferenced) that pins the parse-error
// strings to Korean.
func TestSyncScopeSentryIngestParseErrorsLocalized(t *testing.T) {
s := &Server{}
bad := json.RawMessage("not json")
for _, kind := range []string{"subdomain", "app", "service"} {
got := s.ssIngest(nil, kind, bad, map[string]int{})
if got == "" {
t.Fatalf("%s: 깨진 JSON 인데 오류 문자열이 비었습니다", kind)
}
assertKoreanError(t, "ssIngest/"+kind, got)
if !strings.Contains(got, kind) {
t.Fatalf("%s: 자산 유형 접두가 사라졌습니다: %q", kind, got)
}
}
}