github.com/neohugo/neohugo@v0.123.8/resources/resource_transformers/js/options_test.go (about) 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" 18 "path/filepath" 19 "testing" 20 21 "github.com/neohugo/neohugo/config" 22 "github.com/neohugo/neohugo/config/testconfig" 23 "github.com/neohugo/neohugo/hugofs" 24 "github.com/neohugo/neohugo/hugolib/filesystems" 25 "github.com/neohugo/neohugo/hugolib/paths" 26 "github.com/neohugo/neohugo/media" 27 28 "github.com/spf13/afero" 29 30 "github.com/evanw/esbuild/pkg/api" 31 32 qt "github.com/frankban/quicktest" 33 ) 34 35 // This test is added to test/warn against breaking the "stability" of the 36 // cache key. It's sometimes needed to break this, but should be avoided if possible. 37 func TestOptionKey(t *testing.T) { 38 c := qt.New(t) 39 40 opts := map[string]any{ 41 "TargetPath": "foo", 42 "Target": "es2018", 43 } 44 45 key := (&buildTransformation{optsm: opts}).Key() 46 47 c.Assert(key.Value(), qt.Equals, "jsbuild_7891849149754191852") 48 } 49 50 func TestToBuildOptions(t *testing.T) { 51 c := qt.New(t) 52 53 opts, err := toBuildOptions(Options{mediaType: media.Builtin.JavascriptType}) 54 55 c.Assert(err, qt.IsNil) 56 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 57 Bundle: true, 58 Target: api.ESNext, 59 Format: api.FormatIIFE, 60 LegalComments: api.LegalCommentsEndOfFile, 61 Stdin: &api.StdinOptions{ 62 Loader: api.LoaderJS, 63 }, 64 }) 65 66 opts, err = toBuildOptions(Options{ 67 Target: "es2018", 68 Format: "cjs", 69 Minify: true, 70 mediaType: media.Builtin.JavascriptType, 71 AvoidTDZ: true, 72 }) 73 c.Assert(err, qt.IsNil) 74 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 75 Bundle: true, 76 Target: api.ES2018, 77 Format: api.FormatCommonJS, 78 MinifyIdentifiers: true, 79 MinifySyntax: true, 80 MinifyWhitespace: true, 81 LegalComments: api.LegalCommentsNone, 82 Stdin: &api.StdinOptions{ 83 Loader: api.LoaderJS, 84 }, 85 }) 86 87 opts, err = toBuildOptions(Options{ 88 Target: "es2018", Format: "cjs", Minify: true, mediaType: media.Builtin.JavascriptType, 89 SourceMap: "inline", 90 }) 91 c.Assert(err, qt.IsNil) 92 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 93 Bundle: true, 94 Target: api.ES2018, 95 Format: api.FormatCommonJS, 96 MinifyIdentifiers: true, 97 MinifySyntax: true, 98 MinifyWhitespace: true, 99 LegalComments: api.LegalCommentsNone, 100 Sourcemap: api.SourceMapInline, 101 Stdin: &api.StdinOptions{ 102 Loader: api.LoaderJS, 103 }, 104 }) 105 106 opts, err = toBuildOptions(Options{ 107 Target: "es2018", Format: "cjs", Minify: true, mediaType: media.Builtin.JavascriptType, 108 SourceMap: "inline", 109 }) 110 c.Assert(err, qt.IsNil) 111 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 112 Bundle: true, 113 Target: api.ES2018, 114 Format: api.FormatCommonJS, 115 MinifyIdentifiers: true, 116 MinifySyntax: true, 117 MinifyWhitespace: true, 118 LegalComments: api.LegalCommentsNone, 119 Sourcemap: api.SourceMapInline, 120 Stdin: &api.StdinOptions{ 121 Loader: api.LoaderJS, 122 }, 123 }) 124 125 opts, err = toBuildOptions(Options{ 126 Target: "es2018", Format: "cjs", Minify: true, mediaType: media.Builtin.JavascriptType, 127 SourceMap: "external", 128 }) 129 c.Assert(err, qt.IsNil) 130 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 131 Bundle: true, 132 Target: api.ES2018, 133 Format: api.FormatCommonJS, 134 MinifyIdentifiers: true, 135 MinifySyntax: true, 136 MinifyWhitespace: true, 137 LegalComments: api.LegalCommentsNone, 138 Sourcemap: api.SourceMapExternal, 139 Stdin: &api.StdinOptions{ 140 Loader: api.LoaderJS, 141 }, 142 }) 143 144 opts, err = toBuildOptions(Options{ 145 mediaType: media.Builtin.JavascriptType, 146 JSX: "automatic", JSXImportSource: "preact", 147 }) 148 c.Assert(err, qt.IsNil) 149 c.Assert(opts, qt.DeepEquals, api.BuildOptions{ 150 Bundle: true, 151 Target: api.ESNext, 152 Format: api.FormatIIFE, 153 Stdin: &api.StdinOptions{ 154 Loader: api.LoaderJS, 155 }, 156 LegalComments: api.LegalCommentsEndOfFile, 157 JSX: api.JSXAutomatic, 158 JSXImportSource: "preact", 159 }) 160 } 161 162 func TestResolveComponentInAssets(t *testing.T) { 163 c := qt.New(t) 164 165 for _, test := range []struct { 166 name string 167 files []string 168 impPath string 169 expect string 170 }{ 171 {"Basic, extension", []string{"foo.js", "bar.js"}, "foo.js", "foo.js"}, 172 {"Basic, no extension", []string{"foo.js", "bar.js"}, "foo", "foo.js"}, 173 {"Basic, no extension, typescript", []string{"foo.ts", "bar.js"}, "foo", "foo.ts"}, 174 {"Not found", []string{"foo.js", "bar.js"}, "moo.js", ""}, 175 {"Not found, double js extension", []string{"foo.js.js", "bar.js"}, "foo.js", ""}, 176 {"Index file, folder only", []string{"foo/index.js", "bar.js"}, "foo", "foo/index.js"}, 177 {"Index file, folder and index", []string{"foo/index.js", "bar.js"}, "foo/index", "foo/index.js"}, 178 {"Index file, folder and index and suffix", []string{"foo/index.js", "bar.js"}, "foo/index.js", "foo/index.js"}, 179 {"Index ESM file, folder only", []string{"foo/index.esm.js", "bar.js"}, "foo", "foo/index.esm.js"}, 180 {"Index ESM file, folder and index", []string{"foo/index.esm.js", "bar.js"}, "foo/index", "foo/index.esm.js"}, 181 {"Index ESM file, folder and index and suffix", []string{"foo/index.esm.js", "bar.js"}, "foo/index.esm.js", "foo/index.esm.js"}, 182 // 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 183 // to document Hugo's behavior. We pick the file with the name index.js; anything else would be breaking. 184 {"Index and Index ESM file, folder only", []string{"foo/index.esm.js", "foo/index.js", "bar.js"}, "foo", "foo/index.js"}, 185 186 // Issue #8949 187 {"Check file before directory", []string{"foo.js", "foo/index.js"}, "foo", "foo.js"}, 188 } { 189 c.Run(test.name, func(c *qt.C) { 190 baseDir := "assets" 191 mfs := afero.NewMemMapFs() 192 193 for _, filename := range test.files { 194 c.Assert(afero.WriteFile(mfs, filepath.Join(baseDir, filename), []byte("let foo='bar';"), 0o777), qt.IsNil) 195 } 196 197 conf := testconfig.GetTestConfig(mfs, config.New()) 198 fs := hugofs.NewFrom(mfs, conf.BaseConfig()) 199 200 p, err := paths.New(fs, conf) 201 c.Assert(err, qt.IsNil) 202 bfs, err := filesystems.NewBase(p, nil) 203 c.Assert(err, qt.IsNil) 204 205 got := resolveComponentInAssets(bfs.Assets.Fs, test.impPath) 206 207 gotPath := "" 208 expect := test.expect 209 if got != nil { 210 gotPath = filepath.ToSlash(got.Filename) 211 expect = path.Join(baseDir, test.expect) 212 } 213 214 c.Assert(gotPath, qt.Equals, expect) 215 }) 216 } 217 }