github.com/neohugo/neohugo@v0.123.8/hugolib/hugo_modules_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 hugolib
    15  
    16  import (
    17  	"fmt"
    18  	"math/rand"
    19  	"os"
    20  	"path/filepath"
    21  	"strings"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/bep/logg"
    26  	"github.com/neohugo/neohugo/config"
    27  	"github.com/neohugo/neohugo/modules/npm"
    28  
    29  	"github.com/spf13/afero"
    30  
    31  	"github.com/neohugo/neohugo/common/loggers"
    32  	"github.com/neohugo/neohugo/common/neohugo"
    33  
    34  	"github.com/neohugo/neohugo/htesting"
    35  	"github.com/neohugo/neohugo/hugofs"
    36  
    37  	qt "github.com/frankban/quicktest"
    38  	"github.com/gohugoio/testmodBuilder/mods"
    39  )
    40  
    41  func TestHugoModulesVariants(t *testing.T) {
    42  	if !htesting.IsCI() {
    43  		t.Skip("skip (relative) long running modules test when running locally")
    44  	}
    45  
    46  	tomlConfig := `
    47  baseURL="https://example.org"
    48  workingDir = %q
    49  
    50  [module]
    51  [[module.imports]]
    52  path="github.com/gohugoio/hugoTestModule2"
    53  %s
    54  `
    55  
    56  	createConfig := func(workingDir, moduleOpts string) string {
    57  		return fmt.Sprintf(tomlConfig, workingDir, moduleOpts)
    58  	}
    59  
    60  	newTestBuilder := func(t testing.TB, moduleOpts string) *sitesBuilder {
    61  		b := newTestSitesBuilder(t)
    62  		tempDir := t.TempDir()
    63  		workingDir := filepath.Join(tempDir, "myhugosite")
    64  		b.Assert(os.MkdirAll(workingDir, 0o777), qt.IsNil)
    65  		cfg := config.New()
    66  		cfg.Set("workingDir", workingDir)
    67  		cfg.Set("publishDir", "public")
    68  		b.Fs = hugofs.NewDefault(cfg)
    69  		b.WithWorkingDir(workingDir).WithConfigFile("toml", createConfig(workingDir, moduleOpts))
    70  		b.WithTemplates(
    71  			"index.html", `
    72  Param from module: {{ site.Params.Hugo }}|
    73  {{ $js := resources.Get "jslibs/alpinejs/alpine.js" }}
    74  JS imported in module: {{ with $js }}{{ .RelPermalink }}{{ end }}|
    75  `,
    76  			"_default/single.html", `{{ .Content }}`)
    77  		b.WithContent("p1.md", `---
    78  title: "Page"
    79  ---
    80  
    81  [A link](https://bep.is)
    82  
    83  `)
    84  		b.WithSourceFile("go.mod", `
    85  module github.com/gohugoio/tests/testHugoModules
    86  
    87  
    88  `)
    89  
    90  		b.WithSourceFile("go.sum", `
    91  github.com/gohugoio/hugoTestModule2 v0.0.0-20200131160637-9657d7697877 h1:WLM2bQCKIWo04T6NsIWsX/Vtirhf0TnpY66xyqGlgVY=
    92  github.com/gohugoio/hugoTestModule2 v0.0.0-20200131160637-9657d7697877/go.mod h1:CBFZS3khIAXKxReMwq0le8sEl/D8hcXmixlOHVv+Gd0=
    93  `)
    94  
    95  		return b
    96  	}
    97  
    98  	t.Run("Target in subfolder", func(t *testing.T) {
    99  		b := newTestBuilder(t, "ignoreImports=true")
   100  		b.Build(BuildCfg{})
   101  
   102  		b.AssertFileContent("public/p1/index.html", `<p>Page|https://bep.is|Title: |Text: A link|END</p>`)
   103  	})
   104  
   105  	t.Run("Ignore config", func(t *testing.T) {
   106  		b := newTestBuilder(t, "ignoreConfig=true")
   107  		b.Build(BuildCfg{})
   108  
   109  		b.AssertFileContent("public/index.html", `
   110  Param from module: |
   111  JS imported in module: |
   112  `)
   113  	})
   114  
   115  	t.Run("Ignore imports", func(t *testing.T) {
   116  		b := newTestBuilder(t, "ignoreImports=true")
   117  		b.Build(BuildCfg{})
   118  
   119  		b.AssertFileContent("public/index.html", `
   120  Param from module: Rocks|
   121  JS imported in module: |
   122  `)
   123  	})
   124  
   125  	t.Run("Create package.json", func(t *testing.T) {
   126  		b := newTestBuilder(t, "")
   127  
   128  		b.WithSourceFile("package.json", `{
   129  		"name": "mypack",
   130  		"version": "1.2.3",
   131          "scripts": {
   132            "client": "wait-on http://localhost:1313 && open http://localhost:1313",
   133            "start": "run-p client server",
   134  		  "test": "echo 'hoge' > hoge"
   135  		},
   136            "dependencies": {
   137          	"nonon": "error"
   138          	}
   139  }`)
   140  
   141  		b.WithSourceFile("package.hugo.json", `{
   142  		"name": "mypack",
   143  		"version": "1.2.3",
   144          "scripts": {
   145            "client": "wait-on http://localhost:1313 && open http://localhost:1313",
   146            "start": "run-p client server",
   147  		  "test": "echo 'hoge' > hoge"
   148  		},
   149            "dependencies": {
   150          	"foo": "1.2.3"
   151          	},
   152          "devDependencies": {
   153                  "postcss-cli": "7.8.0",
   154                  "tailwindcss": "1.8.0"
   155  
   156          }
   157  }`)
   158  
   159  		b.Build(BuildCfg{})
   160  		b.Assert(npm.Pack(b.H.BaseFs.ProjectSourceFs, b.H.BaseFs.AssetsWithDuplicatesPreserved.Fs), qt.IsNil)
   161  
   162  		b.AssertFileContentFn("package.json", func(s string) bool {
   163  			return s == `{
   164    "comments": {
   165      "dependencies": {
   166        "foo": "project",
   167        "react-dom": "github.com/gohugoio/hugoTestModule2"
   168      },
   169      "devDependencies": {
   170        "@babel/cli": "github.com/gohugoio/hugoTestModule2",
   171        "@babel/core": "github.com/gohugoio/hugoTestModule2",
   172        "@babel/preset-env": "github.com/gohugoio/hugoTestModule2",
   173        "postcss-cli": "project",
   174        "tailwindcss": "project"
   175      }
   176    },
   177    "dependencies": {
   178      "foo": "1.2.3",
   179      "react-dom": "^16.13.1"
   180    },
   181    "devDependencies": {
   182      "@babel/cli": "7.8.4",
   183      "@babel/core": "7.9.0",
   184      "@babel/preset-env": "7.9.5",
   185      "postcss-cli": "7.8.0",
   186      "tailwindcss": "1.8.0"
   187    },
   188    "name": "mypack",
   189    "scripts": {
   190      "client": "wait-on http://localhost:1313 && open http://localhost:1313",
   191      "start": "run-p client server",
   192      "test": "echo 'hoge' > hoge"
   193    },
   194    "version": "1.2.3"
   195  }
   196  `
   197  		})
   198  	})
   199  
   200  	t.Run("Create package.json, no default", func(t *testing.T) {
   201  		b := newTestBuilder(t, "")
   202  
   203  		const origPackageJSON = `{
   204  		"name": "mypack",
   205  		"version": "1.2.3",
   206          "scripts": {
   207            "client": "wait-on http://localhost:1313 && open http://localhost:1313",
   208            "start": "run-p client server",
   209  		  "test": "echo 'hoge' > hoge"
   210  		},
   211            "dependencies": {
   212             "moo": "1.2.3"
   213          	}
   214  }`
   215  
   216  		b.WithSourceFile("package.json", origPackageJSON)
   217  
   218  		b.Build(BuildCfg{})
   219  		b.Assert(npm.Pack(b.H.BaseFs.ProjectSourceFs, b.H.BaseFs.AssetsWithDuplicatesPreserved.Fs), qt.IsNil)
   220  
   221  		b.AssertFileContentFn("package.json", func(s string) bool {
   222  			return s == `{
   223    "comments": {
   224      "dependencies": {
   225        "moo": "project",
   226        "react-dom": "github.com/gohugoio/hugoTestModule2"
   227      },
   228      "devDependencies": {
   229        "@babel/cli": "github.com/gohugoio/hugoTestModule2",
   230        "@babel/core": "github.com/gohugoio/hugoTestModule2",
   231        "@babel/preset-env": "github.com/gohugoio/hugoTestModule2",
   232        "postcss-cli": "github.com/gohugoio/hugoTestModule2",
   233        "tailwindcss": "github.com/gohugoio/hugoTestModule2"
   234      }
   235    },
   236    "dependencies": {
   237      "moo": "1.2.3",
   238      "react-dom": "^16.13.1"
   239    },
   240    "devDependencies": {
   241      "@babel/cli": "7.8.4",
   242      "@babel/core": "7.9.0",
   243      "@babel/preset-env": "7.9.5",
   244      "postcss-cli": "7.1.0",
   245      "tailwindcss": "1.2.0"
   246    },
   247    "name": "mypack",
   248    "scripts": {
   249      "client": "wait-on http://localhost:1313 && open http://localhost:1313",
   250      "start": "run-p client server",
   251      "test": "echo 'hoge' > hoge"
   252    },
   253    "version": "1.2.3"
   254  }
   255  `
   256  		})
   257  
   258  		// https://github.com/gohugoio/hugo/issues/7690
   259  		b.AssertFileContent("package.hugo.json", origPackageJSON)
   260  	})
   261  
   262  	t.Run("Create package.json, no default, no package.json", func(t *testing.T) {
   263  		b := newTestBuilder(t, "")
   264  
   265  		b.Build(BuildCfg{})
   266  		b.Assert(npm.Pack(b.H.BaseFs.ProjectSourceFs, b.H.BaseFs.AssetsWithDuplicatesPreserved.Fs), qt.IsNil)
   267  
   268  		b.AssertFileContentFn("package.json", func(s string) bool {
   269  			return s == `{
   270    "comments": {
   271      "dependencies": {
   272        "react-dom": "github.com/gohugoio/hugoTestModule2"
   273      },
   274      "devDependencies": {
   275        "@babel/cli": "github.com/gohugoio/hugoTestModule2",
   276        "@babel/core": "github.com/gohugoio/hugoTestModule2",
   277        "@babel/preset-env": "github.com/gohugoio/hugoTestModule2",
   278        "postcss-cli": "github.com/gohugoio/hugoTestModule2",
   279        "tailwindcss": "github.com/gohugoio/hugoTestModule2"
   280      }
   281    },
   282    "dependencies": {
   283      "react-dom": "^16.13.1"
   284    },
   285    "devDependencies": {
   286      "@babel/cli": "7.8.4",
   287      "@babel/core": "7.9.0",
   288      "@babel/preset-env": "7.9.5",
   289      "postcss-cli": "7.1.0",
   290      "tailwindcss": "1.2.0"
   291    },
   292    "name": "myhugosite",
   293    "version": "0.1.0"
   294  }
   295  `
   296  		})
   297  	})
   298  }
   299  
   300  // TODO(bep) this fails when testmodBuilder is also building ...
   301  func TestHugoModulesMatrix(t *testing.T) {
   302  	if !htesting.IsCI() {
   303  		t.Skip("skip (relative) long running modules test when running locally")
   304  	}
   305  	t.Parallel()
   306  
   307  	if !htesting.IsCI() || neohugo.GoMinorVersion() < 12 {
   308  		// https://github.com/golang/go/issues/26794
   309  		// There were some concurrent issues with Go modules in < Go 12.
   310  		t.Skip("skip this on local host and for Go <= 1.11 due to a bug in Go's stdlib")
   311  	}
   312  
   313  	if testing.Short() {
   314  		t.Skip()
   315  	}
   316  
   317  	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
   318  	gooss := []string{"linux", "darwin", "windows"}
   319  	goos := gooss[rnd.Intn(len(gooss))]
   320  	ignoreVendor := rnd.Intn(2) == 0
   321  	testmods := mods.CreateModules(goos).Collect()
   322  	rnd.Shuffle(len(testmods), func(i, j int) { testmods[i], testmods[j] = testmods[j], testmods[i] })
   323  
   324  	for _, m := range testmods[:2] {
   325  		c := qt.New(t)
   326  
   327  		workingDir, clean, err := htesting.CreateTempDir(hugofs.Os, "hugo-modules-test")
   328  		c.Assert(err, qt.IsNil)
   329  		defer clean()
   330  
   331  		v := config.New()
   332  		v.Set("workingDir", workingDir)
   333  		v.Set("publishDir", "public")
   334  
   335  		configTemplate := `
   336  baseURL = "https://example.com"
   337  title = "My Modular Site"
   338  workingDir = %q
   339  theme = %q
   340  ignoreVendorPaths = %q
   341  
   342  `
   343  
   344  		ignoreVendorPaths := ""
   345  		if ignoreVendor {
   346  			ignoreVendorPaths = "github.com/**"
   347  		}
   348  		config := fmt.Sprintf(configTemplate, workingDir, m.Path(), ignoreVendorPaths)
   349  
   350  		b := newTestSitesBuilder(t)
   351  
   352  		// Need to use OS fs for this.
   353  		b.Fs = hugofs.NewDefault(v)
   354  
   355  		b.WithWorkingDir(workingDir).WithConfigFile("toml", config)
   356  		b.WithContent("page.md", `
   357  ---
   358  title: "Foo"
   359  ---
   360  `)
   361  		b.WithTemplates("home.html", `
   362  
   363  {{ $mod := .Site.Data.modinfo.module }}
   364  Mod Name: {{ $mod.name }}
   365  Mod Version: {{ $mod.version }}
   366  ----
   367  {{ range $k, $v := .Site.Data.modinfo }}
   368  - {{ $k }}: {{ range $kk, $vv := $v }}{{ $kk }}: {{ $vv }}|{{ end -}}
   369  {{ end }}
   370  
   371  
   372  `)
   373  		b.WithSourceFile("go.mod", `
   374  module github.com/gohugoio/tests/testHugoModules
   375  
   376  
   377  `)
   378  
   379  		b.Build(BuildCfg{})
   380  
   381  		// Verify that go.mod is autopopulated with all the modules in config.toml.
   382  		b.AssertFileContent("go.mod", m.Path())
   383  
   384  		b.AssertFileContent("public/index.html",
   385  			"Mod Name: "+m.Name(),
   386  			"Mod Version: v1.4.0")
   387  
   388  		b.AssertFileContent("public/index.html", createChildModMatchers(m, ignoreVendor, m.Vendor)...)
   389  
   390  	}
   391  }
   392  
   393  func createChildModMatchers(m *mods.Md, ignoreVendor, vendored bool) []string {
   394  	// Child dependencies are one behind.
   395  	expectMinorVersion := 3
   396  
   397  	if !ignoreVendor && vendored {
   398  		// Vendored modules are stuck at v1.1.0.
   399  		expectMinorVersion = 1
   400  	}
   401  
   402  	expectVersion := fmt.Sprintf("v1.%d.0", expectMinorVersion)
   403  
   404  	var matchers []string
   405  
   406  	for _, mm := range m.Children {
   407  		matchers = append(
   408  			matchers,
   409  			fmt.Sprintf("%s: name: %s|version: %s", mm.Name(), mm.Name(), expectVersion))
   410  		matchers = append(matchers, createChildModMatchers(mm, ignoreVendor, vendored || mm.Vendor)...)
   411  	}
   412  	return matchers
   413  }
   414  
   415  func TestModulesWithContent(t *testing.T) {
   416  	t.Parallel()
   417  
   418  	b := newTestSitesBuilder(t).WithWorkingDir("/site").WithConfigFile("toml", `
   419  baseURL="https://example.org"
   420  
   421  workingDir="/site"
   422  
   423  defaultContentLanguage = "en"
   424  
   425  [module]
   426  [[module.imports]]
   427  path="a"
   428  [[module.imports.mounts]]
   429  source="myacontent"
   430  target="content/blog"
   431  lang="en"
   432  [[module.imports]]
   433  path="b"
   434  [[module.imports.mounts]]
   435  source="mybcontent"
   436  target="content/blog"
   437  lang="nn"
   438  [[module.imports]]
   439  path="c"
   440  [[module.imports]]
   441  path="d"
   442  
   443  [languages]
   444  
   445  [languages.en]
   446  title = "Title in English"
   447  languageName = "English"
   448  weight = 1
   449  [languages.nn]
   450  languageName = "Nynorsk"
   451  weight = 2
   452  title = "Tittel på nynorsk"
   453  [languages.nb]
   454  languageName = "Bokmål"
   455  weight = 3
   456  title = "Tittel på bokmål"
   457  [languages.fr]
   458  languageName = "French"
   459  weight = 4
   460  title = "French Title"
   461  
   462  
   463  `)
   464  
   465  	b.WithTemplatesAdded("index.html", `
   466  {{ range .Site.RegularPages }}
   467  |{{ .Title }}|{{ .RelPermalink }}|{{ .Plain }}
   468  {{ end }}
   469  {{ $data := .Site.Data }}
   470  Data Common: {{ $data.common.value }}
   471  Data C: {{ $data.c.value }}
   472  Data D: {{ $data.d.value }}
   473  All Data: {{ $data }}
   474  
   475  i18n hello1: {{ i18n "hello1" . }}
   476  i18n theme: {{ i18n "theme" . }}
   477  i18n theme2: {{ i18n "theme2" . }}
   478  `)
   479  
   480  	content := func(id string) string {
   481  		return fmt.Sprintf(`---
   482  title: Title %s
   483  ---
   484  Content %s
   485  
   486  `, id, id)
   487  	}
   488  
   489  	i18nContent := func(id, value string) string {
   490  		return fmt.Sprintf(`
   491  [%s]
   492  other = %q
   493  `, id, value)
   494  	}
   495  
   496  	// Content files
   497  	b.WithSourceFile("themes/a/myacontent/page.md", content("theme-a-en"))
   498  	b.WithSourceFile("themes/b/mybcontent/page.md", content("theme-b-nn"))
   499  	b.WithSourceFile("themes/c/content/blog/c.md", content("theme-c-nn"))
   500  
   501  	// Data files
   502  	b.WithSourceFile("data/common.toml", `value="Project"`)
   503  	b.WithSourceFile("themes/c/data/common.toml", `value="Theme C"`)
   504  	b.WithSourceFile("themes/c/data/c.toml", `value="Hugo Rocks!"`)
   505  	b.WithSourceFile("themes/d/data/c.toml", `value="Hugo Rodcks!"`)
   506  	b.WithSourceFile("themes/d/data/d.toml", `value="Hugo Rodks!"`)
   507  
   508  	// i18n files
   509  	b.WithSourceFile("i18n/en.toml", i18nContent("hello1", "Project"))
   510  	b.WithSourceFile("themes/c/i18n/en.toml", `
   511  [hello1]
   512  other="Theme C Hello"
   513  [theme]
   514  other="Theme C"
   515  `)
   516  	b.WithSourceFile("themes/d/i18n/en.toml", i18nContent("theme", "Theme D"))
   517  	b.WithSourceFile("themes/d/i18n/en.toml", i18nContent("theme2", "Theme2 D"))
   518  
   519  	// Static files
   520  	b.WithSourceFile("themes/c/static/hello.txt", `Hugo Rocks!"`)
   521  
   522  	b.Build(BuildCfg{})
   523  
   524  	b.AssertFileContent("public/index.html", "|Title theme-a-en|/blog/page/|Content theme-a-en")
   525  	b.AssertFileContent("public/nn/index.html", "|Title theme-b-nn|/nn/blog/page/|Content theme-b-nn")
   526  
   527  	// Data
   528  	b.AssertFileContent("public/index.html",
   529  		"Data Common: Project",
   530  		"Data C: Hugo Rocks!",
   531  		"Data D: Hugo Rodks!",
   532  	)
   533  
   534  	// i18n
   535  	b.AssertFileContent("public/index.html",
   536  		"i18n hello1: Project",
   537  		"i18n theme: Theme C",
   538  		"i18n theme2: Theme2 D",
   539  	)
   540  }
   541  
   542  func TestModulesIgnoreConfig(t *testing.T) {
   543  	b := newTestSitesBuilder(t).WithWorkingDir("/site").WithConfigFile("toml", `
   544  baseURL="https://example.org"
   545  
   546  workingDir="/site"
   547  
   548  [module]
   549  [[module.imports]]
   550  path="a"
   551  ignoreConfig=true
   552  
   553  `)
   554  
   555  	b.WithSourceFile("themes/a/config.toml", `
   556  [params]
   557  a = "Should Be Ignored!"
   558  `)
   559  
   560  	b.WithTemplatesAdded("index.html", `Params: {{ .Site.Params }}`)
   561  
   562  	b.Build(BuildCfg{})
   563  
   564  	b.AssertFileContentFn("public/index.html", func(s string) bool {
   565  		return !strings.Contains(s, "Ignored")
   566  	})
   567  }
   568  
   569  func TestModulesDisabled(t *testing.T) {
   570  	b := newTestSitesBuilder(t).WithWorkingDir("/site").WithConfigFile("toml", `
   571  baseURL="https://example.org"
   572  
   573  workingDir="/site"
   574  
   575  [module]
   576  [[module.imports]]
   577  path="a"
   578  [[module.imports]]
   579  path="b"
   580  disable=true
   581  
   582  
   583  `)
   584  
   585  	b.WithSourceFile("themes/a/config.toml", `
   586  [params]
   587  a = "A param"
   588  `)
   589  
   590  	b.WithSourceFile("themes/b/config.toml", `
   591  [params]
   592  b = "B param"
   593  `)
   594  
   595  	b.WithTemplatesAdded("index.html", `Params: {{ .Site.Params }}`)
   596  
   597  	b.Build(BuildCfg{})
   598  
   599  	b.AssertFileContentFn("public/index.html", func(s string) bool {
   600  		return strings.Contains(s, "A param") && !strings.Contains(s, "B param")
   601  	})
   602  }
   603  
   604  func TestModulesIncompatible(t *testing.T) {
   605  	t.Parallel()
   606  
   607  	b := newTestSitesBuilder(t).WithWorkingDir("/site").WithConfigFile("toml", `
   608  baseURL="https://example.org"
   609  
   610  workingDir="/site"
   611  
   612  [module]
   613  [[module.imports]]
   614  path="ok"
   615  [[module.imports]]
   616  path="incompat1"
   617  [[module.imports]]
   618  path="incompat2"
   619  [[module.imports]]
   620  path="incompat3"
   621  
   622  `)
   623  
   624  	b.WithSourceFile("themes/ok/data/ok.toml", `title = "OK"`)
   625  
   626  	b.WithSourceFile("themes/incompat1/config.toml", `
   627  
   628  [module]
   629  [module.hugoVersion]
   630  min = "0.33.2"
   631  max = "0.45.0"
   632  
   633  `)
   634  
   635  	// Old setup.
   636  	b.WithSourceFile("themes/incompat2/theme.toml", `
   637  min_version = "5.0.0"
   638  
   639  `)
   640  
   641  	// Issue 6162
   642  	b.WithSourceFile("themes/incompat3/theme.toml", `
   643  min_version = 0.55.0
   644  
   645  `)
   646  
   647  	logger := loggers.NewDefault()
   648  	b.WithLogger(logger)
   649  
   650  	b.Build(BuildCfg{})
   651  
   652  	c := qt.New(t)
   653  
   654  	c.Assert(logger.LoggCount(logg.LevelWarn), qt.Equals, 3)
   655  }
   656  
   657  func TestMountsProject(t *testing.T) {
   658  	t.Parallel()
   659  
   660  	files := `
   661  -- config.toml --
   662  baseURL="https://example.org"
   663  
   664  [module]
   665  [[module.mounts]]
   666  source="mycontent"
   667  target="content"
   668  -- layouts/_default/single.html --
   669  Permalink: {{ .Permalink }}|
   670  -- mycontent/mypage.md --
   671  ---
   672  title: "My Page"
   673  ---
   674  `
   675  	b := Test(t, files)
   676  
   677  	b.AssertFileContent("public/mypage/index.html", "Permalink: https://example.org/mypage/|")
   678  }
   679  
   680  // https://github.com/gohugoio/hugo/issues/6684
   681  func TestMountsContentFile(t *testing.T) {
   682  	files := `
   683  -- hugo.toml --
   684  disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
   685  disableLiveReload = true
   686  [module]
   687  [[module.mounts]]
   688  source = "README.md"
   689  target = "content/_index.md"
   690  -- README.md --
   691  # Hello World
   692  -- layouts/index.html --
   693  Home: {{ .Title }}|{{ .Content }}|
   694  `
   695  	b := Test(t, files)
   696  	b.AssertFileContent("public/index.html", "Home: |<h1 id=\"hello-world\">Hello World</h1>\n|")
   697  }
   698  
   699  // https://github.com/gohugoio/hugo/issues/6299
   700  func TestSiteWithGoModButNoModules(t *testing.T) {
   701  	t.Parallel()
   702  
   703  	tempDir := t.TempDir()
   704  
   705  	files := `
   706  -- hugo.toml --
   707  baseURL = "https://example.org"
   708  -- go.mod --
   709  
   710  `
   711  
   712  	b := Test(t, files, TestOptWithConfig(func(cfg *IntegrationTestConfig) {
   713  		cfg.WorkingDir = tempDir
   714  	}))
   715  
   716  	b.Build()
   717  }
   718  
   719  // https://github.com/gohugoio/hugo/issues/6622
   720  func TestModuleAbsMount(t *testing.T) {
   721  	t.Parallel()
   722  
   723  	c := qt.New(t)
   724  	// We need to use the OS fs for this.
   725  	workDir, clean1, err := htesting.CreateTempDir(hugofs.Os, "hugo-project")
   726  	c.Assert(err, qt.IsNil)
   727  	absContentDir, clean2, err := htesting.CreateTempDir(hugofs.Os, "hugo-content")
   728  	c.Assert(err, qt.IsNil)
   729  
   730  	cfg := config.New()
   731  	cfg.Set("workingDir", workDir)
   732  	cfg.Set("publishDir", "public")
   733  	fs := hugofs.NewFromOld(hugofs.Os, cfg)
   734  
   735  	config := fmt.Sprintf(`
   736  workingDir=%q
   737  
   738  [module]
   739    [[module.mounts]]
   740      source = %q
   741      target = "content"
   742  
   743  `, workDir, absContentDir)
   744  
   745  	defer clean1()
   746  	defer clean2()
   747  
   748  	b := newTestSitesBuilder(t)
   749  	b.Fs = fs
   750  
   751  	contentFilename := filepath.Join(absContentDir, "p1.md")
   752  	// nolint
   753  	afero.WriteFile(hugofs.Os, contentFilename, []byte(`
   754  ---
   755  title: Abs
   756  ---
   757  
   758  Content.
   759  `), 0o777)
   760  
   761  	b.WithWorkingDir(workDir).WithConfigFile("toml", config)
   762  	b.WithContent("dummy.md", "")
   763  
   764  	b.WithTemplatesAdded("index.html", `
   765  {{ $p1 := site.GetPage "p1" }}
   766  P1: {{ $p1.Title }}|{{ $p1.RelPermalink }}|Filename: {{ $p1.File.Filename }}
   767  `)
   768  
   769  	b.Build(BuildCfg{})
   770  
   771  	b.AssertFileContent("public/index.html", "P1: Abs|/p1/", "Filename: "+contentFilename)
   772  }
   773  
   774  // Issue 9426
   775  func TestMountSameSource(t *testing.T) {
   776  	files := `
   777  -- hugo.toml --
   778  baseURL = 'https://example.org/'
   779  languageCode = 'en-us'
   780  title = 'Hugo GitHub Issue #9426'
   781  
   782  disableKinds = ['RSS','sitemap','taxonomy','term']
   783  
   784  [[module.mounts]]
   785  source = "content"
   786  target = "content"
   787  
   788  [[module.mounts]]
   789  source = "extra-content"
   790  target = "content/resources-a"
   791  
   792  [[module.mounts]]
   793  source = "extra-content"
   794  target = "content/resources-b"
   795  -- layouts/_default/single.html --
   796  Single
   797  -- content/p1.md --
   798  -- extra-content/_index.md --
   799  -- extra-content/subdir/_index.md --
   800  -- extra-content/subdir/about.md --
   801  "
   802  `
   803  	b := Test(t, files)
   804  
   805  	b.AssertFileContent("public/resources-a/subdir/about/index.html", "Single")
   806  	b.AssertFileContent("public/resources-b/subdir/about/index.html", "Single")
   807  }
   808  
   809  func TestMountData(t *testing.T) {
   810  	files := `
   811  -- hugo.toml --
   812  baseURL = 'https://example.org/'
   813  disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
   814  
   815  [[module.mounts]]
   816  source = "data"
   817  target = "data"
   818  
   819  [[module.mounts]]
   820  source = "extra-data"
   821  target = "data/extra"
   822  -- extra-data/test.yaml --
   823  message: Hugo Rocks
   824  -- layouts/index.html --
   825  {{ site.Data.extra.test.message }}
   826  `
   827  
   828  	b := Test(t, files)
   829  
   830  	b.AssertFileContent("public/index.html", "Hugo Rocks")
   831  }