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 }