github.com/supabase/cli@v1.168.1/internal/status/status_test.go (about) 1 package status 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "io" 8 "net/http" 9 "os" 10 "strings" 11 "testing" 12 13 "github.com/docker/docker/api/types" 14 "github.com/spf13/afero" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 "github.com/supabase/cli/internal/testing/apitest" 18 "github.com/supabase/cli/internal/utils" 19 "gopkg.in/h2non/gock.v1" 20 ) 21 22 func TestStatusCommand(t *testing.T) { 23 t.Run("shows service status", func(t *testing.T) { 24 services := []string{ 25 "supabase_db_", 26 "supabase_kong_", 27 "supabase_auth_", 28 "supabase_inbucket_", 29 "supabase_realtime_", 30 "supabase_rest_", 31 "supabase_storage_", 32 "supabase_imgproxy_", 33 "supabase_pg_meta_", 34 "supabase_studio_", 35 "supabase_analytics_", 36 } 37 // Setup in-memory fs 38 fsys := afero.NewMemMapFs() 39 require.NoError(t, utils.WriteConfig(fsys, false)) 40 // Setup mock docker 41 require.NoError(t, apitest.MockDocker(utils.Docker)) 42 defer gock.OffAll() 43 for _, container := range services { 44 gock.New(utils.Docker.DaemonHost()). 45 Get("/v" + utils.Docker.ClientVersion() + "/containers/" + container). 46 Reply(http.StatusOK). 47 JSON(types.ContainerJSON{ContainerJSONBase: &types.ContainerJSONBase{ 48 State: &types.ContainerState{Running: true}, 49 }}) 50 } 51 // Run test 52 assert.NoError(t, Run(context.Background(), CustomName{}, utils.OutputPretty, fsys)) 53 // Check error 54 assert.Empty(t, apitest.ListUnmatchedRequests()) 55 }) 56 57 t.Run("throws error on missing config", func(t *testing.T) { 58 err := Run(context.Background(), CustomName{}, utils.OutputPretty, afero.NewMemMapFs()) 59 assert.ErrorIs(t, err, os.ErrNotExist) 60 }) 61 62 t.Run("throws error on invalid config", func(t *testing.T) { 63 // Setup in-memory fs 64 fsys := afero.NewMemMapFs() 65 require.NoError(t, afero.WriteFile(fsys, utils.ConfigPath, []byte("malformed"), 0644)) 66 // Run test 67 err := Run(context.Background(), CustomName{}, utils.OutputPretty, fsys) 68 // Check error 69 assert.ErrorContains(t, err, "toml: line 0: unexpected EOF; expected key separator '='") 70 }) 71 72 t.Run("throws error on missing docker", func(t *testing.T) { 73 // Setup in-memory fs 74 fsys := afero.NewMemMapFs() 75 require.NoError(t, utils.WriteConfig(fsys, false)) 76 // Setup mock docker 77 require.NoError(t, apitest.MockDocker(utils.Docker)) 78 defer gock.OffAll() 79 gock.New(utils.Docker.DaemonHost()). 80 Get("/v" + utils.Docker.ClientVersion() + "/containers/supabase_db_"). 81 ReplyError(errors.New("network error")) 82 // Run test 83 err := Run(context.Background(), CustomName{}, utils.OutputPretty, fsys) 84 // Check error 85 assert.ErrorContains(t, err, "network error") 86 assert.Empty(t, apitest.ListUnmatchedRequests()) 87 }) 88 } 89 90 func TestServiceHealth(t *testing.T) { 91 services := []string{"supabase_db", "supabase_auth"} 92 93 t.Run("checks all services", func(t *testing.T) { 94 // Setup mock docker 95 require.NoError(t, apitest.MockDocker(utils.Docker)) 96 defer gock.OffAll() 97 gock.New(utils.Docker.DaemonHost()). 98 Get("/v" + utils.Docker.ClientVersion() + "/containers/" + services[0] + "/json"). 99 Reply(http.StatusOK). 100 JSON(types.ContainerJSON{ContainerJSONBase: &types.ContainerJSONBase{ 101 State: &types.ContainerState{ 102 Running: true, 103 Health: &types.Health{Status: "Unhealthy"}, 104 }, 105 }}) 106 gock.New(utils.Docker.DaemonHost()). 107 Get("/v" + utils.Docker.ClientVersion() + "/containers/" + services[1] + "/json"). 108 Reply(http.StatusOK). 109 JSON(types.ContainerJSON{ContainerJSONBase: &types.ContainerJSONBase{ 110 State: &types.ContainerState{Status: "exited"}, 111 }}) 112 // Run test 113 var stderr bytes.Buffer 114 stopped := checkServiceHealth(context.Background(), services, &stderr) 115 // Check error 116 assert.Empty(t, stopped) 117 lines := strings.Split(strings.TrimSpace(stderr.String()), "\n") 118 assert.ElementsMatch(t, []string{ 119 "supabase_db container is not ready: Unhealthy", 120 "supabase_auth container is not running: exited", 121 }, lines) 122 assert.Empty(t, apitest.ListUnmatchedRequests()) 123 }) 124 125 t.Run("throws error on missing container", func(t *testing.T) { 126 // Setup in-memory fs 127 fsys := afero.NewMemMapFs() 128 require.NoError(t, utils.WriteConfig(fsys, false)) 129 // Setup mock docker 130 require.NoError(t, apitest.MockDocker(utils.Docker)) 131 defer gock.OffAll() 132 for _, name := range services { 133 gock.New(utils.Docker.DaemonHost()). 134 Get("/v" + utils.Docker.ClientVersion() + "/containers/" + name + "/json"). 135 Reply(http.StatusNotFound) 136 } 137 // Run test 138 stopped := checkServiceHealth(context.Background(), services, io.Discard) 139 // Check error 140 assert.ElementsMatch(t, services, stopped) 141 assert.Empty(t, apitest.ListUnmatchedRequests()) 142 }) 143 } 144 145 func TestPrintStatus(t *testing.T) { 146 utils.Config.Db.Port = 0 147 utils.Config.Hostname = "127.0.0.1" 148 utils.Config.Api.Enabled = false 149 utils.Config.Auth.Enabled = false 150 utils.Config.Storage.Enabled = false 151 utils.Config.Realtime.Enabled = false 152 utils.Config.Studio.Enabled = false 153 utils.Config.Analytics.Enabled = false 154 utils.Config.Inbucket.Enabled = false 155 156 t.Run("outputs env var", func(t *testing.T) { 157 utils.Config.Hostname = "127.0.0.1" 158 // Run test 159 var stdout bytes.Buffer 160 assert.NoError(t, printStatus(CustomName{DbURL: "DB_URL"}, utils.OutputEnv, &stdout)) 161 // Check error 162 assert.Equal(t, "DB_URL=\"postgresql://postgres:postgres@127.0.0.1:0/postgres\"\n", stdout.String()) 163 }) 164 165 t.Run("outputs json object", func(t *testing.T) { 166 // Run test 167 var stdout bytes.Buffer 168 assert.NoError(t, printStatus(CustomName{DbURL: "DB_URL"}, utils.OutputJson, &stdout)) 169 // Check error 170 assert.Equal(t, "{\n \"DB_URL\": \"postgresql://postgres:postgres@127.0.0.1:0/postgres\"\n}\n", stdout.String()) 171 }) 172 173 t.Run("outputs yaml properties", func(t *testing.T) { 174 // Run test 175 var stdout bytes.Buffer 176 assert.NoError(t, printStatus(CustomName{DbURL: "DB_URL"}, utils.OutputYaml, &stdout)) 177 // Check error 178 assert.Equal(t, "DB_URL: postgresql://postgres:postgres@127.0.0.1:0/postgres\n", stdout.String()) 179 }) 180 181 t.Run("outputs toml fields", func(t *testing.T) { 182 // Run test 183 var stdout bytes.Buffer 184 assert.NoError(t, printStatus(CustomName{DbURL: "DB_URL"}, utils.OutputToml, &stdout)) 185 // Check error 186 assert.Equal(t, "DB_URL = \"postgresql://postgres:postgres@127.0.0.1:0/postgres\"\n", stdout.String()) 187 }) 188 }