github.com/gohugoio/hugo@v0.88.1/media/mediaType_test.go (about)

     1  // Copyright 2019 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 media
    15  
    16  import (
    17  	"encoding/json"
    18  	"sort"
    19  	"testing"
    20  
    21  	qt "github.com/frankban/quicktest"
    22  )
    23  
    24  func TestDefaultTypes(t *testing.T) {
    25  	c := qt.New(t)
    26  	for _, test := range []struct {
    27  		tp               Type
    28  		expectedMainType string
    29  		expectedSubType  string
    30  		expectedSuffix   string
    31  		expectedType     string
    32  		expectedString   string
    33  	}{
    34  		{CalendarType, "text", "calendar", "ics", "text/calendar", "text/calendar"},
    35  		{CSSType, "text", "css", "css", "text/css", "text/css"},
    36  		{SCSSType, "text", "x-scss", "scss", "text/x-scss", "text/x-scss"},
    37  		{CSVType, "text", "csv", "csv", "text/csv", "text/csv"},
    38  		{HTMLType, "text", "html", "html", "text/html", "text/html"},
    39  		{JavascriptType, "application", "javascript", "js", "application/javascript", "application/javascript"},
    40  		{TypeScriptType, "application", "typescript", "ts", "application/typescript", "application/typescript"},
    41  		{TSXType, "text", "tsx", "tsx", "text/tsx", "text/tsx"},
    42  		{JSXType, "text", "jsx", "jsx", "text/jsx", "text/jsx"},
    43  		{JSONType, "application", "json", "json", "application/json", "application/json"},
    44  		{RSSType, "application", "rss", "xml", "application/rss+xml", "application/rss+xml"},
    45  		{SVGType, "image", "svg", "svg", "image/svg+xml", "image/svg+xml"},
    46  		{TextType, "text", "plain", "txt", "text/plain", "text/plain"},
    47  		{XMLType, "application", "xml", "xml", "application/xml", "application/xml"},
    48  		{TOMLType, "application", "toml", "toml", "application/toml", "application/toml"},
    49  		{YAMLType, "application", "yaml", "yaml", "application/yaml", "application/yaml"},
    50  	} {
    51  		c.Assert(test.tp.MainType, qt.Equals, test.expectedMainType)
    52  		c.Assert(test.tp.SubType, qt.Equals, test.expectedSubType)
    53  
    54  		c.Assert(test.tp.Type(), qt.Equals, test.expectedType)
    55  		c.Assert(test.tp.String(), qt.Equals, test.expectedString)
    56  
    57  	}
    58  
    59  	c.Assert(len(DefaultTypes), qt.Equals, 28)
    60  }
    61  
    62  func TestGetByType(t *testing.T) {
    63  	c := qt.New(t)
    64  
    65  	types := Types{HTMLType, RSSType}
    66  
    67  	mt, found := types.GetByType("text/HTML")
    68  	c.Assert(found, qt.Equals, true)
    69  	c.Assert(HTMLType, qt.Equals, mt)
    70  
    71  	_, found = types.GetByType("text/nono")
    72  	c.Assert(found, qt.Equals, false)
    73  
    74  	mt, found = types.GetByType("application/rss+xml")
    75  	c.Assert(found, qt.Equals, true)
    76  	c.Assert(RSSType, qt.Equals, mt)
    77  
    78  	mt, found = types.GetByType("application/rss")
    79  	c.Assert(found, qt.Equals, true)
    80  	c.Assert(RSSType, qt.Equals, mt)
    81  }
    82  
    83  func TestGetByMainSubType(t *testing.T) {
    84  	c := qt.New(t)
    85  	f, found := DefaultTypes.GetByMainSubType("text", "plain")
    86  	c.Assert(found, qt.Equals, true)
    87  	c.Assert(f, qt.Equals, TextType)
    88  	_, found = DefaultTypes.GetByMainSubType("foo", "plain")
    89  	c.Assert(found, qt.Equals, false)
    90  }
    91  
    92  func TestBySuffix(t *testing.T) {
    93  	c := qt.New(t)
    94  	formats := DefaultTypes.BySuffix("xml")
    95  	c.Assert(len(formats), qt.Equals, 2)
    96  	c.Assert(formats[0].SubType, qt.Equals, "rss")
    97  	c.Assert(formats[1].SubType, qt.Equals, "xml")
    98  }
    99  
   100  func TestGetFirstBySuffix(t *testing.T) {
   101  	c := qt.New(t)
   102  
   103  	types := DefaultTypes
   104  
   105  	// Issue #8406
   106  	geoJSON := newMediaTypeWithMimeSuffix("application", "geo", "json", []string{"geojson", "gjson"})
   107  	types = append(types, geoJSON)
   108  	sort.Sort(types)
   109  
   110  	check := func(suffix string, expectedType Type) {
   111  		t, f, found := types.GetFirstBySuffix(suffix)
   112  		c.Assert(found, qt.Equals, true)
   113  		c.Assert(f, qt.Equals, SuffixInfo{
   114  			Suffix:     suffix,
   115  			FullSuffix: "." + suffix})
   116  		c.Assert(t, qt.Equals, expectedType)
   117  	}
   118  
   119  	check("js", JavascriptType)
   120  	check("json", JSONType)
   121  	check("geojson", geoJSON)
   122  	check("gjson", geoJSON)
   123  
   124  }
   125  
   126  func TestFromTypeString(t *testing.T) {
   127  	c := qt.New(t)
   128  	f, err := fromString("text/html")
   129  	c.Assert(err, qt.IsNil)
   130  	c.Assert(f.Type(), qt.Equals, HTMLType.Type())
   131  
   132  	f, err = fromString("application/custom")
   133  	c.Assert(err, qt.IsNil)
   134  	c.Assert(f, qt.Equals, Type{MainType: "application", SubType: "custom", mimeSuffix: ""})
   135  
   136  	f, err = fromString("application/custom+sfx")
   137  	c.Assert(err, qt.IsNil)
   138  	c.Assert(f, qt.Equals, Type{MainType: "application", SubType: "custom", mimeSuffix: "sfx"})
   139  
   140  	_, err = fromString("noslash")
   141  	c.Assert(err, qt.Not(qt.IsNil))
   142  
   143  	f, err = fromString("text/xml; charset=utf-8")
   144  	c.Assert(err, qt.IsNil)
   145  
   146  	c.Assert(f, qt.Equals, Type{MainType: "text", SubType: "xml", mimeSuffix: ""})
   147  
   148  }
   149  
   150  func TestFromStringAndExt(t *testing.T) {
   151  	c := qt.New(t)
   152  	f, err := FromStringAndExt("text/html", "html")
   153  	c.Assert(err, qt.IsNil)
   154  	c.Assert(f, qt.Equals, HTMLType)
   155  	f, err = FromStringAndExt("text/html", ".html")
   156  	c.Assert(err, qt.IsNil)
   157  	c.Assert(f, qt.Equals, HTMLType)
   158  }
   159  
   160  // Add a test for the SVG case
   161  // https://github.com/gohugoio/hugo/issues/4920
   162  func TestFromExtensionMultipleSuffixes(t *testing.T) {
   163  	c := qt.New(t)
   164  	tp, si, found := DefaultTypes.GetBySuffix("svg")
   165  	c.Assert(found, qt.Equals, true)
   166  	c.Assert(tp.String(), qt.Equals, "image/svg+xml")
   167  	c.Assert(si.Suffix, qt.Equals, "svg")
   168  	c.Assert(si.FullSuffix, qt.Equals, ".svg")
   169  	c.Assert(tp.FirstSuffix.Suffix, qt.Equals, si.Suffix)
   170  	c.Assert(tp.FirstSuffix.FullSuffix, qt.Equals, si.FullSuffix)
   171  	ftp, found := DefaultTypes.GetByType("image/svg+xml")
   172  	c.Assert(found, qt.Equals, true)
   173  	c.Assert(ftp.String(), qt.Equals, "image/svg+xml")
   174  	c.Assert(found, qt.Equals, true)
   175  
   176  }
   177  
   178  func TestDecodeTypes(t *testing.T) {
   179  	c := qt.New(t)
   180  
   181  	tests := []struct {
   182  		name        string
   183  		maps        []map[string]interface{}
   184  		shouldError bool
   185  		assert      func(t *testing.T, name string, tt Types)
   186  	}{
   187  		{
   188  			"Redefine JSON",
   189  			[]map[string]interface{}{
   190  				{
   191  					"application/json": map[string]interface{}{
   192  						"suffixes": []string{"jasn"},
   193  					},
   194  				},
   195  			},
   196  			false,
   197  			func(t *testing.T, name string, tt Types) {
   198  				c.Assert(len(tt), qt.Equals, len(DefaultTypes))
   199  				json, si, found := tt.GetBySuffix("jasn")
   200  				c.Assert(found, qt.Equals, true)
   201  				c.Assert(json.String(), qt.Equals, "application/json")
   202  				c.Assert(si.FullSuffix, qt.Equals, ".jasn")
   203  			},
   204  		},
   205  		{
   206  			"MIME suffix in key, multiple file suffixes, custom delimiter",
   207  			[]map[string]interface{}{
   208  				{
   209  					"application/hugo+hg": map[string]interface{}{
   210  						"suffixes":  []string{"hg1", "hG2"},
   211  						"Delimiter": "_",
   212  					},
   213  				},
   214  			},
   215  			false,
   216  			func(t *testing.T, name string, tt Types) {
   217  				c.Assert(len(tt), qt.Equals, len(DefaultTypes)+1)
   218  				hg, si, found := tt.GetBySuffix("hg2")
   219  				c.Assert(found, qt.Equals, true)
   220  				c.Assert(hg.mimeSuffix, qt.Equals, "hg")
   221  				c.Assert(hg.FirstSuffix.Suffix, qt.Equals, "hg1")
   222  				c.Assert(hg.FirstSuffix.FullSuffix, qt.Equals, "_hg1")
   223  				c.Assert(si.Suffix, qt.Equals, "hg2")
   224  				c.Assert(si.FullSuffix, qt.Equals, "_hg2")
   225  				c.Assert(hg.String(), qt.Equals, "application/hugo+hg")
   226  
   227  				_, found = tt.GetByType("application/hugo+hg")
   228  				c.Assert(found, qt.Equals, true)
   229  
   230  			},
   231  		},
   232  		{
   233  			"Add custom media type",
   234  			[]map[string]interface{}{
   235  				{
   236  					"text/hugo+hgo": map[string]interface{}{
   237  						"Suffixes": []string{"hgo2"},
   238  					},
   239  				},
   240  			},
   241  			false,
   242  			func(t *testing.T, name string, tp Types) {
   243  				c.Assert(len(tp), qt.Equals, len(DefaultTypes)+1)
   244  				// Make sure we have not broken the default config.
   245  
   246  				_, _, found := tp.GetBySuffix("json")
   247  				c.Assert(found, qt.Equals, true)
   248  
   249  				hugo, _, found := tp.GetBySuffix("hgo2")
   250  				c.Assert(found, qt.Equals, true)
   251  				c.Assert(hugo.String(), qt.Equals, "text/hugo+hgo")
   252  			},
   253  		},
   254  	}
   255  
   256  	for _, test := range tests {
   257  		result, err := DecodeTypes(test.maps...)
   258  		if test.shouldError {
   259  			c.Assert(err, qt.Not(qt.IsNil))
   260  		} else {
   261  			c.Assert(err, qt.IsNil)
   262  			test.assert(t, test.name, result)
   263  		}
   264  	}
   265  }
   266  
   267  func TestToJSON(t *testing.T) {
   268  	c := qt.New(t)
   269  	b, err := json.Marshal(MPEGType)
   270  	c.Assert(err, qt.IsNil)
   271  	c.Assert(string(b), qt.Equals, `{"mainType":"video","subType":"mpeg","delimiter":".","firstSuffix":{"suffix":"mpg","fullSuffix":".mpg"},"type":"video/mpeg","string":"video/mpeg","suffixes":["mpg","mpeg"]}`)
   272  }
   273  
   274  func BenchmarkTypeOps(b *testing.B) {
   275  	mt := MPEGType
   276  	mts := DefaultTypes
   277  	for i := 0; i < b.N; i++ {
   278  		ff := mt.FirstSuffix
   279  		_ = ff.FullSuffix
   280  		_ = mt.IsZero()
   281  		c, err := mt.MarshalJSON()
   282  		if c == nil || err != nil {
   283  			b.Fatal("failed")
   284  		}
   285  		_ = mt.String()
   286  		_ = ff.Suffix
   287  		_ = mt.Suffixes
   288  		_ = mt.Type()
   289  		_ = mts.BySuffix("xml")
   290  		_, _ = mts.GetByMainSubType("application", "xml")
   291  		_, _, _ = mts.GetBySuffix("xml")
   292  		_, _ = mts.GetByType("application")
   293  		_, _, _ = mts.GetFirstBySuffix("xml")
   294  
   295  	}
   296  }