github.com/supabase/cli@v1.168.1/internal/migration/apply/apply_test.go (about) 1 package apply 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/testing/fstest" 16 "github.com/supabase/cli/internal/testing/pgtest" 17 "github.com/supabase/cli/internal/utils" 18 ) 19 20 func TestMigrateDatabase(t *testing.T) { 21 t.Run("applies local migration", func(t *testing.T) { 22 // Setup in-memory fs 23 fsys := afero.NewMemMapFs() 24 path := filepath.Join(utils.MigrationsDir, "0_test.sql") 25 sql := "create schema public" 26 require.NoError(t, afero.WriteFile(fsys, path, []byte(sql), 0644)) 27 // Setup mock postgres 28 conn := pgtest.NewConn() 29 defer conn.Close(t) 30 pgtest.MockMigrationHistory(conn) 31 conn.Query(sql). 32 Reply("CREATE SCHEMA"). 33 Query(history.INSERT_MIGRATION_VERSION, "0", "test", []string{sql}). 34 Reply("INSERT 0 1") 35 // Connect to mock 36 ctx := context.Background() 37 mock, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{Port: 5432}, conn.Intercept) 38 require.NoError(t, err) 39 defer mock.Close(ctx) 40 // Run test 41 err = MigrateAndSeed(ctx, "", mock, fsys) 42 // Check error 43 assert.NoError(t, err) 44 }) 45 46 t.Run("ignores empty local directory", func(t *testing.T) { 47 assert.NoError(t, MigrateAndSeed(context.Background(), "", nil, afero.NewMemMapFs())) 48 }) 49 50 t.Run("throws error on open failure", func(t *testing.T) { 51 // Setup in-memory fs 52 fsys := &fstest.OpenErrorFs{DenyPath: utils.MigrationsDir} 53 // Run test 54 err := MigrateAndSeed(context.Background(), "", nil, fsys) 55 // Check error 56 assert.ErrorIs(t, err, os.ErrPermission) 57 }) 58 } 59 60 func TestSeedDatabase(t *testing.T) { 61 t.Run("seeds from file", func(t *testing.T) { 62 // Setup in-memory fs 63 fsys := afero.NewMemMapFs() 64 // Setup seed file 65 sql := "INSERT INTO employees(name) VALUES ('Alice')" 66 require.NoError(t, afero.WriteFile(fsys, utils.SeedDataPath, []byte(sql), 0644)) 67 // Setup mock postgres 68 conn := pgtest.NewConn() 69 defer conn.Close(t) 70 conn.Query(sql). 71 Reply("INSERT 0 1") 72 // Connect to mock 73 ctx := context.Background() 74 mock, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{Port: 5432}, conn.Intercept) 75 require.NoError(t, err) 76 defer mock.Close(ctx) 77 // Run test 78 assert.NoError(t, SeedDatabase(ctx, mock, fsys)) 79 }) 80 81 t.Run("ignores missing seed", func(t *testing.T) { 82 assert.NoError(t, SeedDatabase(context.Background(), nil, afero.NewMemMapFs())) 83 }) 84 85 t.Run("throws error on read failure", func(t *testing.T) { 86 // Setup in-memory fs 87 fsys := &fstest.OpenErrorFs{DenyPath: utils.SeedDataPath} 88 // Run test 89 err := SeedDatabase(context.Background(), nil, fsys) 90 // Check error 91 assert.ErrorIs(t, err, os.ErrPermission) 92 }) 93 94 t.Run("throws error on insert failure", func(t *testing.T) { 95 // Setup in-memory fs 96 fsys := afero.NewMemMapFs() 97 // Setup seed file 98 sql := "INSERT INTO employees(name) VALUES ('Alice')" 99 require.NoError(t, afero.WriteFile(fsys, utils.SeedDataPath, []byte(sql), 0644)) 100 // Setup mock postgres 101 conn := pgtest.NewConn() 102 defer conn.Close(t) 103 conn.Query(sql). 104 ReplyError(pgerrcode.NotNullViolation, `null value in column "age" of relation "employees"`) 105 // Connect to mock 106 ctx := context.Background() 107 mock, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{Port: 5432}, conn.Intercept) 108 require.NoError(t, err) 109 defer mock.Close(ctx) 110 // Run test 111 err = SeedDatabase(ctx, mock, fsys) 112 // Check error 113 assert.ErrorContains(t, err, `ERROR: null value in column "age" of relation "employees" (SQLSTATE 23502)`) 114 }) 115 } 116 117 func TestMigrateUp(t *testing.T) { 118 t.Run("throws error on missing file", func(t *testing.T) { 119 // Setup in-memory fs 120 fsys := afero.NewMemMapFs() 121 // Setup mock postgres 122 conn := pgtest.NewConn() 123 defer conn.Close(t) 124 pgtest.MockMigrationHistory(conn) 125 // Connect to mock 126 ctx := context.Background() 127 mock, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{Port: 5432}, conn.Intercept) 128 require.NoError(t, err) 129 defer mock.Close(ctx) 130 // Run test 131 err = MigrateUp(context.Background(), mock, []string{"20220727064247_missing.sql"}, fsys) 132 // Check error 133 assert.ErrorIs(t, err, os.ErrNotExist) 134 }) 135 }