test(06-02): add failing tests for JSONFormatter

This commit is contained in:
salvacybersec
2026-04-05 23:30:12 +03:00
parent 5292502000
commit c933673ca9

149
pkg/output/json_test.go Normal file
View File

@@ -0,0 +1,149 @@
package output
import (
"bytes"
"encoding/json"
"strings"
"testing"
"time"
"github.com/salvacybersec/keyhunter/pkg/engine"
)
func TestJSONFormatter_EmptyFindings(t *testing.T) {
var buf bytes.Buffer
if err := (JSONFormatter{}).Format(nil, &buf, Options{}); err != nil {
t.Fatalf("Format returned error: %v", err)
}
got := buf.String()
if got != "[]\n" {
t.Fatalf("empty findings: want %q, got %q", "[]\n", got)
}
}
func TestJSONFormatter_RegisteredUnderJSON(t *testing.T) {
f, err := Get("json")
if err != nil {
t.Fatalf("Get(\"json\") error: %v", err)
}
if _, ok := f.(JSONFormatter); !ok {
t.Fatalf("Get(\"json\") returned %T, want JSONFormatter", f)
}
}
func sampleFinding() engine.Finding {
return engine.Finding{
ProviderName: "openai",
KeyValue: "sk-proj-abcdef1234567890XYZW",
KeyMasked: "sk-proj-...XYZW",
Confidence: "high",
Source: "src/config.go",
SourceType: "file",
LineNumber: 42,
Offset: 1024,
DetectedAt: time.Date(2026, 4, 5, 12, 30, 0, 0, time.UTC),
}
}
func TestJSONFormatter_MaskedByDefault(t *testing.T) {
f := sampleFinding()
var buf bytes.Buffer
if err := (JSONFormatter{}).Format([]engine.Finding{f}, &buf, Options{}); err != nil {
t.Fatalf("Format returned error: %v", err)
}
var out []map[string]any
if err := json.Unmarshal(buf.Bytes(), &out); err != nil {
t.Fatalf("invalid JSON: %v\n%s", err, buf.String())
}
if len(out) != 1 {
t.Fatalf("want 1 element, got %d", len(out))
}
if out[0]["key"] != f.KeyMasked {
t.Errorf("key: want %q (masked), got %v", f.KeyMasked, out[0]["key"])
}
if out[0]["key_masked"] != f.KeyMasked {
t.Errorf("key_masked: want %q, got %v", f.KeyMasked, out[0]["key_masked"])
}
if out[0]["provider"] != "openai" {
t.Errorf("provider: got %v", out[0]["provider"])
}
if out[0]["confidence"] != "high" {
t.Errorf("confidence: got %v", out[0]["confidence"])
}
if out[0]["line"].(float64) != 42 {
t.Errorf("line: got %v", out[0]["line"])
}
if out[0]["detected_at"] != "2026-04-05T12:30:00Z" {
t.Errorf("detected_at: got %v", out[0]["detected_at"])
}
if out[0]["verified"] != false {
t.Errorf("verified: got %v", out[0]["verified"])
}
// Unverified: omitempty fields should not appear.
if _, ok := out[0]["verify_status"]; ok {
t.Errorf("verify_status should be omitted when empty")
}
}
func TestJSONFormatter_UnmaskRevealsKey(t *testing.T) {
f := sampleFinding()
var buf bytes.Buffer
if err := (JSONFormatter{}).Format([]engine.Finding{f}, &buf, Options{Unmask: true}); err != nil {
t.Fatalf("Format returned error: %v", err)
}
var out []map[string]any
if err := json.Unmarshal(buf.Bytes(), &out); err != nil {
t.Fatalf("invalid JSON: %v", err)
}
if out[0]["key"] != f.KeyValue {
t.Errorf("key: want %q (unmasked), got %v", f.KeyValue, out[0]["key"])
}
if out[0]["key_masked"] != f.KeyMasked {
t.Errorf("key_masked should remain masked, got %v", out[0]["key_masked"])
}
}
func TestJSONFormatter_VerifyFieldsPresent(t *testing.T) {
f := sampleFinding()
f.Verified = true
f.VerifyStatus = "live"
f.VerifyHTTPCode = 200
f.VerifyMetadata = map[string]string{"org": "acme"}
var buf bytes.Buffer
if err := (JSONFormatter{}).Format([]engine.Finding{f}, &buf, Options{}); err != nil {
t.Fatalf("Format returned error: %v", err)
}
var out []map[string]any
if err := json.Unmarshal(buf.Bytes(), &out); err != nil {
t.Fatalf("invalid JSON: %v", err)
}
if out[0]["verified"] != true {
t.Errorf("verified: got %v", out[0]["verified"])
}
if out[0]["verify_status"] != "live" {
t.Errorf("verify_status: got %v", out[0]["verify_status"])
}
if out[0]["verify_http_code"].(float64) != 200 {
t.Errorf("verify_http_code: got %v", out[0]["verify_http_code"])
}
meta, ok := out[0]["verify_metadata"].(map[string]any)
if !ok {
t.Fatalf("verify_metadata missing or wrong type: %v", out[0]["verify_metadata"])
}
if meta["org"] != "acme" {
t.Errorf("verify_metadata.org: got %v", meta["org"])
}
}
func TestJSONFormatter_Indented(t *testing.T) {
f := sampleFinding()
var buf bytes.Buffer
if err := (JSONFormatter{}).Format([]engine.Finding{f}, &buf, Options{}); err != nil {
t.Fatalf("Format returned error: %v", err)
}
// Expect 2-space indent on at least one property line.
if !strings.Contains(buf.String(), "\n \"provider\"") {
t.Errorf("output not indented with 2 spaces:\n%s", buf.String())
}
}