github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/tpl/data/data_test.go (about) 1 // Copyright 2017 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 data 15 16 import ( 17 "bytes" 18 "html/template" 19 "net/http" 20 "net/http/httptest" 21 "path/filepath" 22 "strings" 23 "testing" 24 25 "github.com/bep/logg" 26 "github.com/gohugoio/hugo/common/maps" 27 28 qt "github.com/frankban/quicktest" 29 ) 30 31 func TestGetCSV(t *testing.T) { 32 t.Parallel() 33 c := qt.New(t) 34 35 for i, test := range []struct { 36 sep string 37 url string 38 content string 39 expect any 40 }{ 41 // Remotes 42 { 43 ",", 44 `http://success/`, 45 "gomeetup,city\nyes,Sydney\nyes,San Francisco\nyes,Stockholm\n", 46 [][]string{{"gomeetup", "city"}, {"yes", "Sydney"}, {"yes", "San Francisco"}, {"yes", "Stockholm"}}, 47 }, 48 { 49 ",", 50 `http://error.extra.field/`, 51 "gomeetup,city\nyes,Sydney\nyes,San Francisco\nyes,Stockholm,EXTRA\n", 52 false, 53 }, 54 { 55 ",", 56 `http://nofound/404`, 57 ``, 58 false, 59 }, 60 61 // Locals 62 { 63 ";", 64 "pass/semi", 65 "gomeetup;city\nyes;Sydney\nyes;San Francisco\nyes;Stockholm\n", 66 [][]string{{"gomeetup", "city"}, {"yes", "Sydney"}, {"yes", "San Francisco"}, {"yes", "Stockholm"}}, 67 }, 68 { 69 ";", 70 "fail/no-file", 71 "", 72 false, 73 }, 74 } { 75 76 c.Run(test.url, func(c *qt.C) { 77 msg := qt.Commentf("Test %d", i) 78 79 ns := newTestNs() 80 81 // Setup HTTP test server 82 var srv *httptest.Server 83 srv, ns.client = getTestServer(func(w http.ResponseWriter, r *http.Request) { 84 if !hasHeaderValue(r.Header, "Accept", "text/csv") && !hasHeaderValue(r.Header, "Accept", "text/plain") { 85 http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 86 return 87 } 88 89 if r.URL.Path == "/404" { 90 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 91 return 92 } 93 94 w.Header().Add("Content-type", "text/csv") 95 96 w.Write([]byte(test.content)) 97 }) 98 defer func() { srv.Close() }() 99 100 // Setup local test file for schema-less URLs 101 if !strings.Contains(test.url, ":") && !strings.HasPrefix(test.url, "fail/") { 102 f, err := ns.deps.Fs.Source.Create(filepath.Join(ns.deps.Conf.BaseConfig().WorkingDir, test.url)) 103 c.Assert(err, qt.IsNil, msg) 104 f.WriteString(test.content) 105 f.Close() 106 } 107 108 // Get on with it 109 got, err := ns.GetCSV(test.sep, test.url) 110 111 if _, ok := test.expect.(bool); ok { 112 c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 1) 113 c.Assert(got, qt.IsNil) 114 return 115 } 116 117 c.Assert(err, qt.IsNil, msg) 118 c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 0) 119 c.Assert(got, qt.Not(qt.IsNil), msg) 120 c.Assert(got, qt.DeepEquals, test.expect, msg) 121 }) 122 123 } 124 } 125 126 func TestGetJSON(t *testing.T) { 127 t.Parallel() 128 c := qt.New(t) 129 130 for i, test := range []struct { 131 url string 132 content string 133 expect any 134 }{ 135 { 136 `http://success/`, 137 `{"gomeetup":["Sydney","San Francisco","Stockholm"]}`, 138 map[string]any{"gomeetup": []any{"Sydney", "San Francisco", "Stockholm"}}, 139 }, 140 { 141 `http://malformed/`, 142 `{gomeetup:["Sydney","San Francisco","Stockholm"]}`, 143 false, 144 }, 145 { 146 `http://nofound/404`, 147 ``, 148 false, 149 }, 150 // Locals 151 { 152 "pass/semi", 153 `{"gomeetup":["Sydney","San Francisco","Stockholm"]}`, 154 map[string]any{"gomeetup": []any{"Sydney", "San Francisco", "Stockholm"}}, 155 }, 156 { 157 "fail/no-file", 158 "", 159 false, 160 }, 161 { 162 `pass/üńīçøðê-url.json`, 163 `{"gomeetup":["Sydney","San Francisco","Stockholm"]}`, 164 map[string]any{"gomeetup": []any{"Sydney", "San Francisco", "Stockholm"}}, 165 }, 166 } { 167 168 c.Run(test.url, func(c *qt.C) { 169 170 msg := qt.Commentf("Test %d", i) 171 ns := newTestNs() 172 173 // Setup HTTP test server 174 var srv *httptest.Server 175 srv, ns.client = getTestServer(func(w http.ResponseWriter, r *http.Request) { 176 if !hasHeaderValue(r.Header, "Accept", "application/json") { 177 http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 178 return 179 } 180 181 if r.URL.Path == "/404" { 182 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 183 return 184 } 185 186 w.Header().Add("Content-type", "application/json") 187 188 w.Write([]byte(test.content)) 189 }) 190 defer func() { srv.Close() }() 191 192 // Setup local test file for schema-less URLs 193 if !strings.Contains(test.url, ":") && !strings.HasPrefix(test.url, "fail/") { 194 f, err := ns.deps.Fs.Source.Create(filepath.Join(ns.deps.Conf.BaseConfig().WorkingDir, test.url)) 195 c.Assert(err, qt.IsNil, msg) 196 f.WriteString(test.content) 197 f.Close() 198 } 199 200 // Get on with it 201 got, _ := ns.GetJSON(test.url) 202 203 if _, ok := test.expect.(bool); ok { 204 c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 1) 205 return 206 } 207 208 c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 0, msg) 209 c.Assert(got, qt.Not(qt.IsNil), msg) 210 c.Assert(got, qt.DeepEquals, test.expect) 211 212 }) 213 } 214 } 215 216 func TestHeaders(t *testing.T) { 217 t.Parallel() 218 c := qt.New(t) 219 220 for _, test := range []struct { 221 name string 222 headers any 223 assert func(c *qt.C, headers string) 224 }{ 225 { 226 `Misc header variants`, 227 map[string]any{ 228 "Accept-Charset": "utf-8", 229 "Max-forwards": "10", 230 "X-Int": 32, 231 "X-Templ": template.HTML("a"), 232 "X-Multiple": []string{"a", "b"}, 233 "X-MultipleInt": []int{3, 4}, 234 }, 235 func(c *qt.C, headers string) { 236 c.Assert(headers, qt.Contains, "Accept-Charset: utf-8") 237 c.Assert(headers, qt.Contains, "Max-Forwards: 10") 238 c.Assert(headers, qt.Contains, "X-Int: 32") 239 c.Assert(headers, qt.Contains, "X-Templ: a") 240 c.Assert(headers, qt.Contains, "X-Multiple: a") 241 c.Assert(headers, qt.Contains, "X-Multiple: b") 242 c.Assert(headers, qt.Contains, "X-Multipleint: 3") 243 c.Assert(headers, qt.Contains, "X-Multipleint: 4") 244 c.Assert(headers, qt.Contains, "User-Agent: Hugo Static Site Generator") 245 }, 246 }, 247 { 248 `Params`, 249 maps.Params{ 250 "Accept-Charset": "utf-8", 251 }, 252 func(c *qt.C, headers string) { 253 c.Assert(headers, qt.Contains, "Accept-Charset: utf-8") 254 }, 255 }, 256 { 257 `Override User-Agent`, 258 map[string]any{ 259 "User-Agent": "007", 260 }, 261 func(c *qt.C, headers string) { 262 c.Assert(headers, qt.Contains, "User-Agent: 007") 263 }, 264 }, 265 } { 266 267 c.Run(test.name, func(c *qt.C) { 268 269 ns := newTestNs() 270 271 // Setup HTTP test server 272 var srv *httptest.Server 273 var headers bytes.Buffer 274 srv, ns.client = getTestServer(func(w http.ResponseWriter, r *http.Request) { 275 c.Assert(r.URL.String(), qt.Equals, "http://gohugo.io/api?foo") 276 w.Write([]byte("{}")) 277 r.Header.Write(&headers) 278 279 }) 280 defer func() { srv.Close() }() 281 282 testFunc := func(fn func(args ...any) error) { 283 defer headers.Reset() 284 err := fn("http://example.org/api", "?foo", test.headers) 285 286 c.Assert(err, qt.IsNil) 287 c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 0) 288 test.assert(c, headers.String()) 289 } 290 291 testFunc(func(args ...any) error { 292 _, err := ns.GetJSON(args...) 293 return err 294 }) 295 testFunc(func(args ...any) error { 296 _, err := ns.GetCSV(",", args...) 297 return err 298 }) 299 300 }) 301 302 } 303 } 304 305 func TestToURLAndHeaders(t *testing.T) { 306 t.Parallel() 307 c := qt.New(t) 308 url, headers := toURLAndHeaders([]any{"https://foo?id=", 32}) 309 c.Assert(url, qt.Equals, "https://foo?id=32") 310 c.Assert(headers, qt.IsNil) 311 312 url, headers = toURLAndHeaders([]any{"https://foo?id=", 32, map[string]any{"a": "b"}}) 313 c.Assert(url, qt.Equals, "https://foo?id=32") 314 c.Assert(headers, qt.DeepEquals, map[string]any{"a": "b"}) 315 } 316 317 func TestParseCSV(t *testing.T) { 318 t.Parallel() 319 c := qt.New(t) 320 321 for i, test := range []struct { 322 csv []byte 323 sep string 324 exp string 325 err bool 326 }{ 327 {[]byte("a,b,c\nd,e,f\n"), "", "", true}, 328 {[]byte("a,b,c\nd,e,f\n"), "~/", "", true}, 329 {[]byte("a,b,c\nd,e,f"), "|", "a,b,cd,e,f", false}, 330 {[]byte("q,w,e\nd,e,f"), ",", "qwedef", false}, 331 {[]byte("a|b|c\nd|e|f|g"), "|", "abcdefg", true}, 332 {[]byte("z|y|c\nd|e|f"), "|", "zycdef", false}, 333 } { 334 msg := qt.Commentf("Test %d: %v", i, test) 335 336 csv, err := parseCSV(test.csv, test.sep) 337 if test.err { 338 c.Assert(err, qt.Not(qt.IsNil), msg) 339 continue 340 } 341 c.Assert(err, qt.IsNil, msg) 342 343 act := "" 344 for _, v := range csv { 345 act = act + strings.Join(v, "") 346 } 347 348 c.Assert(act, qt.Equals, test.exp, msg) 349 } 350 }