package applog import ( "bytes" "encoding/json" "log/slog" "strings" "testing" ) func TestNewLogger_FiltersBelowConfiguredLevel(t *testing.T) { var buf bytes.Buffer logger := NewLogger("warn", &buf) logger.Info("should be dropped") if buf.Len() != 0 { t.Fatalf("expected no output for an Info message under a warn-level logger, got %q", buf.String()) } logger.Warn("should appear") if !strings.Contains(buf.String(), "should appear") { t.Fatalf("expected the Warn message in output, got %q", buf.String()) } } func TestNewLogger_WritesValidJSON(t *testing.T) { var buf bytes.Buffer logger := NewLogger("info", &buf) logger.Info("hello", "key", "value") var decoded map[string]any if err := json.Unmarshal(buf.Bytes(), &decoded); err != nil { t.Fatalf("output is not valid JSON: %v (%q)", err, buf.String()) } if decoded["msg"] != "hello" || decoded["key"] != "value" { t.Errorf("decoded = %+v, want msg=hello key=value", decoded) } } func TestNewLogger_OmitsEmptyMsg(t *testing.T) { var buf bytes.Buffer logger := NewLogger("info", &buf) logger.Info("", "type", "http", "status", 200) var decoded map[string]any if err := json.Unmarshal(buf.Bytes(), &decoded); err != nil { t.Fatalf("output not JSON: %v (%q)", err, buf.String()) } if _, present := decoded["msg"]; present { t.Errorf("empty msg should be omitted, got %+v", decoded) } if decoded["type"] != "http" { t.Errorf("attrs lost alongside dropped msg: %+v", decoded) } } func TestApp_TagsMandatoryFields(t *testing.T) { var buf bytes.Buffer prev := slog.Default() slog.SetDefault(NewLogger("info", &buf)) defer slog.SetDefault(prev) App("api.Server", "handleThing").Info("did it", "extra", 1) var decoded map[string]any if err := json.Unmarshal(buf.Bytes(), &decoded); err != nil { t.Fatalf("output not JSON: %v", err) } if decoded["type"] != "app" || decoded["class"] != "api.Server" || decoded["method"] != "handleThing" { t.Errorf("mandatory fields = %+v, want type=app class=api.Server method=handleThing", decoded) } }