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  }