github.com/jacekolszak/noteo@v0.5.0/repository/repository_test.go (about) 1 package repository_test 2 3 import ( 4 "context" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "testing" 9 "time" 10 11 "github.com/jacekolszak/noteo/note" 12 "github.com/jacekolszak/noteo/repository" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestRepository_Add(t *testing.T) { 18 t.Run("should generate name", func(t *testing.T) { 19 tests := map[string]struct { 20 content string 21 expectedFilename string 22 }{ 23 "note with YAML front matter black": { 24 content: `--- 25 Tags: "" 26 --- 27 28 yaml`, 29 expectedFilename: "yaml.md", 30 }, 31 "note with YAML without blank line:": { 32 content: `--- 33 Tags: "" 34 --- 35 yaml-without-blank-line`, 36 expectedFilename: "yaml-without-blank-line.md", 37 }, 38 "should remove illegal chars": { 39 content: "chars`~!@#$%^&*()_+[{]}\\|;:'\",<>/?", 40 expectedFilename: "chars.md", 41 }, 42 "should replace diacritics with ascii": { 43 content: "ąćęłńóśżź", 44 expectedFilename: "acelnoszz.md", 45 }, 46 "should replace space with dash": { 47 content: "foo bar", 48 expectedFilename: "foo-bar.md", 49 }, 50 "should trim spaces": { 51 content: " trimspaces ", 52 expectedFilename: "trimspaces.md", 53 }, 54 "should trim spaces after removing illegal chars": { 55 content: "% removedchars @", 56 expectedFilename: "removedchars.md", 57 }, 58 "should trim newlines": { 59 content: "\nnewlines\n", 60 expectedFilename: "newlines.md", 61 }, 62 "should lowercase": { 63 content: "LOWERCASE", 64 expectedFilename: "lowercase.md", 65 }, 66 "unknown": { 67 content: " @#", 68 expectedFilename: "unknown.md", 69 }, 70 "unknown with front matter": { 71 content: `--- 72 Tags: "" 73 --- 74 75 `, 76 expectedFilename: "unknown.md", 77 }, 78 "yaml without break line": { 79 content: `--- 80 Tags: "" 81 ---`, 82 expectedFilename: "unknown.md", 83 }, 84 "should use only first line of body as filename": { 85 content: `--- 86 Tags: "" 87 --- 88 89 first 90 second`, 91 expectedFilename: "first.md", 92 }, 93 "should use capital letter word for very long text": { 94 content: "Very long text and only This word will be used as title", 95 expectedFilename: "this.md", 96 }, 97 "should trim very long text": { 98 content: "this is very long text without any capital letter words", 99 expectedFilename: "this-is-very-long-text-without.md", 100 }, 101 "should remove carriage return": { 102 content: "return\r", 103 expectedFilename: "return.md", 104 }, 105 } 106 for name, test := range tests { 107 t.Run(name, func(t *testing.T) { 108 _, repo := repo(t) 109 // when 110 file, err := repo.Add(test.content) 111 // then 112 require.NoError(t, err) 113 assert.Equal(t, test.expectedFilename, file) 114 }) 115 } 116 }) 117 } 118 119 func TestRepository_Move(t *testing.T) { 120 t.Run("should rename file", func(t *testing.T) { 121 dir, repo := repo(t) 122 require.NoError(t, os.Chdir(dir)) 123 writeFile(t, filepath.Join("source.md"), "source") 124 linkFile := filepath.Join(dir, "link.md") 125 writeFile(t, linkFile, "[link](source.md)") 126 ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second) 127 defer cancelFunc() 128 // when 129 notes, success, errors := repo.Move(ctx, "source.md", "target.md") 130 // then 131 assertSuccess(t, ctx, notes, success, errors) 132 assert.NoFileExists(t, "source.md") 133 assert.FileExists(t, "target.md") 134 assertFileEquals(t, linkFile, "[link](target.md)") 135 }) 136 137 t.Run("should move file to directory", func(t *testing.T) { 138 dir, repo := repo(t) 139 require.NoError(t, os.Chdir(dir)) 140 require.NoError(t, os.MkdirAll("target", os.ModePerm)) 141 writeFile(t, "source.md", "source") 142 linkFile := filepath.Join(dir, "link.md") 143 writeFile(t, linkFile, "[link](source.md)") 144 ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second) 145 defer cancelFunc() 146 // when 147 notes, success, errors := repo.Move(ctx, "source.md", "target") 148 // then 149 assertSuccess(t, ctx, notes, success, errors) 150 assert.NoFileExists(t, "source.md") 151 assert.FileExists(t, filepath.Join("target", "source.md")) 152 assertFileEquals(t, linkFile, "[link](target/source.md)") 153 }) 154 155 t.Run("should move whole dir", func(t *testing.T) { 156 dir, repo := repo(t) 157 require.NoError(t, os.Chdir(dir)) 158 require.NoError(t, os.MkdirAll("source", os.ModePerm)) 159 require.NoError(t, os.MkdirAll("target", os.ModePerm)) 160 sourceDir := filepath.Join(dir, "source") 161 sourceFile := filepath.Join(sourceDir, "foo.md") 162 writeFile(t, sourceFile, "foo") 163 linkFile := filepath.Join(dir, "link.md") 164 writeFile(t, linkFile, "[link](source/foo.md)") 165 ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second) 166 defer cancelFunc() 167 // when 168 notes, success, errors := repo.Move(ctx, "source", "target") 169 // then 170 assertSuccess(t, ctx, notes, success, errors) 171 assert.NoDirExists(t, sourceDir) 172 assert.DirExists(t, filepath.Join(dir, "target", "source")) 173 assert.FileExists(t, filepath.Join(dir, "target", "source", "foo.md")) 174 assertFileEquals(t, linkFile, "[link](target/source/foo.md)") 175 }) 176 } 177 178 func assertSuccess(t *testing.T, ctx context.Context, notes <-chan *note.Note, success <-chan bool, errors <-chan error) { 179 var successClosed, errorClosed, notesClosed bool 180 for !successClosed || !errorClosed || !notesClosed { 181 select { 182 case _, ok := <-notes: 183 if !ok { 184 notesClosed = true 185 continue 186 } 187 case e, ok := <-errors: 188 if !ok { 189 errorClosed = true 190 continue 191 } 192 require.FailNowf(t, "error received", "%v", e) 193 case <-ctx.Done(): 194 require.FailNow(t, "timeout") 195 case s, ok := <-success: 196 if !ok { 197 successClosed = true 198 continue 199 } 200 assert.True(t, s) 201 } 202 } 203 } 204 205 func assertFileEquals(t *testing.T, file, expected string) { 206 content, err := ioutil.ReadFile(file) 207 require.NoError(t, err) 208 assert.Equal(t, expected, string(content)) 209 } 210 211 func repo(t *testing.T) (dir string, repo *repository.Repository) { 212 dir, err := ioutil.TempDir("", "noteo-test") 213 require.NoError(t, err) 214 _, err = repository.Init(dir) 215 require.NoError(t, err) 216 repo, err = repository.ForWorkDir(dir) 217 require.NoError(t, err) 218 return dir, repo 219 } 220 221 func writeFile(t *testing.T, filename, content string) { 222 require.NoError(t, ioutil.WriteFile(filename, []byte(content), os.ModePerm)) 223 }