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 }