github.com/supabase/cli@v1.168.1/internal/db/push/push_test.go (about) 1 package push 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 "testing" 8 9 "github.com/jackc/pgconn" 10 "github.com/jackc/pgerrcode" 11 "github.com/spf13/afero" 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 "github.com/supabase/cli/internal/migration/history" 15 "github.com/supabase/cli/internal/migration/list" 16 "github.com/supabase/cli/internal/testing/fstest" 17 "github.com/supabase/cli/internal/testing/pgtest" 18 "github.com/supabase/cli/internal/utils" 19 ) 20 21 var dbConfig = pgconn.Config{ 22 Host: "127.0.0.1", 23 Port: 5432, 24 User: "admin", 25 Password: "password", 26 Database: "postgres", 27 } 28 29 func TestMigrationPush(t *testing.T) { 30 t.Run("dry run", func(t *testing.T) { 31 // Setup in-memory fs 32 fsys := afero.NewMemMapFs() 33 path := filepath.Join(utils.MigrationsDir, "0_test.sql") 34 require.NoError(t, afero.WriteFile(fsys, path, []byte(""), 0644)) 35 // Setup mock postgres 36 conn := pgtest.NewConn() 37 defer conn.Close(t) 38 conn.Query(list.LIST_MIGRATION_VERSION). 39 Reply("SELECT 0") 40 // Run test 41 err := Run(context.Background(), true, false, true, true, dbConfig, fsys, conn.Intercept) 42 // Check error 43 assert.NoError(t, err) 44 }) 45 46 t.Run("ignores up to date", func(t *testing.T) { 47 // Setup in-memory fs 48 fsys := afero.NewMemMapFs() 49 // Setup mock postgres 50 conn := pgtest.NewConn() 51 defer conn.Close(t) 52 conn.Query(list.LIST_MIGRATION_VERSION). 53 Reply("SELECT 0") 54 // Run test 55 err := Run(context.Background(), false, false, false, false, dbConfig, fsys, conn.Intercept) 56 // Check error 57 assert.NoError(t, err) 58 }) 59 60 t.Run("throws error on connect failure", func(t *testing.T) { 61 // Setup in-memory fs 62 fsys := afero.NewMemMapFs() 63 // Run test 64 err := Run(context.Background(), false, false, false, false, pgconn.Config{}, fsys) 65 // Check error 66 assert.ErrorContains(t, err, "invalid port (outside range)") 67 }) 68 69 t.Run("throws error on remote load failure", func(t *testing.T) { 70 // Setup in-memory fs 71 fsys := afero.NewMemMapFs() 72 // Setup mock postgres 73 conn := pgtest.NewConn() 74 defer conn.Close(t) 75 conn.Query(list.LIST_MIGRATION_VERSION). 76 ReplyError(pgerrcode.InvalidCatalogName, `database "target" does not exist`) 77 // Run test 78 err := Run(context.Background(), false, false, false, false, pgconn.Config{ 79 Host: "db.supabase.co", 80 Port: 5432, 81 User: "admin", 82 Password: "password", 83 Database: "postgres", 84 }, fsys, conn.Intercept) 85 // Check error 86 assert.ErrorContains(t, err, `ERROR: database "target" does not exist (SQLSTATE 3D000)`) 87 }) 88 89 t.Run("throws error on push failure", func(t *testing.T) { 90 // Setup in-memory fs 91 fsys := afero.NewMemMapFs() 92 path := filepath.Join(utils.MigrationsDir, "0_test.sql") 93 require.NoError(t, afero.WriteFile(fsys, path, []byte(""), 0644)) 94 // Setup mock postgres 95 conn := pgtest.NewConn() 96 defer conn.Close(t) 97 conn.Query(list.LIST_MIGRATION_VERSION). 98 Reply("SELECT 0") 99 pgtest.MockMigrationHistory(conn) 100 conn.Query(history.INSERT_MIGRATION_VERSION, "0", "test", nil). 101 ReplyError(pgerrcode.NotNullViolation, `null value in column "version" of relation "schema_migrations"`) 102 // Run test 103 err := Run(context.Background(), false, false, false, false, dbConfig, fsys, conn.Intercept) 104 // Check error 105 assert.ErrorContains(t, err, `ERROR: null value in column "version" of relation "schema_migrations" (SQLSTATE 23502)`) 106 assert.ErrorContains(t, err, "At statement 0: "+history.INSERT_MIGRATION_VERSION) 107 }) 108 } 109 110 func TestPushAll(t *testing.T) { 111 t.Run("ignores missing roles and seed", func(t *testing.T) { 112 // Setup in-memory fs 113 fsys := afero.NewMemMapFs() 114 path := filepath.Join(utils.MigrationsDir, "0_test.sql") 115 require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644)) 116 // Setup mock postgres 117 conn := pgtest.NewConn() 118 defer conn.Close(t) 119 conn.Query(list.LIST_MIGRATION_VERSION). 120 Reply("SELECT 0") 121 pgtest.MockMigrationHistory(conn) 122 conn.Query(history.INSERT_MIGRATION_VERSION, "0", "test", nil). 123 Reply("INSERT 0 1") 124 // Run test 125 err := Run(context.Background(), false, false, true, true, dbConfig, fsys, conn.Intercept) 126 // Check error 127 assert.NoError(t, err) 128 }) 129 130 t.Run("throws error on cancel", func(t *testing.T) { 131 defer fstest.MockStdin(t, "n")() 132 // Setup in-memory fs 133 fsys := afero.NewMemMapFs() 134 path := filepath.Join(utils.MigrationsDir, "0_test.sql") 135 require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644)) 136 // Setup mock postgres 137 conn := pgtest.NewConn() 138 defer conn.Close(t) 139 conn.Query(list.LIST_MIGRATION_VERSION). 140 Reply("SELECT 0") 141 // Run test 142 err := Run(context.Background(), false, false, true, true, dbConfig, fsys, conn.Intercept) 143 // Check error 144 assert.ErrorIs(t, err, context.Canceled) 145 }) 146 147 t.Run("throws error on roles failure", func(t *testing.T) { 148 // Setup in-memory fs 149 fsys := &fstest.OpenErrorFs{DenyPath: utils.CustomRolesPath} 150 path := filepath.Join(utils.MigrationsDir, "0_test.sql") 151 require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644)) 152 // Setup mock postgres 153 conn := pgtest.NewConn() 154 defer conn.Close(t) 155 conn.Query(list.LIST_MIGRATION_VERSION). 156 Reply("SELECT 0") 157 // Run test 158 err := Run(context.Background(), false, false, true, false, dbConfig, fsys, conn.Intercept) 159 // Check error 160 assert.ErrorIs(t, err, os.ErrPermission) 161 }) 162 163 t.Run("throws error on seed failure", func(t *testing.T) { 164 // Setup in-memory fs 165 fsys := &fstest.OpenErrorFs{DenyPath: utils.SeedDataPath} 166 path := filepath.Join(utils.MigrationsDir, "0_test.sql") 167 require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644)) 168 // Setup mock postgres 169 conn := pgtest.NewConn() 170 defer conn.Close(t) 171 conn.Query(list.LIST_MIGRATION_VERSION). 172 Reply("SELECT 0") 173 pgtest.MockMigrationHistory(conn) 174 conn.Query(history.INSERT_MIGRATION_VERSION, "0", "test", nil). 175 Reply("INSERT 0 1") 176 // Run test 177 err := Run(context.Background(), false, false, false, true, dbConfig, fsys, conn.Intercept) 178 // Check error 179 assert.ErrorIs(t, err, os.ErrPermission) 180 }) 181 }