options_test.go (5775B)
1 // Copyright 2020 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 js 15 16 import ( 17 "path/filepath" 18 "testing" 19 20 "github.com/gohugoio/hugo/hugofs" 21 22 "github.com/spf13/afero" 23 24 "github.com/gohugoio/hugo/media" 25 26 "github.com/evanw/esbuild/pkg/api" 27 28 qt "github.com/frankban/quicktest" 29 ) 30 31 // This test is added to test/warn against breaking the "stability" of the 32 // cache key. It's sometimes needed to break this, but should be avoided if possible. 33 func TestOptionKey(t *testing.T) { 34 c := qt.New(t) 35 36 opts := map[string]any{ 37 "TargetPath": "foo", 38 "Target": "es2018", 39 } 40 41 key := (&buildTransformation{optsm: opts}).Key() 42 43 c.Assert(key.Value(), qt.Equals, "jsbuild_7891849149754191852") 44 } 45 46 func TestToBuildOptions(t *testing.T) { 47 c := qt.New(t) 48 49 opts, err := toBuildOptions(Options{mediaType: media.JavascriptType}) 50 51 c.Assert(err, qt.IsNil) 52 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 53 Bundle: true, 54 Target: api.ESNext, 55 Format: api.FormatIIFE, 56 Stdin: &api.StdinOptions{ 57 Loader: api.LoaderJS, 58 }, 59 }) 60 61 opts, err = toBuildOptions(Options{ 62 Target: "es2018", 63 Format: "cjs", 64 Minify: true, 65 mediaType: media.JavascriptType, 66 AvoidTDZ: true, 67 }) 68 c.Assert(err, qt.IsNil) 69 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 70 Bundle: true, 71 Target: api.ES2018, 72 Format: api.FormatCommonJS, 73 MinifyIdentifiers: true, 74 MinifySyntax: true, 75 MinifyWhitespace: true, 76 Stdin: &api.StdinOptions{ 77 Loader: api.LoaderJS, 78 }, 79 }) 80 81 opts, err = toBuildOptions(Options{ 82 Target: "es2018", Format: "cjs", Minify: true, mediaType: media.JavascriptType, 83 SourceMap: "inline", 84 }) 85 c.Assert(err, qt.IsNil) 86 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 87 Bundle: true, 88 Target: api.ES2018, 89 Format: api.FormatCommonJS, 90 MinifyIdentifiers: true, 91 MinifySyntax: true, 92 MinifyWhitespace: true, 93 Sourcemap: api.SourceMapInline, 94 Stdin: &api.StdinOptions{ 95 Loader: api.LoaderJS, 96 }, 97 }) 98 99 opts, err = toBuildOptions(Options{ 100 Target: "es2018", Format: "cjs", Minify: true, mediaType: media.JavascriptType, 101 SourceMap: "inline", 102 }) 103 c.Assert(err, qt.IsNil) 104 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 105 Bundle: true, 106 Target: api.ES2018, 107 Format: api.FormatCommonJS, 108 MinifyIdentifiers: true, 109 MinifySyntax: true, 110 MinifyWhitespace: true, 111 Sourcemap: api.SourceMapInline, 112 Stdin: &api.StdinOptions{ 113 Loader: api.LoaderJS, 114 }, 115 }) 116 117 opts, err = toBuildOptions(Options{ 118 Target: "es2018", Format: "cjs", Minify: true, mediaType: media.JavascriptType, 119 SourceMap: "external", 120 }) 121 c.Assert(err, qt.IsNil) 122 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 123 Bundle: true, 124 Target: api.ES2018, 125 Format: api.FormatCommonJS, 126 MinifyIdentifiers: true, 127 MinifySyntax: true, 128 MinifyWhitespace: true, 129 Sourcemap: api.SourceMapExternal, 130 Stdin: &api.StdinOptions{ 131 Loader: api.LoaderJS, 132 }, 133 }) 134 } 135 136 func TestResolveComponentInAssets(t *testing.T) { 137 c := qt.New(t) 138 139 for _, test := range []struct { 140 name string 141 files []string 142 impPath string 143 expect string 144 }{ 145 {"Basic, extension", []string{"foo.js", "bar.js"}, "foo.js", "foo.js"}, 146 {"Basic, no extension", []string{"foo.js", "bar.js"}, "foo", "foo.js"}, 147 {"Basic, no extension, typescript", []string{"foo.ts", "bar.js"}, "foo", "foo.ts"}, 148 {"Not found", []string{"foo.js", "bar.js"}, "moo.js", ""}, 149 {"Not found, double js extension", []string{"foo.js.js", "bar.js"}, "foo.js", ""}, 150 {"Index file, folder only", []string{"foo/index.js", "bar.js"}, "foo", "foo/index.js"}, 151 {"Index file, folder and index", []string{"foo/index.js", "bar.js"}, "foo/index", "foo/index.js"}, 152 {"Index file, folder and index and suffix", []string{"foo/index.js", "bar.js"}, "foo/index.js", "foo/index.js"}, 153 {"Index ESM file, folder only", []string{"foo/index.esm.js", "bar.js"}, "foo", "foo/index.esm.js"}, 154 {"Index ESM file, folder and index", []string{"foo/index.esm.js", "bar.js"}, "foo/index", "foo/index.esm.js"}, 155 {"Index ESM file, folder and index and suffix", []string{"foo/index.esm.js", "bar.js"}, "foo/index.esm.js", "foo/index.esm.js"}, 156 // We added these index.esm.js cases in v0.101.0. The case below is unlikely to happen in the wild, but add a test 157 // to document Hugo's behavior. We pick the file with the name index.js; anything else would be breaking. 158 {"Index and Index ESM file, folder only", []string{"foo/index.esm.js", "foo/index.js", "bar.js"}, "foo", "foo/index.js"}, 159 160 // Issue #8949 161 {"Check file before directory", []string{"foo.js", "foo/index.js"}, "foo", "foo.js"}, 162 } { 163 c.Run(test.name, func(c *qt.C) { 164 baseDir := "assets" 165 mfs := afero.NewMemMapFs() 166 167 for _, filename := range test.files { 168 c.Assert(afero.WriteFile(mfs, filepath.Join(baseDir, filename), []byte("let foo='bar';"), 0777), qt.IsNil) 169 } 170 171 bfs := hugofs.DecorateBasePathFs(afero.NewBasePathFs(mfs, baseDir).(*afero.BasePathFs)) 172 173 got := resolveComponentInAssets(bfs, test.impPath) 174 175 gotPath := "" 176 if got != nil { 177 gotPath = filepath.ToSlash(got.Path) 178 } 179 180 c.Assert(gotPath, qt.Equals, test.expect) 181 }) 182 183 } 184 }