github.com/neohugo/neohugo@v0.123.8/resources/resource_transformers/tocss/dartsass/dartsass_integration_test.go (about) 1 // Copyright 2021 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 dartsass_test 15 16 import ( 17 "strings" 18 "testing" 19 20 "github.com/bep/logg" 21 qt "github.com/frankban/quicktest" 22 "github.com/neohugo/neohugo/htesting" 23 "github.com/neohugo/neohugo/hugolib" 24 "github.com/neohugo/neohugo/resources/resource_transformers/tocss/dartsass" 25 ) 26 27 func TestTransformIncludePaths(t *testing.T) { 28 t.Parallel() 29 if !dartsass.Supports() { 30 t.Skip() 31 } 32 33 files := ` 34 -- assets/scss/main.scss -- 35 @import "moo"; 36 -- node_modules/foo/_moo.scss -- 37 $moolor: #fff; 38 39 moo { 40 color: $moolor; 41 } 42 -- config.toml -- 43 -- layouts/index.html -- 44 {{ $cssOpts := (dict "includePaths" (slice "node_modules/foo") "transpiler" "dartsass" ) }} 45 {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }} 46 T1: {{ $r.Content }} 47 ` 48 49 b := hugolib.NewIntegrationTestBuilder( 50 hugolib.IntegrationTestConfig{ 51 T: t, 52 TxtarString: files, 53 NeedsOsFS: true, 54 }).Build() 55 56 b.AssertFileContent("public/index.html", `T1: moo{color:#fff}`) 57 } 58 59 func TestTransformImportRegularCSS(t *testing.T) { 60 t.Parallel() 61 if !dartsass.Supports() { 62 t.Skip() 63 } 64 65 files := ` 66 -- assets/scss/_moo.scss -- 67 $moolor: #fff; 68 69 moo { 70 color: $moolor; 71 } 72 -- assets/scss/another.css -- 73 74 -- assets/scss/main.scss -- 75 @import "moo"; 76 @import "regular.css"; 77 @import "moo"; 78 @import "another.css"; 79 80 /* foo */ 81 -- assets/scss/regular.css -- 82 83 -- config.toml -- 84 -- layouts/index.html -- 85 {{ $r := resources.Get "scss/main.scss" | toCSS (dict "transpiler" "dartsass") }} 86 T1: {{ $r.Content | safeHTML }} 87 88 ` 89 90 b := hugolib.NewIntegrationTestBuilder( 91 hugolib.IntegrationTestConfig{ 92 T: t, 93 TxtarString: files, 94 NeedsOsFS: true, 95 }, 96 ).Build() 97 98 // Dart Sass does not follow regular CSS import, but they 99 // get pulled to the top. 100 b.AssertFileContent("public/index.html", `T1: @import "regular.css"; 101 @import "another.css"; 102 moo { 103 color: #fff; 104 } 105 106 moo { 107 color: #fff; 108 } 109 110 /* foo */`) 111 } 112 113 func TestTransformImportIndentedSASS(t *testing.T) { 114 t.Parallel() 115 if !dartsass.Supports() { 116 t.Skip() 117 } 118 119 files := ` 120 -- assets/scss/_moo.sass -- 121 #main 122 color: blue 123 -- assets/scss/main.scss -- 124 @import "moo"; 125 126 /* foo */ 127 -- config.toml -- 128 -- layouts/index.html -- 129 {{ $r := resources.Get "scss/main.scss" | toCSS (dict "transpiler" "dartsass") }} 130 T1: {{ $r.Content | safeHTML }} 131 132 ` 133 134 b := hugolib.NewIntegrationTestBuilder( 135 hugolib.IntegrationTestConfig{ 136 T: t, 137 TxtarString: files, 138 NeedsOsFS: true, 139 }, 140 ).Build() 141 142 b.AssertFileContent("public/index.html", "T1: #main {\n color: blue;\n}\n\n/* foo */") 143 } 144 145 // Issue 10592 146 func TestTransformImportMountedCSS(t *testing.T) { 147 t.Parallel() 148 if !dartsass.Supports() { 149 t.Skip() 150 } 151 152 files := ` 153 -- assets/main.scss -- 154 @import "import-this-file.css"; 155 @import "foo/import-this-mounted-file.css"; 156 @import "compile-this-file"; 157 @import "foo/compile-this-mounted-file"; 158 a {color: main-scss;} 159 -- assets/_compile-this-file.css -- 160 a {color: compile-this-file-css;} 161 -- assets/_import-this-file.css -- 162 a {color: import-this-file-css;} 163 -- foo/_compile-this-mounted-file.css -- 164 a {color: compile-this-mounted-file-css;} 165 -- foo/_import-this-mounted-file.css -- 166 a {color: import-this-mounted-file-css;} 167 -- layouts/index.html -- 168 {{- $opts := dict "transpiler" "dartsass" }} 169 {{- with resources.Get "main.scss" | toCSS $opts }}{{ .Content | safeHTML }}{{ end }} 170 -- config.toml -- 171 disableKinds = ['RSS','sitemap','taxonomy','term','page','section'] 172 173 [[module.mounts]] 174 source = 'assets' 175 target = 'assets' 176 177 [[module.mounts]] 178 source = 'foo' 179 target = 'assets/foo' 180 ` 181 b := hugolib.NewIntegrationTestBuilder( 182 hugolib.IntegrationTestConfig{ 183 T: t, 184 TxtarString: files, 185 NeedsOsFS: true, 186 }, 187 ).Build() 188 189 b.AssertFileContent("public/index.html", ` 190 @import "import-this-file.css"; 191 @import "foo/import-this-mounted-file.css"; 192 a { 193 color: compile-this-file-css; 194 } 195 196 a { 197 color: compile-this-mounted-file-css; 198 } 199 200 a { 201 color: main-scss; 202 } 203 `) 204 } 205 206 func TestTransformThemeOverrides(t *testing.T) { 207 t.Parallel() 208 if !dartsass.Supports() { 209 t.Skip() 210 } 211 212 files := ` 213 -- assets/scss/components/_boo.scss -- 214 $boolor: green; 215 216 boo { 217 color: $boolor; 218 } 219 -- assets/scss/components/_moo.scss -- 220 $moolor: #ccc; 221 222 moo { 223 color: $moolor; 224 } 225 -- config.toml -- 226 theme = 'mytheme' 227 -- layouts/index.html -- 228 {{ $cssOpts := (dict "includePaths" (slice "node_modules/foo" ) "transpiler" "dartsass" ) }} 229 {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }} 230 T1: {{ $r.Content }} 231 -- themes/mytheme/assets/scss/components/_boo.scss -- 232 $boolor: orange; 233 234 boo { 235 color: $boolor; 236 } 237 -- themes/mytheme/assets/scss/components/_imports.scss -- 238 @import "moo"; 239 @import "_boo"; 240 @import "_zoo"; 241 -- themes/mytheme/assets/scss/components/_moo.scss -- 242 $moolor: #fff; 243 244 moo { 245 color: $moolor; 246 } 247 -- themes/mytheme/assets/scss/components/_zoo.scss -- 248 $zoolor: pink; 249 250 zoo { 251 color: $zoolor; 252 } 253 -- themes/mytheme/assets/scss/main.scss -- 254 @import "components/imports"; 255 ` 256 257 b := hugolib.NewIntegrationTestBuilder( 258 hugolib.IntegrationTestConfig{ 259 T: t, 260 TxtarString: files, 261 NeedsOsFS: true, 262 }, 263 ).Build() 264 265 b.AssertFileContent("public/index.html", `T1: moo{color:#ccc}boo{color:green}zoo{color:pink}`) 266 } 267 268 func TestTransformLogging(t *testing.T) { 269 t.Parallel() 270 if !dartsass.Supports() { 271 t.Skip() 272 } 273 274 files := ` 275 -- assets/scss/main.scss -- 276 @warn "foo"; 277 @debug "bar"; 278 279 -- config.toml -- 280 disableKinds = ["term", "taxonomy", "section", "page"] 281 -- layouts/index.html -- 282 {{ $cssOpts := (dict "transpiler" "dartsass" ) }} 283 {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts }} 284 T1: {{ $r.Content }} 285 ` 286 287 b := hugolib.NewIntegrationTestBuilder( 288 hugolib.IntegrationTestConfig{ 289 T: t, 290 TxtarString: files, 291 NeedsOsFS: true, 292 LogLevel: logg.LevelInfo, 293 }).Build() 294 295 b.AssertLogMatches(`Dart Sass: foo`) 296 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:1:0: bar`) 297 } 298 299 func TestTransformErrors(t *testing.T) { 300 if !dartsass.Supports() { 301 t.Skip() 302 } 303 304 c := qt.New(t) 305 306 const filesTemplate = ` 307 -- config.toml -- 308 -- assets/scss/components/_foo.scss -- 309 /* comment line 1 */ 310 $foocolor: #ccc; 311 312 foo { 313 color: $foocolor; 314 } 315 -- assets/scss/main.scss -- 316 /* comment line 1 */ 317 /* comment line 2 */ 318 @import "components/foo"; 319 /* comment line 4 */ 320 321 $maincolor: #eee; 322 323 body { 324 color: $maincolor; 325 } 326 327 -- layouts/index.html -- 328 {{ $cssOpts := dict "transpiler" "dartsass" }} 329 {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts | minify }} 330 T1: {{ $r.Content }} 331 332 ` 333 334 c.Run("error in main", func(c *qt.C) { 335 b, err := hugolib.NewIntegrationTestBuilder( 336 hugolib.IntegrationTestConfig{ 337 T: c, 338 TxtarString: strings.Replace(filesTemplate, "$maincolor: #eee;", "$maincolor #eee;", 1), 339 NeedsOsFS: true, 340 }).BuildE() 341 342 b.Assert(err, qt.IsNotNil) 343 b.Assert(err.Error(), qt.Contains, `main.scss:8:13":`) 344 b.Assert(err.Error(), qt.Contains, `: expected ":".`) 345 fe := b.AssertIsFileError(err) 346 b.Assert(fe.ErrorContext(), qt.IsNotNil) 347 b.Assert(fe.ErrorContext().Lines, qt.DeepEquals, []string{" $maincolor #eee;", "", "body {", "\tcolor: $maincolor;", "}"}) 348 b.Assert(fe.ErrorContext().ChromaLexer, qt.Equals, "scss") 349 }) 350 351 c.Run("error in import", func(c *qt.C) { 352 b, err := hugolib.NewIntegrationTestBuilder( 353 hugolib.IntegrationTestConfig{ 354 T: c, 355 TxtarString: strings.Replace(filesTemplate, "$foocolor: #ccc;", "$foocolor #ccc;", 1), 356 NeedsOsFS: true, 357 }).BuildE() 358 359 b.Assert(err, qt.IsNotNil) 360 b.Assert(err.Error(), qt.Contains, `_foo.scss:2:10":`) 361 b.Assert(err.Error(), qt.Contains, `: expected ":".`) 362 fe := b.AssertIsFileError(err) 363 b.Assert(fe.ErrorContext(), qt.IsNotNil) 364 b.Assert(fe.ErrorContext().Lines, qt.DeepEquals, []string{"/* comment line 1 */", "$foocolor #ccc;", "", "foo {"}) 365 b.Assert(fe.ErrorContext().ChromaLexer, qt.Equals, "scss") 366 }) 367 } 368 369 func TestOptionVars(t *testing.T) { 370 t.Parallel() 371 if !dartsass.Supports() { 372 t.Skip() 373 } 374 375 files := ` 376 -- assets/scss/main.scss -- 377 @use "hugo:vars"; 378 379 body { 380 body { 381 background: url(vars.$image) no-repeat center/cover; 382 font-family: vars.$font; 383 } 384 } 385 386 p { 387 color: vars.$color1; 388 font-size: vars.$font_size; 389 } 390 391 b { 392 color: vars.$color2; 393 } 394 -- layouts/index.html -- 395 {{ $image := "images/hero.jpg" }} 396 {{ $font := "Hugo's New Roman" }} 397 {{ $vars := dict "$color1" "blue" "$color2" "green" "font_size" "24px" "image" $image "font" $font }} 398 {{ $cssOpts := (dict "transpiler" "dartsass" "outputStyle" "compressed" "vars" $vars ) }} 399 {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts }} 400 T1: {{ $r.Content }} 401 ` 402 403 b := hugolib.NewIntegrationTestBuilder( 404 hugolib.IntegrationTestConfig{ 405 T: t, 406 TxtarString: files, 407 NeedsOsFS: true, 408 }).Build() 409 410 b.AssertFileContent("public/index.html", `T1: body body{background:url(images/hero.jpg) no-repeat center/cover;font-family:Hugo's New Roman}p{color:blue;font-size:24px}b{color:green}`) 411 } 412 413 func TestOptionVarsParams(t *testing.T) { 414 t.Parallel() 415 if !dartsass.Supports() { 416 t.Skip() 417 } 418 419 files := ` 420 -- config.toml -- 421 [params] 422 [params.sassvars] 423 color1 = "blue" 424 color2 = "green" 425 font_size = "24px" 426 image = "images/hero.jpg" 427 -- assets/scss/main.scss -- 428 @use "hugo:vars"; 429 430 body { 431 body { 432 background: url(vars.$image) no-repeat center/cover; 433 } 434 } 435 436 p { 437 color: vars.$color1; 438 font-size: vars.$font_size; 439 } 440 441 b { 442 color: vars.$color2; 443 } 444 -- layouts/index.html -- 445 {{ $vars := site.Params.sassvars}} 446 {{ $cssOpts := (dict "transpiler" "dartsass" "outputStyle" "compressed" "vars" $vars ) }} 447 {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts }} 448 T1: {{ $r.Content }} 449 ` 450 451 b := hugolib.NewIntegrationTestBuilder( 452 hugolib.IntegrationTestConfig{ 453 T: t, 454 TxtarString: files, 455 NeedsOsFS: true, 456 }).Build() 457 458 b.AssertFileContent("public/index.html", `T1: body body{background:url(images/hero.jpg) no-repeat center/cover}p{color:blue;font-size:24px}b{color:green}`) 459 } 460 461 func TestVarsCasting(t *testing.T) { 462 t.Parallel() 463 if !dartsass.Supports() { 464 t.Skip() 465 } 466 467 files := ` 468 -- config.toml -- 469 disableKinds = ["term", "taxonomy", "section", "page"] 470 471 [params] 472 [params.sassvars] 473 color_hex = "#fff" 474 color_rgb = "rgb(255, 255, 255)" 475 color_hsl = "hsl(0, 0%, 100%)" 476 dimension = "24px" 477 percentage = "10%" 478 flex = "5fr" 479 name = "Hugo" 480 url = "https://gohugo.io" 481 integer = 32 482 float = 3.14 483 -- assets/scss/main.scss -- 484 @use "hugo:vars"; 485 @use "sass:meta"; 486 487 @debug meta.type-of(vars.$color_hex); 488 @debug meta.type-of(vars.$color_rgb); 489 @debug meta.type-of(vars.$color_hsl); 490 @debug meta.type-of(vars.$dimension); 491 @debug meta.type-of(vars.$percentage); 492 @debug meta.type-of(vars.$flex); 493 @debug meta.type-of(vars.$name); 494 @debug meta.type-of(vars.$url); 495 @debug meta.type-of(vars.$not_a_number); 496 @debug meta.type-of(vars.$integer); 497 @debug meta.type-of(vars.$float); 498 @debug meta.type-of(vars.$a_number); 499 -- layouts/index.html -- 500 {{ $vars := site.Params.sassvars}} 501 {{ $vars = merge $vars (dict "not_a_number" ("32xxx" | css.Quoted) "a_number" ("234" | css.Unquoted) )}} 502 {{ $cssOpts := (dict "transpiler" "dartsass" "vars" $vars ) }} 503 {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts }} 504 T1: {{ $r.Content }} 505 ` 506 507 b := hugolib.NewIntegrationTestBuilder( 508 hugolib.IntegrationTestConfig{ 509 T: t, 510 TxtarString: files, 511 NeedsOsFS: true, 512 LogLevel: logg.LevelInfo, 513 }).Build() 514 515 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:3:0: color`) 516 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:4:0: color`) 517 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:5:0: color`) 518 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:6:0: number`) 519 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:7:0: number`) 520 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:8:0: number`) 521 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:9:0: string`) 522 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:10:0: string`) 523 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:11:0: string`) 524 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:12:0: number`) 525 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:13:0: number`) 526 b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:14:0: number`) 527 } 528 529 // Note: This test is more or less duplicated in both of the SCSS packages (libsass and dartsass). 530 func TestBootstrap(t *testing.T) { 531 t.Parallel() 532 if !dartsass.Supports() { 533 t.Skip() 534 } 535 if !htesting.IsCI() { 536 t.Skip("skip (slow) test in non-CI environment") 537 } 538 539 files := ` 540 -- hugo.toml -- 541 disableKinds = ["term", "taxonomy", "section", "page"] 542 [module] 543 [[module.imports]] 544 path="github.com/gohugoio/hugo-mod-bootstrap-scss/v5" 545 -- go.mod -- 546 module github.com/gohugoio/tests/testHugoModules 547 -- assets/scss/main.scss -- 548 @import "bootstrap/bootstrap"; 549 -- layouts/index.html -- 550 {{ $cssOpts := (dict "transpiler" "dartsass" ) }} 551 {{ $r := resources.Get "scss/main.scss" | toCSS $cssOpts }} 552 Styles: {{ $r.RelPermalink }} 553 ` 554 555 b := hugolib.NewIntegrationTestBuilder( 556 hugolib.IntegrationTestConfig{ 557 T: t, 558 TxtarString: files, 559 NeedsOsFS: true, 560 }).Build() 561 562 b.AssertFileContent("public/index.html", "Styles: /scss/main.css") 563 }