Skip to content

Commit 679f873

Browse files
chore: add some utils tests (#3514)
* chore: add parse db url tests * chore: add cloudflare basic tests * chore: add cred store tests * chore: add some tenant keys tests * chore: more utils tests * chore: add utils misc tests * chore: rm some files from coverage * chore: lint fixes * Update .github/workflows/ci.yml * chore: update unit tests * fix race in test * chore: rm wsl tests --------- Co-authored-by: Han Qiao <[email protected]> Co-authored-by: Qiao Han <[email protected]>
1 parent 5d1fa9c commit 679f873

File tree

11 files changed

+1338
-2
lines changed

11 files changed

+1338
-2
lines changed

internal/utils/cloudflare/dns_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package cloudflare
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"testing"
7+
8+
"github.com/h2non/gock"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/supabase/cli/internal/testing/apitest"
11+
)
12+
13+
func TestDNSQuery(t *testing.T) {
14+
t.Run("successfully queries A records", func(t *testing.T) {
15+
api := NewCloudflareAPI()
16+
defer gock.OffAll()
17+
gock.New("https://1.1.1.1").
18+
Get("/dns-query").
19+
MatchParam("name", "example.com").
20+
MatchHeader("accept", "application/dns-json").
21+
Reply(http.StatusOK).
22+
JSON(DNSResponse{
23+
Answer: []DNSAnswer{
24+
{
25+
Name: "example.com",
26+
Type: TypeA,
27+
Ttl: 300,
28+
Data: "93.184.216.34",
29+
},
30+
},
31+
})
32+
33+
resp, err := api.DNSQuery(context.Background(), DNSParams{
34+
Name: "example.com",
35+
})
36+
37+
assert.NoError(t, err)
38+
assert.Len(t, resp.Answer, 1)
39+
assert.Equal(t, "93.184.216.34", resp.Answer[0].Data)
40+
assert.Equal(t, TypeA, resp.Answer[0].Type)
41+
assert.Empty(t, apitest.ListUnmatchedRequests())
42+
})
43+
44+
t.Run("successfully queries specific DNS type", func(t *testing.T) {
45+
api := NewCloudflareAPI()
46+
dnsType := TypeCNAME
47+
defer gock.OffAll()
48+
gock.New("https://1.1.1.1").
49+
Get("/dns-query").
50+
MatchParam("name", "www.example.com").
51+
MatchParam("type", "5"). // TypeCNAME = 5
52+
MatchHeader("accept", "application/dns-json").
53+
Reply(http.StatusOK).
54+
JSON(DNSResponse{
55+
Answer: []DNSAnswer{
56+
{
57+
Name: "www.example.com",
58+
Type: TypeCNAME,
59+
Ttl: 3600,
60+
Data: "example.com",
61+
},
62+
},
63+
})
64+
65+
resp, err := api.DNSQuery(context.Background(), DNSParams{
66+
Name: "www.example.com",
67+
Type: &dnsType,
68+
})
69+
70+
assert.NoError(t, err)
71+
assert.Len(t, resp.Answer, 1)
72+
assert.Equal(t, "example.com", resp.Answer[0].Data)
73+
assert.Equal(t, TypeCNAME, resp.Answer[0].Type)
74+
assert.Empty(t, apitest.ListUnmatchedRequests())
75+
})
76+
77+
t.Run("handles network error", func(t *testing.T) {
78+
api := NewCloudflareAPI()
79+
defer gock.OffAll()
80+
gock.New("https://1.1.1.1").
81+
Get("/dns-query").
82+
MatchParam("name", "example.com").
83+
ReplyError(gock.ErrCannotMatch)
84+
85+
resp, err := api.DNSQuery(context.Background(), DNSParams{
86+
Name: "example.com",
87+
})
88+
89+
assert.Error(t, err)
90+
assert.Empty(t, resp.Answer)
91+
assert.Empty(t, apitest.ListUnmatchedRequests())
92+
})
93+
94+
t.Run("handles service unavailable", func(t *testing.T) {
95+
api := NewCloudflareAPI()
96+
defer gock.OffAll()
97+
gock.New("https://1.1.1.1").
98+
Get("/dns-query").
99+
MatchParam("name", "example.com").
100+
Reply(http.StatusServiceUnavailable)
101+
102+
resp, err := api.DNSQuery(context.Background(), DNSParams{
103+
Name: "example.com",
104+
})
105+
106+
assert.ErrorContains(t, err, "status 503")
107+
assert.Empty(t, resp.Answer)
108+
assert.Empty(t, apitest.ListUnmatchedRequests())
109+
})
110+
111+
t.Run("handles malformed response", func(t *testing.T) {
112+
api := NewCloudflareAPI()
113+
defer gock.OffAll()
114+
gock.New("https://1.1.1.1").
115+
Get("/dns-query").
116+
MatchParam("name", "example.com").
117+
Reply(http.StatusOK).
118+
JSON("invalid json")
119+
120+
resp, err := api.DNSQuery(context.Background(), DNSParams{
121+
Name: "example.com",
122+
})
123+
124+
assert.ErrorContains(t, err, "failed to parse")
125+
assert.Empty(t, resp.Answer)
126+
assert.Empty(t, apitest.ListUnmatchedRequests())
127+
})
128+
}

internal/utils/config_test.go

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
package utils
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/spf13/afero"
8+
"github.com/spf13/viper"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestGetId(t *testing.T) {
14+
t.Run("generates container id", func(t *testing.T) {
15+
Config.ProjectId = "test-project"
16+
name := "test-service"
17+
18+
id := GetId(name)
19+
20+
assert.Equal(t, "supabase_test-service_test-project", id)
21+
})
22+
}
23+
24+
func TestUpdateDockerIds(t *testing.T) {
25+
t.Run("updates all container ids", func(t *testing.T) {
26+
Config.ProjectId = "test-project"
27+
viper.Set("network-id", "custom-network")
28+
defer viper.Reset()
29+
30+
UpdateDockerIds()
31+
32+
assert.Equal(t, "custom-network", NetId)
33+
assert.Equal(t, "supabase_db_test-project", DbId)
34+
assert.Equal(t, "supabase_kong_test-project", KongId)
35+
assert.Equal(t, "supabase_auth_test-project", GotrueId)
36+
assert.Equal(t, "supabase_inbucket_test-project", InbucketId)
37+
assert.Equal(t, "supabase_realtime_test-project", RealtimeId)
38+
assert.Equal(t, "supabase_rest_test-project", RestId)
39+
assert.Equal(t, "supabase_storage_test-project", StorageId)
40+
assert.Equal(t, "supabase_imgproxy_test-project", ImgProxyId)
41+
assert.Equal(t, "supabase_differ_test-project", DifferId)
42+
assert.Equal(t, "supabase_pg_meta_test-project", PgmetaId)
43+
assert.Equal(t, "supabase_studio_test-project", StudioId)
44+
assert.Equal(t, "supabase_edge_runtime_test-project", EdgeRuntimeId)
45+
assert.Equal(t, "supabase_analytics_test-project", LogflareId)
46+
assert.Equal(t, "supabase_vector_test-project", VectorId)
47+
assert.Equal(t, "supabase_pooler_test-project", PoolerId)
48+
})
49+
50+
t.Run("generates network id if not set", func(t *testing.T) {
51+
Config.ProjectId = "test-project"
52+
viper.Reset()
53+
54+
UpdateDockerIds()
55+
56+
assert.Equal(t, "supabase_network_test-project", NetId)
57+
})
58+
}
59+
60+
func TestInitConfig(t *testing.T) {
61+
t.Run("creates new config file", func(t *testing.T) {
62+
fsys := afero.NewMemMapFs()
63+
params := InitParams{
64+
ProjectId: "test-project",
65+
}
66+
67+
err := InitConfig(params, fsys)
68+
69+
assert.NoError(t, err)
70+
exists, err := afero.Exists(fsys, ConfigPath)
71+
assert.NoError(t, err)
72+
assert.True(t, exists)
73+
})
74+
75+
t.Run("creates config with orioledb", func(t *testing.T) {
76+
fsys := afero.NewMemMapFs()
77+
params := InitParams{
78+
ProjectId: "test-project",
79+
UseOrioleDB: true,
80+
}
81+
82+
err := InitConfig(params, fsys)
83+
84+
assert.NoError(t, err)
85+
content, err := afero.ReadFile(fsys, ConfigPath)
86+
assert.NoError(t, err)
87+
assert.Contains(t, string(content), "15.1.0.150")
88+
})
89+
90+
t.Run("fails if config exists and no overwrite", func(t *testing.T) {
91+
fsys := afero.NewMemMapFs()
92+
err := afero.WriteFile(fsys, ConfigPath, []byte("existing"), 0644)
93+
require.NoError(t, err)
94+
params := InitParams{
95+
ProjectId: "test-project",
96+
}
97+
98+
err = InitConfig(params, fsys)
99+
100+
assert.ErrorIs(t, err, os.ErrExist)
101+
})
102+
103+
t.Run("overwrites existing config when specified", func(t *testing.T) {
104+
fsys := afero.NewMemMapFs()
105+
err := afero.WriteFile(fsys, ConfigPath, []byte("existing"), 0644)
106+
require.NoError(t, err)
107+
params := InitParams{
108+
ProjectId: "test-project",
109+
Overwrite: true,
110+
}
111+
112+
err = InitConfig(params, fsys)
113+
114+
assert.NoError(t, err)
115+
content, err := afero.ReadFile(fsys, ConfigPath)
116+
assert.NoError(t, err)
117+
assert.NotEqual(t, "existing", string(content))
118+
})
119+
}
120+
121+
func TestGetApiUrl(t *testing.T) {
122+
t.Run("returns external url when configured", func(t *testing.T) {
123+
Config.Api.ExternalUrl = "https://api.example.com"
124+
125+
url := GetApiUrl("/test")
126+
127+
assert.Equal(t, "https://api.example.com/test", url)
128+
})
129+
130+
t.Run("builds url from hostname and port", func(t *testing.T) {
131+
Config.Hostname = "localhost"
132+
Config.Api.Port = 8000
133+
Config.Api.ExternalUrl = ""
134+
135+
url := GetApiUrl("/test")
136+
137+
assert.Equal(t, "http://localhost:8000/test", url)
138+
})
139+
}
140+
141+
func TestRootFS(t *testing.T) {
142+
t.Run("opens file from root fs", func(t *testing.T) {
143+
fsys := afero.NewMemMapFs()
144+
content := []byte("test content")
145+
err := afero.WriteFile(fsys, "/test.txt", content, 0644)
146+
require.NoError(t, err)
147+
148+
rootfs := NewRootFS(fsys)
149+
f, err := rootfs.Open("/test.txt")
150+
assert.NoError(t, err)
151+
defer f.Close()
152+
153+
buf := make([]byte, len(content))
154+
n, err := f.Read(buf)
155+
assert.NoError(t, err)
156+
assert.Equal(t, len(content), n)
157+
assert.Equal(t, content, buf)
158+
})
159+
160+
t.Run("returns error for non-existent file", func(t *testing.T) {
161+
fsys := afero.NewMemMapFs()
162+
rootfs := NewRootFS(fsys)
163+
164+
_, err := rootfs.Open("/non-existent.txt")
165+
166+
assert.Error(t, err)
167+
})
168+
}

0 commit comments

Comments
 (0)