github.com/neohugo/neohugo@v0.123.8/tpl/partials/partials_integration_test.go (about)

     1  // Copyright 2024 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 partials_test
    15  
    16  import (
    17  	"bytes"
    18  	"fmt"
    19  	"regexp"
    20  	"sort"
    21  	"strings"
    22  	"testing"
    23  
    24  	qt "github.com/frankban/quicktest"
    25  
    26  	"github.com/neohugo/neohugo/htesting/hqt"
    27  	"github.com/neohugo/neohugo/hugolib"
    28  )
    29  
    30  func TestInclude(t *testing.T) {
    31  	t.Parallel()
    32  
    33  	files := `
    34  -- config.toml --
    35  baseURL = 'http://example.com/'
    36  -- layouts/index.html --
    37  partial: {{ partials.Include "foo.html" . }}
    38  -- layouts/partials/foo.html --
    39  foo
    40    `
    41  
    42  	b := hugolib.Test(t, files)
    43  
    44  	b.AssertFileContent("public/index.html", `
    45  partial: foo
    46  `)
    47  }
    48  
    49  func TestIncludeCached(t *testing.T) {
    50  	t.Parallel()
    51  
    52  	files := `
    53  -- config.toml --
    54  baseURL = 'http://example.com/'
    55  -- layouts/index.html --
    56  partialCached: {{ partials.IncludeCached "foo.html" . }}
    57  partialCached: {{ partials.IncludeCached "foo.html" . }}
    58  -- layouts/partials/foo.html --
    59  foo
    60    `
    61  
    62  	b := hugolib.Test(t, files)
    63  
    64  	b.AssertFileContent("public/index.html", `
    65  partialCached: foo
    66  partialCached: foo
    67  `)
    68  }
    69  
    70  // Issue 9519
    71  func TestIncludeCachedRecursion(t *testing.T) {
    72  	t.Parallel()
    73  
    74  	files := `
    75  -- config.toml --
    76  baseURL = 'http://example.com/'
    77  -- layouts/index.html --
    78  {{ partials.IncludeCached "p1.html" . }}
    79  -- layouts/partials/p1.html --
    80  {{ partials.IncludeCached "p2.html" . }}
    81  -- layouts/partials/p2.html --
    82  P2
    83  
    84    `
    85  
    86  	b := hugolib.Test(t, files)
    87  
    88  	b.AssertFileContent("public/index.html", `
    89  P2
    90  `)
    91  }
    92  
    93  // Issue #588
    94  func TestIncludeCachedRecursionShortcode(t *testing.T) {
    95  	t.Parallel()
    96  
    97  	files := `
    98  -- config.toml --
    99  baseURL = 'http://example.com/'
   100  -- content/_index.md --
   101  ---
   102  title: "Index"
   103  ---
   104  {{< short >}}
   105  -- layouts/index.html --
   106  {{ partials.IncludeCached "p1.html" . }}
   107  -- layouts/partials/p1.html --
   108  {{ .Content }}
   109  {{ partials.IncludeCached "p2.html" . }}
   110  -- layouts/partials/p2.html --
   111  -- layouts/shortcodes/short.html --
   112  SHORT
   113  {{ partials.IncludeCached "p2.html" . }}
   114  P2
   115  
   116    `
   117  
   118  	b := hugolib.Test(t, files)
   119  
   120  	b.AssertFileContent("public/index.html", `
   121  SHORT
   122  P2
   123  `)
   124  }
   125  
   126  func TestIncludeCacheHints(t *testing.T) {
   127  	t.Parallel()
   128  
   129  	files := `
   130  -- config.toml --
   131  baseURL = 'http://example.com/'
   132  templateMetrics=true
   133  templateMetricsHints=true
   134  disableKinds = ["page", "section", "taxonomy", "term", "sitemap"]
   135  [outputs]
   136  home = ["HTML"]
   137  -- layouts/index.html --
   138  {{ partials.IncludeCached "static1.html" . }}
   139  {{ partials.IncludeCached "static1.html" . }}
   140  {{ partials.Include "static2.html" . }}
   141  
   142  D1I: {{ partials.Include "dynamic1.html" . }}
   143  D1C: {{ partials.IncludeCached "dynamic1.html" . }}
   144  D1C: {{ partials.IncludeCached "dynamic1.html" . }}
   145  D1C: {{ partials.IncludeCached "dynamic1.html" . }}
   146  H1I: {{ partials.Include "halfdynamic1.html" . }}
   147  H1C: {{ partials.IncludeCached "halfdynamic1.html" . }}
   148  H1C: {{ partials.IncludeCached "halfdynamic1.html" . }}
   149  
   150  -- layouts/partials/static1.html --
   151  P1
   152  -- layouts/partials/static2.html --
   153  P2
   154  -- layouts/partials/dynamic1.html --
   155  {{ math.Counter }}
   156  -- layouts/partials/halfdynamic1.html --
   157  D1
   158  {{ math.Counter }}
   159  
   160  
   161    `
   162  
   163  	b := hugolib.Test(t, files)
   164  
   165  	// fmt.Println(b.FileContent("public/index.html"))
   166  
   167  	var buf bytes.Buffer
   168  	b.H.Metrics.WriteMetrics(&buf)
   169  
   170  	got := buf.String()
   171  
   172  	// Get rid of all the durations, they are never the same.
   173  	durationRe := regexp.MustCompile(`\b[\.\d]*(ms|µs|s)\b`)
   174  
   175  	normalize := func(s string) string {
   176  		s = durationRe.ReplaceAllString(s, "")
   177  		linesIn := strings.Split(s, "\n")[3:]
   178  		var lines []string
   179  		for _, l := range linesIn {
   180  			l = strings.TrimSpace(l)
   181  			if l == "" {
   182  				continue
   183  			}
   184  			lines = append(lines, l)
   185  		}
   186  
   187  		sort.Strings(lines)
   188  
   189  		return strings.Join(lines, "\n")
   190  	}
   191  
   192  	got = normalize(got)
   193  
   194  	expect := `
   195  	0        0       0      1  index.html
   196  	100        0       0      1  partials/static2.html
   197  	100       50       1      2  partials/static1.html
   198  	25       50       2      4  partials/dynamic1.html
   199  	66       33       1      3  partials/halfdynamic1.html
   200  	`
   201  
   202  	b.Assert(got, hqt.IsSameString, expect)
   203  }
   204  
   205  // gobench --package ./tpl/partials
   206  func BenchmarkIncludeCached(b *testing.B) {
   207  	files := `
   208  -- config.toml --
   209  baseURL = 'http://example.com/'
   210  -- layouts/index.html --
   211  -- layouts/_default/single.html --
   212  {{ partialCached "heavy.html" "foo" }}
   213  {{ partialCached "easy1.html" "bar" }}
   214  {{ partialCached "easy1.html" "baz" }}
   215  {{ partialCached "easy2.html" "baz" }}
   216  -- layouts/partials/easy1.html --
   217  ABCD
   218  -- layouts/partials/easy2.html --
   219  ABCDE
   220  -- layouts/partials/heavy.html --
   221  {{ $result := slice }}
   222  {{ range site.RegularPages }}
   223  {{ $result = $result | append (dict "title" .Title "link" .RelPermalink "readingTime" .ReadingTime) }}
   224  {{ end }}
   225  {{ range $result }}
   226  * {{ .title }} {{ .link }} {{ .readingTime }}
   227  {{ end }}
   228  
   229  
   230  `
   231  
   232  	for i := 1; i < 100; i++ {
   233  		files += fmt.Sprintf("\n-- content/p%d.md --\n---\ntitle: page\n---\n"+strings.Repeat("FOO ", i), i)
   234  	}
   235  
   236  	cfg := hugolib.IntegrationTestConfig{
   237  		T:           b,
   238  		TxtarString: files,
   239  	}
   240  	builders := make([]*hugolib.IntegrationTestBuilder, b.N)
   241  
   242  	for i := range builders {
   243  		builders[i] = hugolib.NewIntegrationTestBuilder(cfg)
   244  	}
   245  
   246  	b.ResetTimer()
   247  
   248  	for i := 0; i < b.N; i++ {
   249  		builders[i].Build()
   250  	}
   251  }
   252  
   253  func TestIncludeTimeout(t *testing.T) {
   254  	t.Parallel()
   255  
   256  	files := `
   257  -- config.toml --
   258  baseURL = 'http://example.com/'
   259  timeout = '200ms'
   260  -- layouts/index.html --
   261  {{ partials.Include "foo.html" . }}
   262  -- layouts/partials/foo.html --
   263  {{ partial "foo.html" . }}
   264    `
   265  
   266  	b, err := hugolib.NewIntegrationTestBuilder(
   267  		hugolib.IntegrationTestConfig{
   268  			T:           t,
   269  			TxtarString: files,
   270  		},
   271  	).BuildE()
   272  
   273  	b.Assert(err, qt.Not(qt.IsNil))
   274  	b.Assert(err.Error(), qt.Contains, "timed out")
   275  }
   276  
   277  func TestIncludeCachedTimeout(t *testing.T) {
   278  	t.Parallel()
   279  
   280  	files := `
   281  -- config.toml --
   282  baseURL = 'http://example.com/'
   283  timeout = '200ms'
   284  -- layouts/index.html --
   285  {{ partials.IncludeCached "foo.html" . }}
   286  -- layouts/partials/foo.html --
   287  {{ partialCached "foo.html" . }}
   288    `
   289  
   290  	b, err := hugolib.NewIntegrationTestBuilder(
   291  		hugolib.IntegrationTestConfig{
   292  			T:           t,
   293  			TxtarString: files,
   294  		},
   295  	).BuildE()
   296  
   297  	b.Assert(err, qt.Not(qt.IsNil))
   298  	b.Assert(err.Error(), qt.Contains, "timed out")
   299  }
   300  
   301  // See Issue #10789
   302  func TestReturnExecuteFromTemplateInPartial(t *testing.T) {
   303  	t.Parallel()
   304  
   305  	files := `
   306  -- config.toml --
   307  baseURL = 'http://example.com/'
   308  -- layouts/index.html --
   309  {{ $r :=  partial "foo" }}
   310  FOO:{{ $r.Content }}
   311  -- layouts/partials/foo.html --
   312  {{ $r := §§{{ partial "bar" }}§§ | resources.FromString "bar.html" | resources.ExecuteAsTemplate "bar.html" . }}
   313  {{ return $r }}
   314  -- layouts/partials/bar.html --
   315  BAR
   316    `
   317  
   318  	b := hugolib.Test(t, files)
   319  
   320  	b.AssertFileContent("public/index.html", "OO:BAR")
   321  }