Skip to content

Commit ca24d8a

Browse files
Add unit tests for internal/service module
1 parent 2e617fe commit ca24d8a

File tree

1 file changed

+289
-0
lines changed

1 file changed

+289
-0
lines changed

internal/services/services_test.go

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
package services
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/h2non/gock"
8+
"github.com/spf13/afero"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
"github.com/supabase/cli/internal/utils"
12+
"github.com/supabase/cli/internal/utils/flags"
13+
)
14+
15+
// TestRun tests the main Run function that displays service versions
16+
func TestRun(t *testing.T) {
17+
// Test case: Display service versions without linked project
18+
t.Run("displays service versions without linked project", func(t *testing.T) {
19+
// Setup: Create an in-memory filesystem
20+
fsys := afero.NewMemMapFs()
21+
22+
// Execute: Call the Run function
23+
err := Run(context.Background(), fsys)
24+
25+
// Verify: Check that no error occurred
26+
assert.NoError(t, err)
27+
})
28+
29+
// Test case: Display service versions with linked project
30+
t.Run("displays service versions with linked project", func(t *testing.T) {
31+
// Setup: Create an in-memory filesystem and simulate linked project
32+
fsys := afero.NewMemMapFs()
33+
34+
// Create project config file with project reference
35+
projectRef := "test-project-ref"
36+
require.NoError(t, utils.InitConfig(utils.InitParams{
37+
ProjectId: projectRef,
38+
}, fsys))
39+
40+
// Set project reference in flags
41+
flags.ProjectRef = projectRef
42+
43+
// Execute: Call the Run function
44+
err := Run(context.Background(), fsys)
45+
46+
// Verify: Check that no error occurred
47+
assert.NoError(t, err)
48+
})
49+
}
50+
51+
// TestCheckVersions tests the function that checks local and remote service versions
52+
func TestCheckVersions(t *testing.T) {
53+
// Test case: Check local versions only
54+
t.Run("checks local versions", func(t *testing.T) {
55+
// Setup: Create an in-memory filesystem
56+
fsys := afero.NewMemMapFs()
57+
58+
// Execute: Call CheckVersions function
59+
versions := CheckVersions(context.Background(), fsys)
60+
61+
// Verify: Check that versions are returned and contain required fields
62+
assert.NotEmpty(t, versions)
63+
for _, v := range versions {
64+
assert.NotEmpty(t, v.Name, "Service name should not be empty")
65+
assert.NotEmpty(t, v.Local, "Local version should not be empty")
66+
}
67+
})
68+
69+
// Test case: Check both local and remote versions
70+
t.Run("checks local and remote versions", func(t *testing.T) {
71+
// Setup: Create an in-memory filesystem and simulate linked project
72+
fsys := afero.NewMemMapFs()
73+
74+
// Create project config file with project reference
75+
projectRef := "test-project-ref"
76+
require.NoError(t, utils.InitConfig(utils.InitParams{
77+
ProjectId: projectRef,
78+
}, fsys))
79+
80+
// Set project reference in flags
81+
flags.ProjectRef = projectRef
82+
83+
// Execute: Call CheckVersions function
84+
versions := CheckVersions(context.Background(), fsys)
85+
86+
// Verify: Check that versions are returned and contain required fields
87+
assert.NotEmpty(t, versions)
88+
for _, v := range versions {
89+
assert.NotEmpty(t, v.Name, "Service name should not be empty")
90+
assert.NotEmpty(t, v.Local, "Local version should not be empty")
91+
// Remote version might be empty if not linked
92+
}
93+
})
94+
95+
// Test case: Handle version mismatch
96+
t.Run("handles version mismatch", func(t *testing.T) {
97+
// Setup: Create an in-memory filesystem and simulate linked project
98+
fsys := afero.NewMemMapFs()
99+
100+
// Create project config file with project reference
101+
projectRef := "test-project-ref"
102+
require.NoError(t, utils.InitConfig(utils.InitParams{
103+
ProjectId: projectRef,
104+
}, fsys))
105+
106+
// Set project reference in flags
107+
flags.ProjectRef = projectRef
108+
109+
// Execute: Call CheckVersions function
110+
versions := CheckVersions(context.Background(), fsys)
111+
112+
// Verify: Check that versions are returned and contain required fields
113+
assert.NotEmpty(t, versions)
114+
for _, v := range versions {
115+
assert.NotEmpty(t, v.Name, "Service name should not be empty")
116+
assert.NotEmpty(t, v.Local, "Local version should not be empty")
117+
// Remote version might be empty if not linked
118+
}
119+
})
120+
121+
// Test case: Verify version comparison logic
122+
t.Run("compares local and remote versions correctly", func(t *testing.T) {
123+
fsys := afero.NewMemMapFs()
124+
projectRef := "test-project-ref"
125+
126+
// Setup: Create linked project with specific versions
127+
require.NoError(t, utils.InitConfig(utils.InitParams{
128+
ProjectId: projectRef,
129+
}, fsys))
130+
flags.ProjectRef = projectRef
131+
132+
// Mock remote versions
133+
token := "sbp_0102030405060708091011121314151617181920"
134+
require.NoError(t, utils.SaveAccessToken(token, fsys))
135+
136+
defer gock.OffAll()
137+
// Mock API responses with specific versions
138+
gock.New(utils.DefaultApiHost).
139+
Get("/v1/projects/" + projectRef + "/api-keys").
140+
Reply(200).
141+
JSON([]map[string]string{{"name": "anon", "api_key": "test-key"}})
142+
143+
gock.New(utils.DefaultApiHost).
144+
Get("/v1/projects/" + projectRef + "/database/version").
145+
Reply(200).
146+
JSON(map[string]string{"version": "1.0.0"})
147+
148+
versions := CheckVersions(context.Background(), fsys)
149+
150+
// Verify version comparison logic
151+
for _, v := range versions {
152+
assert.NotEmpty(t, v.Name)
153+
assert.NotEmpty(t, v.Local)
154+
// Check if remote versions are properly assigned
155+
}
156+
})
157+
}
158+
159+
// TestListRemoteImages tests the function that retrieves remote service versions
160+
func TestListRemoteImages(t *testing.T) {
161+
// Test case: Get remote versions successfully
162+
t.Run("gets remote versions successfully", func(t *testing.T) {
163+
// Setup: Create context and project reference
164+
ctx := context.Background()
165+
projectRef := "test-project-ref"
166+
167+
// Setup: Create in-memory filesystem
168+
fsys := afero.NewMemMapFs()
169+
170+
// Setup: Create access token file with valid format
171+
token := "sbp_0102030405060708091011121314151617181920"
172+
require.NoError(t, utils.SaveAccessToken(token, fsys))
173+
174+
// Setup: Mock API responses
175+
defer gock.OffAll()
176+
177+
// Mock API keys response
178+
gock.New(utils.DefaultApiHost).
179+
Get("/v1/projects/" + projectRef + "/api-keys").
180+
Reply(200).
181+
JSON([]map[string]string{
182+
{"name": "anon", "api_key": "test-key"},
183+
})
184+
185+
// Mock database version response
186+
gock.New(utils.DefaultApiHost).
187+
Get("/v1/projects/" + projectRef + "/database/version").
188+
Reply(200).
189+
JSON(map[string]string{"version": "1.0.0"})
190+
191+
// Mock auth version response
192+
gock.New(utils.DefaultApiHost).
193+
Get("/auth/v1/version").
194+
Reply(200).
195+
JSON(map[string]string{"version": "2.0.0"})
196+
197+
// Mock postgrest version response
198+
gock.New(utils.DefaultApiHost).
199+
Get("/rest/v1/version").
200+
Reply(200).
201+
JSON(map[string]string{"version": "3.0.0"})
202+
203+
// Execute: Call listRemoteImages function
204+
remoteVersions := listRemoteImages(ctx, projectRef)
205+
206+
// Verify: Check that remote versions are returned
207+
assert.NotNil(t, remoteVersions)
208+
assert.NotEmpty(t, remoteVersions)
209+
210+
// Verify: Check that all expected versions are present
211+
for _, version := range remoteVersions {
212+
assert.NotEmpty(t, version)
213+
}
214+
})
215+
216+
// Test case: Handle API errors
217+
t.Run("handles API errors", func(t *testing.T) {
218+
// Setup: Create context and project reference
219+
ctx := context.Background()
220+
projectRef := "invalid-project"
221+
222+
// Setup: Create in-memory filesystem
223+
fsys := afero.NewMemMapFs()
224+
225+
// Setup: Create access token file with valid format
226+
token := "sbp_0102030405060708091011121314151617181920"
227+
require.NoError(t, utils.SaveAccessToken(token, fsys))
228+
229+
// Setup: Mock API error response
230+
defer gock.OffAll()
231+
gock.New(utils.DefaultApiHost).
232+
Get("/v1/projects/" + projectRef + "/api-keys").
233+
Reply(404)
234+
235+
// Execute: Call listRemoteImages function
236+
remoteVersions := listRemoteImages(ctx, projectRef)
237+
238+
// Verify: Check that remote versions are empty
239+
assert.Empty(t, remoteVersions)
240+
})
241+
242+
// Test case: Handle missing access token
243+
t.Run("handles missing access token", func(t *testing.T) {
244+
// Setup: Create context and project reference
245+
ctx := context.Background()
246+
projectRef := "test-project-ref"
247+
248+
// Setup: Create in-memory filesystem without access token
249+
afero.NewMemMapFs()
250+
251+
// Execute: Call listRemoteImages function
252+
remoteVersions := listRemoteImages(ctx, projectRef)
253+
254+
// Verify: Check that remote versions are empty
255+
assert.Empty(t, remoteVersions)
256+
})
257+
}
258+
259+
// TestSuggestUpdateCmd tests the function that generates update command suggestions
260+
func TestSuggestUpdateCmd(t *testing.T) {
261+
// Test case: Generate update command for version mismatch
262+
t.Run("generates update command for version mismatch", func(t *testing.T) {
263+
// Setup: Create map of service images with version mismatches
264+
serviceImages := map[string]string{
265+
"service1": "v1.0.0",
266+
"service2": "v2.0.0",
267+
}
268+
269+
// Execute: Call suggestUpdateCmd function
270+
cmd := suggestUpdateCmd(serviceImages)
271+
272+
// Verify: Check that command contains expected content
273+
assert.Contains(t, cmd, "WARNING:")
274+
assert.Contains(t, cmd, "supabase link")
275+
})
276+
277+
// Test case: Handle empty service images
278+
t.Run("handles empty service images", func(t *testing.T) {
279+
// Setup: Create empty map of service images
280+
serviceImages := map[string]string{}
281+
282+
// Execute: Call suggestUpdateCmd function
283+
cmd := suggestUpdateCmd(serviceImages)
284+
285+
// Verify: Check that command contains expected content
286+
assert.Contains(t, cmd, "WARNING:")
287+
assert.Contains(t, cmd, "supabase link")
288+
})
289+
}

0 commit comments

Comments
 (0)