path_test.go (6910B)
1 // Copyright 2021 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package paths 15 16 import ( 17 "path/filepath" 18 "testing" 19 20 qt "github.com/frankban/quicktest" 21 ) 22 23 func TestGetRelativePath(t *testing.T) { 24 tests := []struct { 25 path string 26 base string 27 expect any 28 }{ 29 {filepath.FromSlash("/a/b"), filepath.FromSlash("/a"), filepath.FromSlash("b")}, 30 {filepath.FromSlash("/a/b/c/"), filepath.FromSlash("/a"), filepath.FromSlash("b/c/")}, 31 {filepath.FromSlash("/c"), filepath.FromSlash("/a/b"), filepath.FromSlash("../../c")}, 32 {filepath.FromSlash("/c"), "", false}, 33 } 34 for i, this := range tests { 35 // ultimately a fancy wrapper around filepath.Rel 36 result, err := GetRelativePath(this.path, this.base) 37 38 if b, ok := this.expect.(bool); ok && !b { 39 if err == nil { 40 t.Errorf("[%d] GetRelativePath didn't return an expected error", i) 41 } 42 } else { 43 if err != nil { 44 t.Errorf("[%d] GetRelativePath failed: %s", i, err) 45 continue 46 } 47 if result != this.expect { 48 t.Errorf("[%d] GetRelativePath got %v but expected %v", i, result, this.expect) 49 } 50 } 51 52 } 53 } 54 55 func TestMakePathRelative(t *testing.T) { 56 type test struct { 57 inPath, path1, path2, output string 58 } 59 60 data := []test{ 61 {"/abc/bcd/ab.css", "/abc/bcd", "/bbc/bcd", "/ab.css"}, 62 {"/abc/bcd/ab.css", "/abcd/bcd", "/abc/bcd", "/ab.css"}, 63 } 64 65 for i, d := range data { 66 output, _ := makePathRelative(d.inPath, d.path1, d.path2) 67 if d.output != output { 68 t.Errorf("Test #%d failed. Expected %q got %q", i, d.output, output) 69 } 70 } 71 _, error := makePathRelative("a/b/c.ss", "/a/c", "/d/c", "/e/f") 72 73 if error == nil { 74 t.Errorf("Test failed, expected error") 75 } 76 } 77 78 func TestGetDottedRelativePath(t *testing.T) { 79 // on Windows this will receive both kinds, both country and western ... 80 for _, f := range []func(string) string{filepath.FromSlash, func(s string) string { return s }} { 81 doTestGetDottedRelativePath(f, t) 82 } 83 } 84 85 func doTestGetDottedRelativePath(urlFixer func(string) string, t *testing.T) { 86 type test struct { 87 input, expected string 88 } 89 data := []test{ 90 {"", "./"}, 91 {urlFixer("/"), "./"}, 92 {urlFixer("post"), "../"}, 93 {urlFixer("/post"), "../"}, 94 {urlFixer("post/"), "../"}, 95 {urlFixer("tags/foo.html"), "../"}, 96 {urlFixer("/tags/foo.html"), "../"}, 97 {urlFixer("/post/"), "../"}, 98 {urlFixer("////post/////"), "../"}, 99 {urlFixer("/foo/bar/index.html"), "../../"}, 100 {urlFixer("/foo/bar/foo/"), "../../../"}, 101 {urlFixer("/foo/bar/foo"), "../../../"}, 102 {urlFixer("foo/bar/foo/"), "../../../"}, 103 {urlFixer("foo/bar/foo/bar"), "../../../../"}, 104 {"404.html", "./"}, 105 {"404.xml", "./"}, 106 {"/404.html", "./"}, 107 } 108 for i, d := range data { 109 output := GetDottedRelativePath(d.input) 110 if d.expected != output { 111 t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) 112 } 113 } 114 } 115 116 func TestMakeTitle(t *testing.T) { 117 type test struct { 118 input, expected string 119 } 120 data := []test{ 121 {"Make-Title", "Make Title"}, 122 {"MakeTitle", "MakeTitle"}, 123 {"make_title", "make_title"}, 124 } 125 for i, d := range data { 126 output := MakeTitle(d.input) 127 if d.expected != output { 128 t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) 129 } 130 } 131 } 132 133 // Replace Extension is probably poorly named, but the intent of the 134 // function is to accept a path and return only the file name with a 135 // new extension. It's intentionally designed to strip out the path 136 // and only provide the name. We should probably rename the function to 137 // be more explicit at some point. 138 func TestReplaceExtension(t *testing.T) { 139 type test struct { 140 input, newext, expected string 141 } 142 data := []test{ 143 // These work according to the above definition 144 {"/some/random/path/file.xml", "html", "file.html"}, 145 {"/banana.html", "xml", "banana.xml"}, 146 {"./banana.html", "xml", "banana.xml"}, 147 {"banana/pie/index.html", "xml", "index.xml"}, 148 {"../pies/fish/index.html", "xml", "index.xml"}, 149 // but these all fail 150 {"filename-without-an-ext", "ext", "filename-without-an-ext.ext"}, 151 {"/filename-without-an-ext", "ext", "filename-without-an-ext.ext"}, 152 {"/directory/mydir/", "ext", ".ext"}, 153 {"mydir/", "ext", ".ext"}, 154 } 155 156 for i, d := range data { 157 output := ReplaceExtension(filepath.FromSlash(d.input), d.newext) 158 if d.expected != output { 159 t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) 160 } 161 } 162 } 163 164 func TestExtNoDelimiter(t *testing.T) { 165 c := qt.New(t) 166 c.Assert(ExtNoDelimiter(filepath.FromSlash("/my/data.json")), qt.Equals, "json") 167 } 168 169 func TestFilename(t *testing.T) { 170 type test struct { 171 input, expected string 172 } 173 data := []test{ 174 {"index.html", "index"}, 175 {"./index.html", "index"}, 176 {"/index.html", "index"}, 177 {"index", "index"}, 178 {"/tmp/index.html", "index"}, 179 {"./filename-no-ext", "filename-no-ext"}, 180 {"/filename-no-ext", "filename-no-ext"}, 181 {"filename-no-ext", "filename-no-ext"}, 182 {"directory/", ""}, // no filename case?? 183 {"directory/.hidden.ext", ".hidden"}, 184 {"./directory/../~/banana/gold.fish", "gold"}, 185 {"../directory/banana.man", "banana"}, 186 {"~/mydir/filename.ext", "filename"}, 187 {"./directory//tmp/filename.ext", "filename"}, 188 } 189 190 for i, d := range data { 191 output := Filename(filepath.FromSlash(d.input)) 192 if d.expected != output { 193 t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) 194 } 195 } 196 } 197 198 func TestFileAndExt(t *testing.T) { 199 type test struct { 200 input, expectedFile, expectedExt string 201 } 202 data := []test{ 203 {"index.html", "index", ".html"}, 204 {"./index.html", "index", ".html"}, 205 {"/index.html", "index", ".html"}, 206 {"index", "index", ""}, 207 {"/tmp/index.html", "index", ".html"}, 208 {"./filename-no-ext", "filename-no-ext", ""}, 209 {"/filename-no-ext", "filename-no-ext", ""}, 210 {"filename-no-ext", "filename-no-ext", ""}, 211 {"directory/", "", ""}, // no filename case?? 212 {"directory/.hidden.ext", ".hidden", ".ext"}, 213 {"./directory/../~/banana/gold.fish", "gold", ".fish"}, 214 {"../directory/banana.man", "banana", ".man"}, 215 {"~/mydir/filename.ext", "filename", ".ext"}, 216 {"./directory//tmp/filename.ext", "filename", ".ext"}, 217 } 218 219 for i, d := range data { 220 file, ext := fileAndExt(filepath.FromSlash(d.input), fpb) 221 if d.expectedFile != file { 222 t.Errorf("Test %d failed. Expected filename %q got %q.", i, d.expectedFile, file) 223 } 224 if d.expectedExt != ext { 225 t.Errorf("Test %d failed. Expected extension %q got %q.", i, d.expectedExt, ext) 226 } 227 } 228 }