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
95 lines
4.0 KiB
Go
95 lines
4.0 KiB
Go
package notify
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// 이 파일은 F4 ③(이메일 본문·HTML 템플릿) 한국어화를 회귀로부터 지킨다.
|
|
// html.go 의 라벨과 email.go 의 검증 오류가 중국어로 되돌아가면 잡아낸다.
|
|
// 헬퍼 hasHan·hasHangul·assertKorean 은 notify_localized_test.go 에 있다(같은 패키지).
|
|
//
|
|
// 데이터(제목·유형·자산·개요)는 전부 ASCII 로 둔다. 그래야 "출력 전체에 한자 0"
|
|
// 이라는 단언이 콘텐츠가 아니라 골격 라벨의 회귀만 정확히 포착한다. 심각도·상태
|
|
// 라벨은 F4 ①에서 이미 한국어라 출력에 한글로 나오며(한자 아님) 단언을 통과한다.
|
|
|
|
// TestHTMLItemLabelsLocalized 는 단건 이메일 본문의 모든 라벨 분기를 켠 뒤
|
|
// 골격이 한국어이고 중국어 한자가 없음을 확인한다.
|
|
func TestHTMLItemLabelsLocalized(t *testing.T) {
|
|
m := Message{
|
|
HomeURL: "https://example.com/panel",
|
|
Items: []Item{{
|
|
Name: "sqli-login", // Title() = Name
|
|
VulnClass: "injection", // Title() 과 달라야 유형 줄이 렌더됨
|
|
Severity: "high", // SeverityLabel → 높음(한글)
|
|
Summary: "login form is injectable",
|
|
Assets: []string{"host-a.example.com"},
|
|
DetailURL: "https://example.com/f/1",
|
|
FromStatus: "pending", // IsStatusChange()=true → 상태 변경 줄
|
|
ToStatus: "fixed",
|
|
}},
|
|
}
|
|
out := htmlBody(m, 0)
|
|
if hasHan(out) {
|
|
t.Errorf("이메일 본문에 중국어 한자가 남아 있습니다:\n%s", out)
|
|
}
|
|
for _, want := range []string{
|
|
"상태 변경", "유형", "자산", "개요", "상세 보기", "플랫폼에서 전체 보기",
|
|
} {
|
|
if !strings.Contains(out, want) {
|
|
t.Errorf("이메일 본문에 %q 라벨이 없습니다:\n%s", want, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestHTMLBatchIntroLocalized 는 다건(digest) 머리말의 두 분기(시간창 유무)가
|
|
// 한국어로 렌더되는지 확인한다.
|
|
func TestHTMLBatchIntroLocalized(t *testing.T) {
|
|
items := []Item{{Name: "a", Severity: "high"}, {Name: "b", Severity: "low"}}
|
|
|
|
withWindow := htmlBatchIntro(Message{Batch: true, WindowMinutes: 30, Items: items})
|
|
assertKorean(t, "htmlBatchIntro(시간창)", withWindow)
|
|
for _, want := range []string{"최근 30분간", "신규 취약점", "2건"} {
|
|
if !strings.Contains(withWindow, want) {
|
|
t.Errorf("시간창 머리말에 %q 가 없습니다: %q", want, withWindow)
|
|
}
|
|
}
|
|
|
|
noWindow := htmlBatchIntro(Message{Batch: true, WindowMinutes: 0, Items: items})
|
|
assertKorean(t, "htmlBatchIntro(시간창 없음)", noWindow)
|
|
if !strings.Contains(noWindow, "신규 취약점 2건") {
|
|
t.Errorf("시간창 없는 머리말이 %q 를 포함해야 합니다: %q", "신규 취약점 2건", noWindow)
|
|
}
|
|
if strings.Contains(noWindow, "분간") {
|
|
t.Errorf("시간창이 없는데 '분간' 이 들어갔습니다: %q", noWindow)
|
|
}
|
|
}
|
|
|
|
// TestEmailValidateLocalized 는 SMTP 설정 검증 오류 네 가지가 한국어이고,
|
|
// 각 오류가 어떤 필드가 문제인지 알려 주는지 확인한다. 이 메시지는 알림 채널을
|
|
// 설정하는 사용자에게 그대로 표시된다.
|
|
func TestEmailValidateLocalized(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
cfg map[string]any
|
|
substr string
|
|
}{
|
|
{"서버 주소 누락", map[string]any{"port": float64(25), "from": "a@b.c", "to": []any{"d@e.f"}}, "SMTP"},
|
|
{"포트 범위 벗어남", map[string]any{"host": "h"}, "포트"},
|
|
{"발신자 누락", map[string]any{"host": "h", "port": float64(25), "to": []any{"d@e.f"}}, "발신자"},
|
|
{"수신자 누락", map[string]any{"host": "h", "port": float64(25), "from": "a@b.c"}, "수신자"},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
err := (emailChannel{}).Validate(tc.cfg)
|
|
if err == nil {
|
|
t.Fatalf("검증이 실패해야 합니다: %v", tc.cfg)
|
|
}
|
|
assertKorean(t, "Validate("+tc.name+")", err.Error())
|
|
if !strings.Contains(err.Error(), tc.substr) {
|
|
t.Errorf("오류 메시지에 %q 가 있어야 합니다, 받은 값 %q", tc.substr, err.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|