github.com/knoebber/dotfile@v1.0.6/local/storage_test.go (about)

     1  package local
     2  
     3  import (
     4  	"bytes"
     5  	"net/http"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/knoebber/dotfile/dotfile"
    12  	"github.com/knoebber/dotfile/dotfileclient"
    13  	"github.com/pkg/errors"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestStorage_JSON(t *testing.T) {
    18  	t.Run("not tracked error", func(t *testing.T) {
    19  		s := testStorage()
    20  		s.Dir = "/does/not/exist"
    21  		_, err := s.JSON()
    22  		assert.True(t, errors.Is(err, ErrNotTracked))
    23  	})
    24  }
    25  
    26  func TestStorage_SetTrackingData(t *testing.T) {
    27  	t.Run("error when storage dir is empty", func(t *testing.T) {
    28  		s := testStorage()
    29  		s.Dir = ""
    30  		assert.Error(t, s.SetTrackingData())
    31  	})
    32  
    33  	t.Run("error when storage dir does not exist", func(t *testing.T) {
    34  		s := testStorage()
    35  		s.Dir = "/not/exist"
    36  		assert.Error(t, s.SetTrackingData())
    37  	})
    38  
    39  	t.Run("error when alias is empty", func(t *testing.T) {
    40  		s := testStorage()
    41  		s.Alias = ""
    42  		assert.Error(t, s.SetTrackingData())
    43  	})
    44  
    45  	t.Run("error when file is not tracked", func(t *testing.T) {
    46  		clearTestStorage()
    47  		s := testStorage()
    48  		assert.Error(t, s.SetTrackingData())
    49  	})
    50  
    51  	t.Run("error on invalid json", func(t *testing.T) {
    52  		s := testStorage()
    53  		_ = os.Mkdir(testDir, 0755)
    54  		_ = os.WriteFile(s.jsonPath(), []byte("invalid json"), 0644)
    55  		assert.Error(t, s.SetTrackingData())
    56  	})
    57  }
    58  
    59  func TestStorage_save(t *testing.T) {
    60  	t.Run("error when directory doesn't exist", func(t *testing.T) {
    61  		s := &Storage{Dir: "/not/exist"}
    62  		assert.Error(t, s.save())
    63  	})
    64  	t.Run("error when json path doesn't exist", func(t *testing.T) {
    65  		resetTestStorage(t)
    66  		s := testStorage()
    67  		s.Alias = "not/tracked"
    68  		assert.Error(t, s.save())
    69  	})
    70  }
    71  
    72  func TestStorage_HasCommit(t *testing.T) {
    73  	s := &Storage{
    74  		FileData: &dotfile.TrackingData{
    75  			Commits: []dotfile.Commit{{
    76  				Hash: "a",
    77  			}},
    78  		}}
    79  
    80  	t.Run("returns true", func(t *testing.T) {
    81  		res, _ := s.HasCommit("a")
    82  		assert.True(t, res)
    83  	})
    84  	t.Run("returns false", func(t *testing.T) {
    85  		res, _ := s.HasCommit("b")
    86  		assert.False(t, res)
    87  	})
    88  }
    89  
    90  func TestStorage_Revision(t *testing.T) {
    91  	s := setupTestFile(t)
    92  
    93  	t.Run("error when revision does not exist", func(t *testing.T) {
    94  		_, err := s.Revision("")
    95  		assert.Error(t, err)
    96  	})
    97  
    98  	t.Run("ok", func(t *testing.T) {
    99  		s := setupTestFile(t)
   100  		_ = os.Mkdir(filepath.Join(testDir, testAlias), 0755)
   101  		_ = os.WriteFile(filepath.Join(testDir, testAlias, testHash), []byte(testContent), 0644)
   102  		contents, err := s.Revision(testHash)
   103  		assert.NoError(t, err)
   104  		assert.NotEmpty(t, contents)
   105  	})
   106  }
   107  
   108  func TestStorage_Revert(t *testing.T) {
   109  	t.Run("error when unable to write", func(t *testing.T) {
   110  		s := &Storage{FileData: &dotfile.TrackingData{Path: "/not/exists"}}
   111  		assert.Error(t, s.Revert(new(bytes.Buffer), testHash))
   112  	})
   113  
   114  	t.Run("ok", func(t *testing.T) {
   115  		s := setupTestFile(t)
   116  		err := s.Revert(bytes.NewBuffer([]byte(testUpdatedContent)), testUpdatedHash)
   117  		assert.NoError(t, err)
   118  		assert.Equal(t, testUpdatedHash, s.FileData.Revision)
   119  	})
   120  }
   121  
   122  func TestStorage_SaveCommit(t *testing.T) {
   123  	t.Run("error when tracking data is not set", func(t *testing.T) {
   124  		s := testStorage()
   125  		err := s.SaveCommit(new(bytes.Buffer), new(dotfile.Commit))
   126  		assert.Error(t, err)
   127  	})
   128  	t.Run("error when unable to write commit", func(t *testing.T) {
   129  		s := testStorage()
   130  		s.Dir = "/not/exist"
   131  		s.FileData = new(dotfile.TrackingData)
   132  		err := s.SaveCommit(new(bytes.Buffer), new(dotfile.Commit))
   133  		assert.Error(t, err)
   134  	})
   135  
   136  	t.Run("error when unable to create commit file", func(t *testing.T) {
   137  		s := setupTestFile(t)
   138  		s.Alias = "/not/exists"
   139  		err := s.SaveCommit(new(bytes.Buffer), new(dotfile.Commit))
   140  		assert.Error(t, err)
   141  	})
   142  
   143  	t.Run("ok", func(t *testing.T) {
   144  		s := setupTestFile(t)
   145  		timestamp := time.Now()
   146  		c := &dotfile.Commit{
   147  			Hash:      testUpdatedHash,
   148  			Timestamp: time.Now().Unix(),
   149  			Message:   testMessage,
   150  		}
   151  
   152  		err := s.SaveCommit(bytes.NewBuffer([]byte(testUpdatedContent)), c)
   153  
   154  		assert.NoError(t, err)
   155  		assert.Equal(t, testUpdatedHash, s.FileData.Revision)
   156  		assert.Equal(t, testMessage, s.FileData.Commits[1].Message)
   157  		assert.Equal(t, timestamp.Unix(), s.FileData.Commits[1].Timestamp)
   158  	})
   159  }
   160  
   161  func TestStorage_Path(t *testing.T) {
   162  	t.Run("error when filedata is nil", func(t *testing.T) {
   163  		s := testStorage()
   164  		_, err := s.Path()
   165  		assert.Error(t, err)
   166  	})
   167  	t.Run("error when path is empty", func(t *testing.T) {
   168  		s := testStorage()
   169  		s.FileData = new(dotfile.TrackingData)
   170  		_, err := s.Path()
   171  		assert.Error(t, err)
   172  	})
   173  
   174  	t.Run("error when $HOME not set", func(t *testing.T) {
   175  		defer os.Setenv("HOME", os.Getenv("HOME"))
   176  		_ = os.Unsetenv("HOME")
   177  
   178  		s := testStorage()
   179  		s.FileData = &dotfile.TrackingData{Path: "~/relative-path"}
   180  
   181  		_, err := s.Path()
   182  		assert.Error(t, err)
   183  	})
   184  
   185  	t.Run("ok", func(t *testing.T) {
   186  		s := testStorage()
   187  		s.FileData = &dotfile.TrackingData{Path: "~/relative-path"}
   188  
   189  		path, err := s.Path()
   190  		assert.NoError(t, err)
   191  		assert.NotEmpty(t, path)
   192  	})
   193  }
   194  
   195  func TestStorage_Push(t *testing.T) {
   196  	t.Run("error when data not loaded", func(t *testing.T) {
   197  		s := testStorage()
   198  		assert.Error(t, s.Push(nil))
   199  	})
   200  	t.Run("error when client fails to connect", func(t *testing.T) {
   201  		client := new(dotfileclient.Client)
   202  		s := testStorage()
   203  		assert.Error(t, s.Push(client))
   204  	})
   205  }
   206  
   207  func TestStorage_Pull(t *testing.T) {
   208  	s := testStorage()
   209  	client := new(dotfileclient.Client)
   210  	client.Client = http.DefaultClient
   211  	t.Run("error on attempt to load invalid json", func(t *testing.T) {
   212  		setupTestFile(t)
   213  
   214  		if err := os.WriteFile(testDir+testAlias+".json", []byte("invalid json"), 0644); err != nil {
   215  			t.Fatalf("writing test json")
   216  		}
   217  		assert.Error(t, s.Pull(client))
   218  	})
   219  
   220  	t.Run("uncommitted changes", func(t *testing.T) {
   221  		setupTestFile(t)
   222  		updateTestFile(t)
   223  		err := s.Pull(client)
   224  		assert.Error(t, err)
   225  		assert.Contains(t, err.Error(), "uncommitted")
   226  	})
   227  
   228  	t.Run("client error", func(t *testing.T) {
   229  		setupTestFile(t)
   230  		err := s.Pull(client)
   231  		assert.Error(t, err)
   232  	})
   233  }
   234  
   235  func TestStorage_Move(t *testing.T) {
   236  	s := testStorage()
   237  	setupTestFile(t)
   238  
   239  	t.Run("error when no data", func(t *testing.T) {
   240  		assert.Error(t, s.Move(testTrackedFile, false))
   241  	})
   242  
   243  	assert.NoError(t, s.SetTrackingData())
   244  
   245  	t.Run("parent dirs works", func(t *testing.T) {
   246  		nested := testDir + "new/file.txt"
   247  		assert.Error(t, s.Move(nested, false))
   248  		assert.NoError(t, s.Move(nested, true))
   249  	})
   250  
   251  	t.Run("error when path can't be made", func(t *testing.T) {
   252  		assert.Error(t, s.Move("/not/real.txt", true))
   253  	})
   254  }
   255  
   256  func TestStorage_Rename(t *testing.T) {
   257  	s := testStorage()
   258  	setupTestFile(t)
   259  
   260  	t.Run("error when alias exists", func(t *testing.T) {
   261  		assert.Error(t, s.Rename(testAlias))
   262  	})
   263  
   264  	t.Run("error when alias has invalid format", func(t *testing.T) {
   265  		assert.Error(t, s.Rename("invalid/alias"))
   266  	})
   267  
   268  	t.Run("error when dir doesn't exist", func(t *testing.T) {
   269  		invalidStorage := &Storage{
   270  			Alias: testAlias,
   271  			Dir:   "/does/not/exist",
   272  		}
   273  
   274  		assert.Error(t, invalidStorage.Rename("newalias"))
   275  	})
   276  
   277  	t.Run("ok", func(t *testing.T) {
   278  		assert.NoError(t, s.Rename("new"))
   279  	})
   280  }
   281  
   282  func TestStorage_Forget(t *testing.T) {
   283  	t.Run("error when dir doesn't exist", func(t *testing.T) {
   284  		invalidStorage := &Storage{Dir: "/does/not/exist"}
   285  		assert.Error(t, invalidStorage.Forget())
   286  	})
   287  
   288  	t.Run("ok", func(t *testing.T) {
   289  		setupTestFile(t)
   290  		s := testStorage()
   291  		assert.NoError(t, s.Forget())
   292  	})
   293  }
   294  
   295  func TestStorage_RemoveCommits(t *testing.T) {
   296  	setupTestFile(t)
   297  	s := testStorage()
   298  
   299  	t.Run("error when file data not set", func(t *testing.T) {
   300  		assert.Error(t, s.RemoveCommits())
   301  	})
   302  
   303  	t.Run("ok with no commits", func(t *testing.T) {
   304  		s.FileData = new(dotfile.TrackingData)
   305  		assert.NoError(t, s.RemoveCommits())
   306  	})
   307  
   308  	t.Run("removes non current commit", func(t *testing.T) {
   309  		updateTestFile(t)
   310  		assert.NoError(t, s.SetTrackingData())
   311  		assert.NoError(t, dotfile.NewCommit(s, "testing remove commits"))
   312  		assert.NoError(t, s.RemoveCommits())
   313  		assert.Equal(t, 1, len(s.FileData.Commits))
   314  	})
   315  }
   316  
   317  func TestStorage_Remove(t *testing.T) {
   318  	setupTestFile(t)
   319  	s := testStorage()
   320  
   321  	t.Run("error when tracking data not loaded", func(t *testing.T) {
   322  		assert.Error(t, s.Remove())
   323  	})
   324  
   325  	t.Run("ok", func(t *testing.T) {
   326  		assert.NoError(t, s.SetTrackingData())
   327  		assert.NoError(t, s.Remove())
   328  	})
   329  }