package client import ( "context" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" "edge-infra.dev/pkg/sds/emergencyaccess/eaconst" "edge-infra.dev/pkg/sds/emergencyaccess/types" ) func TestHTransport(t *testing.T) { t.Parallel() tests := map[string]struct { applyUser func(context.Context) context.Context headerAssertions func(*testing.T, *http.Request) }{ "No User": { // No user in context should not set the header at all applyUser: func(ctx context.Context) context.Context { return ctx }, headerAssertions: func(t *testing.T, r *http.Request) { // Nil indicates the header has not been set assert.Nil(t, r.Header.Values(eaconst.HeaderAuthKeyUsername)) assert.Nil(t, r.Header.Values(eaconst.HeaderAuthKeyEmail)) assert.Nil(t, r.Header.Values(eaconst.HeaderAuthKeyRoles)) assert.Nil(t, r.Header.Values(eaconst.HeaderAuthKeyBanners)) }, }, "Empty User": { // If empty user in context, user and email headers will be present, // and set to an empty string // The banners and roles headers will not be present applyUser: func(ctx context.Context) context.Context { ctx = types.UserIntoContext(ctx, types.User{}) return ctx }, headerAssertions: func(t *testing.T, r *http.Request) { // The header has been set to an empty value assert.Equal(t, []string{""}, r.Header.Values(eaconst.HeaderAuthKeyUsername)) assert.Equal(t, []string{""}, r.Header.Values(eaconst.HeaderAuthKeyEmail)) assert.Nil(t, r.Header.Values(eaconst.HeaderAuthKeyRoles)) assert.Nil(t, r.Header.Values(eaconst.HeaderAuthKeyBanners)) }, }, "Mixed empty and not empty fields": { // If the user struct has a mixture of empty and not empty fields, // the transport does a best effort of setting all headers it can // Note though, that unlike [Empty User], this time the email header // has been set to an empty value, but the banner header is nil as // expected applyUser: func(ctx context.Context) context.Context { ctx = types.UserIntoContext(ctx, types.User{ Username: "user", Roles: []string{"role1"}, }) return ctx }, headerAssertions: func(t *testing.T, r *http.Request) { assert.Equal(t, []string{"user"}, r.Header.Values(eaconst.HeaderAuthKeyUsername)) assert.Equal(t, []string{""}, r.Header.Values(eaconst.HeaderAuthKeyEmail)) assert.Equal(t, []string{"role1"}, r.Header.Values(eaconst.HeaderAuthKeyRoles)) assert.Nil(t, r.Header.Values(eaconst.HeaderAuthKeyBanners)) }, }, "User": { applyUser: func(ctx context.Context) context.Context { ctx = types.UserIntoContext(ctx, types.User{ Username: "abcd", Email: "abcd@efgh.xyz", Roles: []string{"role1", "role2"}, Banners: []string{"banner1", "banner2"}, }) return ctx }, headerAssertions: func(t *testing.T, r *http.Request) { assert.Equal(t, []string{"abcd"}, r.Header.Values(eaconst.HeaderAuthKeyUsername)) assert.Equal(t, []string{"abcd@efgh.xyz"}, r.Header.Values(eaconst.HeaderAuthKeyEmail)) assert.Equal(t, []string{"role1", "role2"}, r.Header.Values(eaconst.HeaderAuthKeyRoles)) assert.Equal(t, []string{"banner1", "banner2"}, r.Header.Values(eaconst.HeaderAuthKeyBanners)) }, }, } for name, tc := range tests { tc := tc t.Run(name, func(t *testing.T) { t.Parallel() server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { tc.headerAssertions(t, r) w.WriteHeader(200) })) ctx := tc.applyUser(context.Background()) req, err := http.NewRequestWithContext(ctx, http.MethodGet, server.URL, nil) assert.NoError(t, err) // Create a new client which uses HTransport client := New() _, err = client.Do(req) assert.NoError(t, err) }) } }