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 }