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  }