github.com/supabase/cli@v1.168.1/internal/init/init_test.go (about)

     1  package init
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/spf13/afero"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  	"github.com/supabase/cli/internal/testing/fstest"
    12  	"github.com/supabase/cli/internal/utils"
    13  )
    14  
    15  func TestInitCommand(t *testing.T) {
    16  	t.Run("creates config file", func(t *testing.T) {
    17  		// Setup in-memory fs
    18  		fsys := &afero.MemMapFs{}
    19  		require.NoError(t, fsys.Mkdir(".git", 0755))
    20  		// Run test
    21  		assert.NoError(t, Run(fsys, nil, nil, utils.InitParams{}))
    22  		// Validate generated config.toml
    23  		exists, err := afero.Exists(fsys, utils.ConfigPath)
    24  		assert.NoError(t, err)
    25  		assert.True(t, exists)
    26  		// Validate generated .gitignore
    27  		exists, err = afero.Exists(fsys, utils.GitIgnorePath)
    28  		assert.NoError(t, err)
    29  		assert.True(t, exists)
    30  		// Validate generated seed.sql
    31  		exists, err = afero.Exists(fsys, utils.SeedDataPath)
    32  		assert.NoError(t, err)
    33  		assert.True(t, exists)
    34  		// Validate vscode settings file isn't generated
    35  		exists, err = afero.Exists(fsys, settingsPath)
    36  		assert.NoError(t, err)
    37  		assert.False(t, exists)
    38  		exists, err = afero.Exists(fsys, extensionsPath)
    39  		assert.NoError(t, err)
    40  		assert.False(t, exists)
    41  		// Validate intellij settings file isn't generated
    42  		exists, err = afero.Exists(fsys, denoPath)
    43  		assert.NoError(t, err)
    44  		assert.False(t, exists)
    45  	})
    46  
    47  	t.Run("throws error when config file exists", func(t *testing.T) {
    48  		// Setup in-memory fs
    49  		fsys := &afero.MemMapFs{}
    50  		_, err := fsys.Create(utils.ConfigPath)
    51  		require.NoError(t, err)
    52  		// Run test
    53  		assert.Error(t, Run(fsys, nil, nil, utils.InitParams{}))
    54  	})
    55  
    56  	t.Run("throws error on permission denied", func(t *testing.T) {
    57  		// Setup in-memory fs
    58  		fsys := &fstest.OpenErrorFs{DenyPath: utils.ConfigPath}
    59  		// Run test
    60  		err := Run(fsys, nil, nil, utils.InitParams{})
    61  		// Check error
    62  		assert.ErrorIs(t, err, os.ErrPermission)
    63  	})
    64  
    65  	t.Run("throws error on failure to write config", func(t *testing.T) {
    66  		// Setup read-only fs
    67  		fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
    68  		// Run test
    69  		assert.Error(t, Run(fsys, nil, nil, utils.InitParams{}))
    70  	})
    71  
    72  	t.Run("throws error on seed failure", func(t *testing.T) {
    73  		// Setup in-memory fs
    74  		fsys := &fstest.OpenErrorFs{DenyPath: utils.SeedDataPath}
    75  		// Run test
    76  		err := Run(fsys, nil, nil, utils.InitParams{})
    77  		// Check error
    78  		assert.ErrorIs(t, err, os.ErrPermission)
    79  	})
    80  
    81  	t.Run("creates vscode settings file", func(t *testing.T) {
    82  		// Setup in-memory fs
    83  		fsys := &afero.MemMapFs{}
    84  		// Run test
    85  		assert.NoError(t, Run(fsys, utils.Ptr(true), nil, utils.InitParams{}))
    86  		// Validate generated vscode settings
    87  		exists, err := afero.Exists(fsys, settingsPath)
    88  		assert.NoError(t, err)
    89  		assert.True(t, exists)
    90  		exists, err = afero.Exists(fsys, extensionsPath)
    91  		assert.NoError(t, err)
    92  		assert.True(t, exists)
    93  	})
    94  
    95  	t.Run("does not create vscode settings file", func(t *testing.T) {
    96  		// Setup in-memory fs
    97  		fsys := &afero.MemMapFs{}
    98  		// Run test
    99  		assert.NoError(t, Run(fsys, utils.Ptr(false), nil, utils.InitParams{}))
   100  		// Validate vscode settings file isn't generated
   101  		exists, err := afero.Exists(fsys, settingsPath)
   102  		assert.NoError(t, err)
   103  		assert.False(t, exists)
   104  		exists, err = afero.Exists(fsys, extensionsPath)
   105  		assert.NoError(t, err)
   106  		assert.False(t, exists)
   107  	})
   108  
   109  	t.Run("creates intellij deno file", func(t *testing.T) {
   110  		// Setup in-memory fs
   111  		fsys := &afero.MemMapFs{}
   112  		// Run test
   113  		assert.NoError(t, Run(fsys, nil, utils.Ptr(true), utils.InitParams{}))
   114  		// Validate generated intellij deno config
   115  		exists, err := afero.Exists(fsys, denoPath)
   116  		assert.NoError(t, err)
   117  		assert.True(t, exists)
   118  	})
   119  
   120  	t.Run("does not create intellij deno file", func(t *testing.T) {
   121  		// Setup in-memory fs
   122  		fsys := &afero.MemMapFs{}
   123  		// Run test
   124  		assert.NoError(t, Run(fsys, nil, utils.Ptr(false), utils.InitParams{}))
   125  		// Validate intellij deno config file isn't generated
   126  		exists, err := afero.Exists(fsys, denoPath)
   127  		assert.NoError(t, err)
   128  		assert.False(t, exists)
   129  	})
   130  }
   131  
   132  func TestUpdateGitIgnore(t *testing.T) {
   133  	const ignorePath = "/home/supabase/.gitignore"
   134  
   135  	t.Run("appends to git ignore", func(t *testing.T) {
   136  		// Setup in-memory fs
   137  		fsys := &afero.MemMapFs{}
   138  		_, err := fsys.Create(ignorePath)
   139  		require.NoError(t, err)
   140  		// Run test
   141  		assert.NoError(t, updateGitIgnore(ignorePath, fsys))
   142  		// Validate file contents
   143  		content, err := afero.ReadFile(fsys, ignorePath)
   144  		assert.NoError(t, err)
   145  		assert.Equal(t, append([]byte("\n"), initGitignore...), content)
   146  	})
   147  
   148  	t.Run("noop if already ignored", func(t *testing.T) {
   149  		// Setup read-only fs
   150  		fsys := &afero.MemMapFs{}
   151  		require.NoError(t, afero.WriteFile(fsys, ignorePath, initGitignore, 0644))
   152  		// Run test
   153  		assert.NoError(t, updateGitIgnore(ignorePath, fsys))
   154  		// Validate file contents
   155  		content, err := afero.ReadFile(fsys, ignorePath)
   156  		assert.NoError(t, err)
   157  		assert.Equal(t, initGitignore, content)
   158  	})
   159  
   160  	t.Run("throws error on failure to open", func(t *testing.T) {
   161  		// Setup read-only fs
   162  		fsys := &fstest.OpenErrorFs{DenyPath: ignorePath}
   163  		// Run test
   164  		err := updateGitIgnore(ignorePath, fsys)
   165  		// Check error
   166  		assert.Error(t, err, os.ErrPermission)
   167  	})
   168  
   169  	t.Run("throws error on failure to create", func(t *testing.T) {
   170  		// Setup read-only fs
   171  		fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
   172  		// Run test
   173  		err := updateGitIgnore(ignorePath, fsys)
   174  		// Check error
   175  		assert.ErrorContains(t, err, "operation not permitted")
   176  	})
   177  }
   178  
   179  func TestWriteVSCodeConfig(t *testing.T) {
   180  	t.Run("throws error on permission denied", func(t *testing.T) {
   181  		// Setup in-memory fs
   182  		fsys := afero.NewMemMapFs()
   183  		// Run test
   184  		err := writeVscodeConfig(afero.NewReadOnlyFs(fsys))
   185  		// Check error
   186  		assert.ErrorIs(t, err, os.ErrPermission)
   187  	})
   188  
   189  	t.Run("throws error on extensions failure", func(t *testing.T) {
   190  		// Setup in-memory fs
   191  		fsys := &fstest.OpenErrorFs{DenyPath: extensionsPath}
   192  		// Run test
   193  		err := writeVscodeConfig(fsys)
   194  		// Check error
   195  		assert.ErrorIs(t, err, os.ErrPermission)
   196  	})
   197  
   198  	t.Run("throws error on settings failure", func(t *testing.T) {
   199  		// Setup in-memory fs
   200  		fsys := &fstest.OpenErrorFs{DenyPath: settingsPath}
   201  		// Run test
   202  		err := writeVscodeConfig(fsys)
   203  		// Check error
   204  		assert.ErrorIs(t, err, os.ErrPermission)
   205  	})
   206  }
   207  
   208  func TestUpdateJsonFile(t *testing.T) {
   209  	t.Run("overwrites empty settings with template", func(t *testing.T) {
   210  		// Setup in-memory fs
   211  		fsys := afero.NewMemMapFs()
   212  		require.NoError(t, afero.WriteFile(fsys, settingsPath, []byte{}, 0644))
   213  		// Run test
   214  		err := updateJsonFile(settingsPath, "{}", fsys)
   215  		// Check error
   216  		assert.NoError(t, err)
   217  		contents, err := afero.ReadFile(fsys, settingsPath)
   218  		assert.NoError(t, err)
   219  		assert.Equal(t, []byte("{}"), contents)
   220  	})
   221  
   222  	t.Run("merges template into user settings", func(t *testing.T) {
   223  		// Setup in-memory fs
   224  		fsys := afero.NewMemMapFs()
   225  		require.NoError(t, afero.WriteFile(fsys, settingsPath, []byte(`{"a": true, "b": 123}`), 0644))
   226  		// Run test
   227  		err := updateJsonFile(settingsPath, `{"b": 456, "c": false}`, fsys)
   228  		// Check error
   229  		assert.NoError(t, err)
   230  		f, err := fsys.Open(settingsPath)
   231  		assert.NoError(t, err)
   232  		var settings VSCodeSettings
   233  		dec := json.NewDecoder(f)
   234  		assert.NoError(t, dec.Decode(&settings))
   235  		assert.Equal(t, VSCodeSettings{
   236  			"a": true,
   237  			"b": float64(456),
   238  			"c": false,
   239  		}, settings)
   240  	})
   241  
   242  	t.Run("throws error on merge failure", func(t *testing.T) {
   243  		// Setup in-memory fs
   244  		fsys := afero.NewMemMapFs()
   245  		require.NoError(t, afero.WriteFile(fsys, settingsPath, []byte("{}"), 0644))
   246  		// Run test
   247  		err := updateJsonFile(settingsPath, "", fsys)
   248  		// Check error
   249  		assert.ErrorContains(t, err, "failed to copy template:")
   250  	})
   251  
   252  	t.Run("throws error on save failure", func(t *testing.T) {
   253  		// Setup in-memory fs
   254  		fsys := afero.NewMemMapFs()
   255  		require.NoError(t, afero.WriteFile(fsys, settingsPath, []byte("{}"), 0644))
   256  		// Run test
   257  		err := updateJsonFile(settingsPath, "{}", afero.NewReadOnlyFs(fsys))
   258  		// Check error
   259  		assert.ErrorContains(t, err, "operation not permitted")
   260  	})
   261  }