package events import ( "context" "errors" "fmt" "testing" "github.com/stretchr/testify/assert" ) func TestNew_Lifecycle(t *testing.T) { receives := make([][]int, 0) d := New() d.On("event", func(x int, y int) { receives = append(receives, []int{1, x, y}) }) d.On("event", func(x int) { receives = append(receives, []int{2, x}) }) d.On("event", func(x int, y string, z string) { receives = append(receives, []int{3, x, len(y)}) }) d.Fire("event", 123, 123) d.Fire("event", 234, 234) d.Fire("event", "string", "value") assert.Equal(t, [][]int{ {1, 123, 123}, {2, 123}, {3, 123, 0}, {1, 234, 234}, {2, 234}, {3, 234, 0}, {1, 0, 0}, {2, 0}, {3, 0, 5}, }, receives) } func TestFire(t *testing.T) { t.Run("should preserve context.Context", func(t *testing.T) { var wasFired bool d := New() d.On("event", func(ctx context.Context) { assert.NotNil(t, ctx) wasFired = true }) d.Fire("event", context.Background()) assert.True(t, wasFired) }) } func TestUnsubscribe(t *testing.T) { t.Run("should remove subscription 1", func(t *testing.T) { fired := make([]int, 3) d := New() s1 := d.On("event", func() { fired[0]++ }) s2 := d.On("event", func() { fired[1]++ }) s3 := d.On("event", func() { fired[2]++ }) d.Fire("event") assert.Equal(t, []int{1, 1, 1}, fired) s1.Unsubscribe() d.Fire("event") assert.Equal(t, []int{1, 2, 2}, fired) s2.Unsubscribe() d.Fire("event") assert.Equal(t, []int{1, 2, 3}, fired) s3.Unsubscribe() d.Fire("event") assert.Equal(t, []int{1, 2, 3}, fired) }) t.Run("should remove subscription 2", func(t *testing.T) { fired := make([]int, 3) d := New() s1 := d.On("event", func() { fired[0]++ }) s2 := d.On("event", func() { fired[1]++ }) s3 := d.On("event", func() { fired[2]++ }) d.Fire("event") assert.Equal(t, []int{1, 1, 1}, fired) s3.Unsubscribe() d.Fire("event") assert.Equal(t, []int{2, 2, 1}, fired) s2.Unsubscribe() d.Fire("event") assert.Equal(t, []int{3, 2, 1}, fired) s1.Unsubscribe() d.Fire("event") assert.Equal(t, []int{3, 2, 1}, fired) }) t.Run("should remove subscription 3", func(t *testing.T) { fired := make([]int, 3) d := New() s1 := d.On("event", func() { fired[0]++ }) s2 := d.On("event", func() { fired[1]++ }) s3 := d.On("event", func() { fired[2]++ }) d.Fire("event") assert.Equal(t, []int{1, 1, 1}, fired) s2.Unsubscribe() d.Fire("event") assert.Equal(t, []int{2, 1, 2}, fired) s1.Unsubscribe() d.Fire("event") assert.Equal(t, []int{2, 1, 3}, fired) s3.Unsubscribe() d.Fire("event") assert.Equal(t, []int{2, 1, 3}, fired) }) t.Run("should support new subscribers subscription", func(t *testing.T) { fired := make([]int, 3) d := New() d.On("event", func() { fired[0]++ }) s2 := d.On("event", func() { fired[1]++ }) d.Fire("event") assert.Equal(t, []int{1, 1, 0}, fired) s2.Unsubscribe() d.Fire("event") assert.Equal(t, []int{2, 1, 0}, fired) s3 := d.On("event", func() { fired[2]++ }) s2.Unsubscribe() d.Fire("event") assert.Equal(t, []int{3, 1, 1}, fired) s3.Unsubscribe() d.Fire("event") assert.Equal(t, []int{4, 1, 1}, fired) }) t.Run("should nop if no events", func(t *testing.T) { fired := false d := New() s1 := d.On("event", func() { fired = true }) s1.Unsubscribe() s1.Unsubscribe() d.Fire("event") assert.False(t, fired) }) } func TestTryFire(t *testing.T) { errVal := errors.New("bang") tests := []struct { errsRet [3]error wantErr bool }{ { errsRet: [3]error{nil, nil, nil}, wantErr: false, }, { errsRet: [3]error{errVal, nil, nil}, wantErr: true, }, { errsRet: [3]error{nil, errVal, nil}, wantErr: true, }, { errsRet: [3]error{nil, nil, errVal}, wantErr: true, }, { errsRet: [3]error{errVal, nil, errVal}, wantErr: true, }, } for i, tt := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { d := New() var handlersFired [4]bool d.On("event", func() error { handlersFired[0] = true; return tt.errsRet[0] }) d.On("event", func(x int) error { handlersFired[1] = true; return tt.errsRet[1] }) d.On("event", func(x int, y string) error { handlersFired[2] = true; return tt.errsRet[2] }) d.On("event", func(x string, y string) { handlersFired[3] = true }) err := d.TryFire("event") if tt.wantErr { assert.Error(t, err) } else { assert.NoError(t, err) } assert.Equal(t, [4]bool{true, true, true, true}, handlersFired) }) } }