package bootstrap import ( "os" "path/filepath" "testing" "github.com/jackc/pgconn" "github.com/joho/godotenv" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/supabase/cli/internal/utils/flags" "github.com/supabase/cli/pkg/api" ) func TestSuggestAppStart(t *testing.T) { t.Run("suggest npm", func(t *testing.T) { cwd, err := os.Getwd() require.NoError(t, err) // Run test suggestion := suggestAppStart(cwd, "npm ci && npm run dev") // Check error assert.Equal(t, "To start your app:\n npm ci && npm run dev", suggestion) }) t.Run("suggest cd", func(t *testing.T) { cwd, err := os.Getwd() require.NoError(t, err) // Run test suggestion := suggestAppStart(filepath.Dir(cwd), "npm ci && npm run dev") // Check error expected := "To start your app:" expected += "\n cd " + filepath.Base(cwd) expected += "\n npm ci && npm run dev" assert.Equal(t, expected, suggestion) }) t.Run("ignore relative path", func(t *testing.T) { // Run test suggestion := suggestAppStart(".", "supabase start") // Check error assert.Equal(t, "To start your app:\n supabase start", suggestion) }) } func TestWriteEnv(t *testing.T) { var apiKeys = []api.ApiKeyResponse{{ ApiKey: "anonkey", Name: "anon", }, { ApiKey: "servicekey", Name: "service_role", }} var dbConfig = pgconn.Config{ Host: "db.supabase.co", Port: 5432, User: "admin", Password: "password", Database: "postgres", } t.Run("writes .env", func(t *testing.T) { flags.ProjectRef = "testing" // Setup in-memory fs fsys := afero.NewMemMapFs() // Run test err := writeDotEnv(apiKeys, dbConfig, fsys) // Check error assert.NoError(t, err) env, err := afero.ReadFile(fsys, ".env") assert.NoError(t, err) assert.Equal(t, `POSTGRES_URL="postgresql://admin:password@db.supabase.co:6543/postgres?connect_timeout=10" SUPABASE_ANON_KEY="anonkey" SUPABASE_SERVICE_ROLE_KEY="servicekey" SUPABASE_URL="https://testing.supabase.co"`, string(env)) }) t.Run("merges with .env.example", func(t *testing.T) { flags.ProjectRef = "testing" // Setup in-memory fs fsys := afero.NewMemMapFs() example, err := godotenv.Marshal(map[string]string{ POSTGRES_PRISMA_URL: "example", POSTGRES_URL_NON_POOLING: "example", POSTGRES_USER: "example", POSTGRES_HOST: "example", POSTGRES_PASSWORD: "example", POSTGRES_DATABASE: "example", NEXT_PUBLIC_SUPABASE_ANON_KEY: "example", NEXT_PUBLIC_SUPABASE_URL: "example", "no_match": "example", SUPABASE_SERVICE_ROLE_KEY: "example", SUPABASE_ANON_KEY: "example", SUPABASE_URL: "example", POSTGRES_URL: "example", }) require.NoError(t, err) require.NoError(t, afero.WriteFile(fsys, ".env.example", []byte(example), 0644)) // Run test err = writeDotEnv(apiKeys, dbConfig, fsys) // Check error assert.NoError(t, err) env, err := afero.ReadFile(fsys, ".env") assert.NoError(t, err) assert.Equal(t, `NEXT_PUBLIC_SUPABASE_ANON_KEY="anonkey" NEXT_PUBLIC_SUPABASE_URL="https://testing.supabase.co" POSTGRES_DATABASE="postgres" POSTGRES_HOST="db.supabase.co" POSTGRES_PASSWORD="password" POSTGRES_PRISMA_URL="postgresql://admin:password@db.supabase.co:6543/postgres?connect_timeout=10" POSTGRES_URL="postgresql://admin:password@db.supabase.co:6543/postgres?connect_timeout=10" POSTGRES_URL_NON_POOLING="postgresql://admin:password@db.supabase.co:5432/postgres?connect_timeout=10" POSTGRES_USER="admin" SUPABASE_ANON_KEY="anonkey" SUPABASE_SERVICE_ROLE_KEY="servicekey" SUPABASE_URL="https://testing.supabase.co" no_match="example"`, string(env)) }) t.Run("throws error on malformed example", func(t *testing.T) { // Setup in-memory fs fsys := afero.NewMemMapFs() require.NoError(t, afero.WriteFile(fsys, ".env.example", []byte("!="), 0644)) // Run test err := writeDotEnv(nil, dbConfig, fsys) // Check error assert.ErrorContains(t, err, `unexpected character "!" in variable name near "!="`) }) t.Run("throws error on permission denied", func(t *testing.T) { // Setup in-memory fs fsys := afero.NewMemMapFs() // Run test err := writeDotEnv(nil, dbConfig, afero.NewReadOnlyFs(fsys)) // Check error assert.ErrorIs(t, err, os.ErrPermission) }) }