hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

data_test.go (8744B)

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