event_test.go

  1package event
  2
  3// These tests verify that the Error function correctly handles various
  4// scenarios. These tests will not log anything.
  5
  6import (
  7	"reflect"
  8	"testing"
  9
 10	"github.com/posthog/posthog-go"
 11)
 12
 13func TestError(t *testing.T) {
 14	t.Run("returns early when client is nil", func(t *testing.T) {
 15		// This test verifies that when the PostHog client is not initialized
 16		// the Error function safely returns early without attempting to
 17		// enqueue any events. This is important during initialization or when
 18		// metrics are disabled, as we don't want the error reporting mechanism
 19		// itself to cause panics.
 20		originalClient := client
 21		defer func() {
 22			client = originalClient
 23		}()
 24
 25		client = nil
 26		Error("test error", "key", "value")
 27	})
 28
 29	t.Run("handles nil client without panicking", func(t *testing.T) {
 30		// This test covers various edge cases where the error value might be
 31		// nil, a string, or an error type.
 32		originalClient := client
 33		defer func() {
 34			client = originalClient
 35		}()
 36
 37		client = nil
 38		Error(nil)
 39		Error("some error")
 40		Error(newDefaultTestError("runtime error"), "key", "value")
 41	})
 42
 43	t.Run("handles error with properties", func(t *testing.T) {
 44		// This test verifies that the Error function can handle additional
 45		// key-value properties that provide context about the error. These
 46		// properties are typically passed when recovering from panics (i.e.,
 47		// panic name, function name).
 48		//
 49		// Even with these additional properties, the function should handle
 50		// them gracefully without panicking.
 51		originalClient := client
 52		defer func() {
 53			client = originalClient
 54		}()
 55
 56		client = nil
 57		Error(
 58			"test error",
 59			"type", "test",
 60			"severity", "high",
 61			"source", "unit-test",
 62		)
 63	})
 64}
 65
 66func TestPairsToProps(t *testing.T) {
 67	t.Run("sets valid key value pairs", func(t *testing.T) {
 68		got := pairsToProps("foo", "bar", "count", 3)
 69		want := posthog.NewProperties().
 70			Set("foo", "bar").
 71			Set("count", 3)
 72		if !reflect.DeepEqual(got, want) {
 73			t.Fatalf("pairsToProps() = %#v, want %#v", got, want)
 74		}
 75	})
 76
 77	t.Run("returns empty properties for odd pairs", func(t *testing.T) {
 78		got := pairsToProps("foo", "bar", "count")
 79		if len(got) != 0 {
 80			t.Fatalf("pairsToProps() should return empty properties, got %#v", got)
 81		}
 82	})
 83
 84	t.Run("ignores non-string key and continues", func(t *testing.T) {
 85		got := pairsToProps(123, "bad", "ok", true)
 86		want := posthog.NewProperties().Set("ok", true)
 87		if !reflect.DeepEqual(got, want) {
 88			t.Fatalf("pairsToProps() = %#v, want %#v", got, want)
 89		}
 90	})
 91}
 92
 93// newDefaultTestError creates a test error that mimics runtime panic
 94// errors. This helps us testing that the Error function can handle various
 95// error types, including those that might be passed from a panic recovery
 96// scenario.
 97func newDefaultTestError(s string) error {
 98	return testError(s)
 99}
100
101type testError string
102
103func (e testError) Error() string {
104	return string(e)
105}