Skip to content

Commit 1d4b930

Browse files
committed
Add durable profile acceptance fixtures
1 parent f8d064d commit 1d4b930

4 files changed

Lines changed: 193 additions & 0 deletions

File tree

internal/acctest/acctest.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,48 @@ func cleanupProject(t testing.TB, client projectCleaner, id string) {
159159
})
160160
}
161161

162+
// CleanupProfile registers a cleanup that deletes the profile from projectID;
163+
// empty means the env-configured default project.
164+
func CleanupProfile(t testing.TB, projectID, id string) {
165+
t.Helper()
166+
167+
cleanupProfile(t, ClientFromEnv(), projectID, id)
168+
}
169+
170+
type profileCleaner interface {
171+
DefaultProjectID() string
172+
DeleteProfile(context.Context, string, string) error
173+
}
174+
175+
func cleanupProfile(t testing.TB, client profileCleaner, projectID, id string) {
176+
t.Helper()
177+
178+
if id == "" {
179+
return
180+
}
181+
if !AcceptanceEnabled() {
182+
t.Fatalf("%s must be set to clean up Kernel acceptance test resources", EnvAcceptance)
183+
return
184+
}
185+
if os.Getenv(EnvAPIKey) == "" {
186+
t.Fatalf("%s must be set to clean up Kernel acceptance test resources", EnvAPIKey)
187+
return
188+
}
189+
190+
if projectID == "" {
191+
projectID = client.DefaultProjectID()
192+
}
193+
194+
t.Cleanup(func() {
195+
ctx, cancel := context.WithTimeout(context.Background(), cleanupTimeout)
196+
defer cancel()
197+
198+
if err := client.DeleteProfile(ctx, projectID, id); err != nil && !IsNotFound(err) {
199+
t.Errorf("cleanup Kernel profile %s: %v", id, err)
200+
}
201+
})
202+
}
203+
162204
func ClientFromEnv() kernelclient.Clients {
163205
return kernelclient.New(kernelclient.Config{
164206
APIKey: os.Getenv(EnvAPIKey),

internal/acctest/profile_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package acctest
2+
3+
import (
4+
"context"
5+
"errors"
6+
"testing"
7+
)
8+
9+
type fakeProfileCleaner struct {
10+
defaultProjectID string
11+
delete func(context.Context, string, string) error
12+
}
13+
14+
func (f fakeProfileCleaner) DefaultProjectID() string {
15+
return f.defaultProjectID
16+
}
17+
18+
func (f fakeProfileCleaner) DeleteProfile(ctx context.Context, projectID, id string) error {
19+
return f.delete(ctx, projectID, id)
20+
}
21+
22+
func TestCleanupProfile(t *testing.T) {
23+
tests := map[string]struct {
24+
acceptance string
25+
apiKey string
26+
projectID string
27+
defaultProject string
28+
id string
29+
deleteErr error
30+
wantProjectID string
31+
wantCleanups int
32+
wantDelete bool
33+
wantFailure bool
34+
}{
35+
"empty ID is ignored": {},
36+
"acceptance disabled": {
37+
apiKey: "test-key",
38+
id: "profile_123",
39+
wantFailure: true,
40+
},
41+
"API key missing": {
42+
acceptance: "1",
43+
id: "profile_123",
44+
wantFailure: true,
45+
},
46+
"default project is resolved": {
47+
acceptance: "1",
48+
apiKey: "test-key",
49+
defaultProject: "project_default",
50+
id: "profile_123",
51+
wantProjectID: "project_default",
52+
wantCleanups: 1,
53+
wantDelete: true,
54+
},
55+
"not found is already clean": {
56+
acceptance: "1",
57+
apiKey: "test-key",
58+
projectID: "project_explicit",
59+
id: "profile_123",
60+
deleteErr: notFoundAPIError(),
61+
wantProjectID: "project_explicit",
62+
wantCleanups: 1,
63+
wantDelete: true,
64+
},
65+
"delete error is reported": {
66+
acceptance: "1",
67+
apiKey: "test-key",
68+
projectID: "project_explicit",
69+
id: "profile_123",
70+
deleteErr: errors.New("connection reset"),
71+
wantProjectID: "project_explicit",
72+
wantCleanups: 1,
73+
wantDelete: true,
74+
wantFailure: true,
75+
},
76+
}
77+
78+
for name, test := range tests {
79+
t.Run(name, func(t *testing.T) {
80+
t.Setenv(EnvAcceptance, test.acceptance)
81+
t.Setenv(EnvAPIKey, test.apiKey)
82+
83+
var gotID, gotProjectID string
84+
deleteCalled := false
85+
deadlineSet := false
86+
recorder := &testRecorder{TB: t}
87+
cleanupProfile(recorder, fakeProfileCleaner{
88+
defaultProjectID: test.defaultProject,
89+
delete: func(ctx context.Context, projectID, id string) error {
90+
deleteCalled = true
91+
_, deadlineSet = ctx.Deadline()
92+
gotProjectID = projectID
93+
gotID = id
94+
return test.deleteErr
95+
},
96+
}, test.projectID, test.id)
97+
98+
if got, want := len(recorder.cleanups), test.wantCleanups; got != want {
99+
t.Fatalf("cleanupProfile registered %d cleanups, want %d", got, want)
100+
}
101+
if test.wantCleanups == 1 {
102+
recorder.cleanups[0]()
103+
}
104+
if recorder.failed != test.wantFailure {
105+
t.Fatalf("cleanupProfile failure = %t, want %t", recorder.failed, test.wantFailure)
106+
}
107+
if deleteCalled != test.wantDelete {
108+
t.Fatalf("cleanupProfile called delete = %t, want %t", deleteCalled, test.wantDelete)
109+
}
110+
if deleteCalled && !deadlineSet {
111+
t.Fatal("cleanupProfile called delete without a context deadline")
112+
}
113+
if test.wantDelete && (gotID != test.id || gotProjectID != test.wantProjectID) {
114+
t.Fatalf("cleanup profile scope/id = %q/%q, want %q/%q", gotProjectID, gotID, test.wantProjectID, test.id)
115+
}
116+
})
117+
}
118+
}

internal/kernelclient/client.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ func (c Clients) GetProfile(ctx context.Context, projectID, idOrName string) (*k
134134
return c.profiles.Get(ctx, idOrName, scope(projectID)...)
135135
}
136136

137+
func (c Clients) CreateProfile(ctx context.Context, projectID string, params kernel.ProfileNewParams) (*kernel.Profile, error) {
138+
return c.profiles.New(ctx, params, scope(projectID, noMutationRetries())...)
139+
}
140+
141+
func (c Clients) DeleteProfile(ctx context.Context, projectID, idOrName string) error {
142+
return c.profiles.Delete(ctx, idOrName, scope(projectID, noMutationRetries())...)
143+
}
144+
137145
func (c Clients) ListProfilePage(ctx context.Context, projectID, query string, offset int64) (ProfilePage, error) {
138146
var raw *http.Response
139147
params := kernel.ProfileListParams{

internal/kernelclient/client_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,23 @@ func TestMutationsDisableSDKRetriesAndUseExpectedScope(t *testing.T) {
333333
return clients.DeleteProject(ctx, "project_123")
334334
},
335335
},
336+
"profile create": {
337+
method: http.MethodPost,
338+
path: "/profiles",
339+
projectID: "project_123",
340+
call: func(ctx context.Context, clients Clients) error {
341+
_, err := clients.CreateProfile(ctx, "project_123", kernel.ProfileNewParams{Name: kernel.String("Profile")})
342+
return err
343+
},
344+
},
345+
"profile delete": {
346+
method: http.MethodDelete,
347+
path: "/profiles/profile_123",
348+
projectID: "project_123",
349+
call: func(ctx context.Context, clients Clients) error {
350+
return clients.DeleteProfile(ctx, "project_123", "profile_123")
351+
},
352+
},
336353
"browser pool create": {
337354
method: http.MethodPost,
338355
path: "/browser_pools",
@@ -443,6 +460,14 @@ func TestClientsDoNotExposeRuntimeBrowserPoolMethods(t *testing.T) {
443460
}
444461
}
445462

463+
func TestClientsDoNotExposeProfileArchiveMethods(t *testing.T) {
464+
t.Parallel()
465+
466+
if _, ok := reflect.TypeOf(Clients{}).MethodByName("DownloadProfile"); ok {
467+
t.Fatal("Clients exposes profile archive download")
468+
}
469+
}
470+
446471
type capturedRequest struct {
447472
Method string
448473
Path string

0 commit comments

Comments
 (0)