Skip to content

chore: add some utils tests #3514

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
May 5, 2025
128 changes: 128 additions & 0 deletions internal/utils/cloudflare/dns_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package cloudflare

import (
"context"
"net/http"
"testing"

"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/supabase/cli/internal/testing/apitest"
)

func TestDNSQuery(t *testing.T) {
t.Run("successfully queries A records", func(t *testing.T) {
api := NewCloudflareAPI()
defer gock.OffAll()
gock.New("https://1.1.1.1").
Get("/dns-query").
MatchParam("name", "example.com").
MatchHeader("accept", "application/dns-json").
Reply(http.StatusOK).
JSON(DNSResponse{
Answer: []DNSAnswer{
{
Name: "example.com",
Type: TypeA,
Ttl: 300,
Data: "93.184.216.34",
},
},
})

resp, err := api.DNSQuery(context.Background(), DNSParams{
Name: "example.com",
})

assert.NoError(t, err)
assert.Len(t, resp.Answer, 1)
assert.Equal(t, "93.184.216.34", resp.Answer[0].Data)
assert.Equal(t, TypeA, resp.Answer[0].Type)
assert.Empty(t, apitest.ListUnmatchedRequests())
})

t.Run("successfully queries specific DNS type", func(t *testing.T) {
api := NewCloudflareAPI()
dnsType := TypeCNAME
defer gock.OffAll()
gock.New("https://1.1.1.1").
Get("/dns-query").
MatchParam("name", "www.example.com").
MatchParam("type", "5"). // TypeCNAME = 5
MatchHeader("accept", "application/dns-json").
Reply(http.StatusOK).
JSON(DNSResponse{
Answer: []DNSAnswer{
{
Name: "www.example.com",
Type: TypeCNAME,
Ttl: 3600,
Data: "example.com",
},
},
})

resp, err := api.DNSQuery(context.Background(), DNSParams{
Name: "www.example.com",
Type: &dnsType,
})

assert.NoError(t, err)
assert.Len(t, resp.Answer, 1)
assert.Equal(t, "example.com", resp.Answer[0].Data)
assert.Equal(t, TypeCNAME, resp.Answer[0].Type)
assert.Empty(t, apitest.ListUnmatchedRequests())
})

t.Run("handles network error", func(t *testing.T) {
api := NewCloudflareAPI()
defer gock.OffAll()
gock.New("https://1.1.1.1").
Get("/dns-query").
MatchParam("name", "example.com").
ReplyError(gock.ErrCannotMatch)

resp, err := api.DNSQuery(context.Background(), DNSParams{
Name: "example.com",
})

assert.Error(t, err)
assert.Empty(t, resp.Answer)
assert.Empty(t, apitest.ListUnmatchedRequests())
})

t.Run("handles service unavailable", func(t *testing.T) {
api := NewCloudflareAPI()
defer gock.OffAll()
gock.New("https://1.1.1.1").
Get("/dns-query").
MatchParam("name", "example.com").
Reply(http.StatusServiceUnavailable)

resp, err := api.DNSQuery(context.Background(), DNSParams{
Name: "example.com",
})

assert.ErrorContains(t, err, "status 503")
assert.Empty(t, resp.Answer)
assert.Empty(t, apitest.ListUnmatchedRequests())
})

t.Run("handles malformed response", func(t *testing.T) {
api := NewCloudflareAPI()
defer gock.OffAll()
gock.New("https://1.1.1.1").
Get("/dns-query").
MatchParam("name", "example.com").
Reply(http.StatusOK).
JSON("invalid json")

resp, err := api.DNSQuery(context.Background(), DNSParams{
Name: "example.com",
})

assert.ErrorContains(t, err, "failed to parse")
assert.Empty(t, resp.Answer)
assert.Empty(t, apitest.ListUnmatchedRequests())
})
}
168 changes: 168 additions & 0 deletions internal/utils/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package utils

import (
"os"
"testing"

"github.com/spf13/afero"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGetId(t *testing.T) {
t.Run("generates container id", func(t *testing.T) {
Config.ProjectId = "test-project"
name := "test-service"

id := GetId(name)

assert.Equal(t, "supabase_test-service_test-project", id)
})
}

func TestUpdateDockerIds(t *testing.T) {
t.Run("updates all container ids", func(t *testing.T) {
Config.ProjectId = "test-project"
viper.Set("network-id", "custom-network")
defer viper.Reset()

UpdateDockerIds()

assert.Equal(t, "custom-network", NetId)
assert.Equal(t, "supabase_db_test-project", DbId)
assert.Equal(t, "supabase_kong_test-project", KongId)
assert.Equal(t, "supabase_auth_test-project", GotrueId)
assert.Equal(t, "supabase_inbucket_test-project", InbucketId)
assert.Equal(t, "supabase_realtime_test-project", RealtimeId)
assert.Equal(t, "supabase_rest_test-project", RestId)
assert.Equal(t, "supabase_storage_test-project", StorageId)
assert.Equal(t, "supabase_imgproxy_test-project", ImgProxyId)
assert.Equal(t, "supabase_differ_test-project", DifferId)
assert.Equal(t, "supabase_pg_meta_test-project", PgmetaId)
assert.Equal(t, "supabase_studio_test-project", StudioId)
assert.Equal(t, "supabase_edge_runtime_test-project", EdgeRuntimeId)
assert.Equal(t, "supabase_analytics_test-project", LogflareId)
assert.Equal(t, "supabase_vector_test-project", VectorId)
assert.Equal(t, "supabase_pooler_test-project", PoolerId)
})

t.Run("generates network id if not set", func(t *testing.T) {
Config.ProjectId = "test-project"
viper.Reset()

UpdateDockerIds()

assert.Equal(t, "supabase_network_test-project", NetId)
})
}

func TestInitConfig(t *testing.T) {
t.Run("creates new config file", func(t *testing.T) {
fsys := afero.NewMemMapFs()
params := InitParams{
ProjectId: "test-project",
}

err := InitConfig(params, fsys)

assert.NoError(t, err)
exists, err := afero.Exists(fsys, ConfigPath)
assert.NoError(t, err)
assert.True(t, exists)
})

t.Run("creates config with orioledb", func(t *testing.T) {
fsys := afero.NewMemMapFs()
params := InitParams{
ProjectId: "test-project",
UseOrioleDB: true,
}

err := InitConfig(params, fsys)

assert.NoError(t, err)
content, err := afero.ReadFile(fsys, ConfigPath)
assert.NoError(t, err)
assert.Contains(t, string(content), "15.1.0.150")
})

t.Run("fails if config exists and no overwrite", func(t *testing.T) {
fsys := afero.NewMemMapFs()
err := afero.WriteFile(fsys, ConfigPath, []byte("existing"), 0644)
require.NoError(t, err)
params := InitParams{
ProjectId: "test-project",
}

err = InitConfig(params, fsys)

assert.ErrorIs(t, err, os.ErrExist)
})

t.Run("overwrites existing config when specified", func(t *testing.T) {
fsys := afero.NewMemMapFs()
err := afero.WriteFile(fsys, ConfigPath, []byte("existing"), 0644)
require.NoError(t, err)
params := InitParams{
ProjectId: "test-project",
Overwrite: true,
}

err = InitConfig(params, fsys)

assert.NoError(t, err)
content, err := afero.ReadFile(fsys, ConfigPath)
assert.NoError(t, err)
assert.NotEqual(t, "existing", string(content))
})
}

func TestGetApiUrl(t *testing.T) {
t.Run("returns external url when configured", func(t *testing.T) {
Config.Api.ExternalUrl = "https://api.example.com"

url := GetApiUrl("/test")

assert.Equal(t, "https://api.example.com/test", url)
})

t.Run("builds url from hostname and port", func(t *testing.T) {
Config.Hostname = "localhost"
Config.Api.Port = 8000
Config.Api.ExternalUrl = ""

url := GetApiUrl("/test")

assert.Equal(t, "http://localhost:8000/test", url)
})
}

func TestRootFS(t *testing.T) {
t.Run("opens file from root fs", func(t *testing.T) {
fsys := afero.NewMemMapFs()
content := []byte("test content")
err := afero.WriteFile(fsys, "/test.txt", content, 0644)
require.NoError(t, err)

rootfs := NewRootFS(fsys)
f, err := rootfs.Open("/test.txt")
assert.NoError(t, err)
defer f.Close()

buf := make([]byte, len(content))
n, err := f.Read(buf)
assert.NoError(t, err)
assert.Equal(t, len(content), n)
assert.Equal(t, content, buf)
})

t.Run("returns error for non-existent file", func(t *testing.T) {
fsys := afero.NewMemMapFs()
rootfs := NewRootFS(fsys)

_, err := rootfs.Open("/non-existent.txt")

assert.Error(t, err)
})
}
Loading