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 }