package sentrysetup import ( "bytes" "errors" "fmt" "log/slog" "strings" "testing" "github.com/getsentry/sentry-go" "github.com/stretchr/testify/assert" ) func TestSetupSentry(t *testing.T) { type args struct { releaseName string args SentryConfig } tests := []struct { name string args args init func(t *testing.T) func(sentry.ClientOptions) error wantErr assert.ErrorAssertionFunc wantLogged []string }{ { name: "disabled", args: args{ releaseName: "v1.0.0", args: SentryConfig{ DSN: "https://dsn.example.org/123", Environment: "dev", Disabled: true, }, }, init: nil, wantErr: assert.NoError, wantLogged: []string{`level=INFO msg="Sentry disabled, setup using empty options"`}, }, { name: "no environment", args: args{ releaseName: "v1.0.0", args: SentryConfig{ DSN: "https://dsn.example.org/123", Environment: "", Disabled: false, }, }, init: nil, wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { return assert.EqualError(t, err, "no Sentry environment supplied, exiting") }, wantLogged: []string{}, }, { name: "illegal environment", args: args{ releaseName: "v1.0.0", args: SentryConfig{ DSN: "https://dsn.example.org/123", Environment: "unknown", Disabled: false, }, }, init: nil, wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { return assert.EqualError(t, err, "illegal environment unknown") }, wantLogged: []string{}, }, { name: "error setting up Sentry", args: args{ releaseName: "v1.0.0", args: SentryConfig{ DSN: "https://dsn.example.org/123", Environment: "development", Disabled: false, }, }, init: func(t *testing.T) func(sentry.ClientOptions) error { return func(options sentry.ClientOptions) error { assert.Equal(t, sentry.ClientOptions{ Dsn: "https://dsn.example.org/123", Debug: true, Release: "v1.0.0", Environment: "development", }, options) return errors.New("error") } }, wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { return assert.EqualError(t, err, "sentry setup: error") }, wantLogged: []string{}, }, { name: "missing DSN for prod-like environment", args: args{ releaseName: "v1.0.0", args: SentryConfig{ DSN: "", Environment: "staging", Disabled: false, }, }, init: nil, wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { return assert.EqualError(t, err, "no DSN supplied for non-dev environment, exiting") }, wantLogged: []string{}, }, { name: "success", args: args{ releaseName: "v1.0.0", args: SentryConfig{ DSN: "https://dsn.example.org/123", Environment: "production", Disabled: false, }, }, init: func(t *testing.T) func(sentry.ClientOptions) error { return func(options sentry.ClientOptions) error { assert.Equal(t, sentry.ClientOptions{ Dsn: "https://dsn.example.org/123", Debug: false, EnableTracing: true, TracesSampleRate: 1, Release: "v1.0.0", Environment: "production", }, options) return nil } }, wantErr: assert.NoError, wantLogged: []string{`level=INFO msg="configured Sentry for env: production"`}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { logged := &bytes.Buffer{} logger := &MockLogger{ logger: slog.New(slog.NewTextHandler(logged, &slog.HandlerOptions{ ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { if a.Key == "time" { return slog.Attr{} } return a }, })), logged: logged, } if tt.init == nil { sentryInit = sentry.Init } else { sentryInit = tt.init(t) } tt.wantErr(t, SetupSentry(logger.Logger(), tt.args.releaseName, tt.args.args), fmt.Sprintf("SetupSentry(%v, %v, %v)", logger, tt.args.releaseName, tt.args.args)) logger.Check(t, tt.wantLogged) }) } } type MockLogger struct { logger *slog.Logger logged *bytes.Buffer } func (m *MockLogger) Logger() *slog.Logger { return m.logger } func (m *MockLogger) Check(t testing.TB, wantLogged []string) { var gotLogged []string if m.logged.String() != "" { gotLogged = strings.Split(m.logged.String(), "\n") gotLogged = gotLogged[:len(gotLogged)-1] } if len(wantLogged) == 0 { assert.Empty(t, gotLogged) return } assert.Equal(t, wantLogged, gotLogged) }