github.com/neohugo/neohugo@v0.123.8/resources/resource_transformers/postcss/postcss_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 postcss_test 15 16 import ( 17 "fmt" 18 "path/filepath" 19 "runtime" 20 "strings" 21 "testing" 22 23 "github.com/bep/logg" 24 qt "github.com/frankban/quicktest" 25 "github.com/neohugo/neohugo/htesting" 26 "github.com/neohugo/neohugo/hugofs" 27 "github.com/neohugo/neohugo/hugolib" 28 ) 29 30 const postCSSIntegrationTestFiles = ` 31 -- assets/css/components/a.css -- 32 /* A comment. */ 33 /* Another comment. */ 34 class-in-a { 35 color: blue; 36 } 37 38 -- assets/css/components/all.css -- 39 @import "a.css"; 40 @import "b.css"; 41 -- assets/css/components/b.css -- 42 @import "a.css"; 43 44 class-in-b { 45 color: blue; 46 } 47 48 -- assets/css/styles.css -- 49 @tailwind base; 50 @tailwind components; 51 @tailwind utilities; 52 @import "components/all.css"; 53 h1 { 54 @apply text-2xl font-bold; 55 } 56 57 -- config.toml -- 58 disablekinds = ['taxonomy', 'term', 'page'] 59 baseURL = "https://example.com" 60 [build] 61 useResourceCacheWhen = 'never' 62 -- content/p1.md -- 63 -- data/hugo.toml -- 64 slogan = "Hugo Rocks!" 65 -- i18n/en.yaml -- 66 hello: 67 other: "Hello" 68 -- i18n/fr.yaml -- 69 hello: 70 other: "Bonjour" 71 -- layouts/index.html -- 72 {{ $options := dict "inlineImports" true }} 73 {{ $styles := resources.Get "css/styles.css" | resources.PostCSS $options }} 74 Styles RelPermalink: {{ $styles.RelPermalink }} 75 {{ $cssContent := $styles.Content }} 76 Styles Content: Len: {{ len $styles.Content }}| 77 -- package.json -- 78 { 79 "scripts": {}, 80 81 "devDependencies": { 82 "postcss-cli": "7.1.0", 83 "tailwindcss": "1.2.0" 84 } 85 } 86 -- postcss.config.js -- 87 console.error("Hugo Environment:", process.env.HUGO_ENVIRONMENT ); 88 console.error("Hugo PublishDir:", process.env.HUGO_PUBLISHDIR ); 89 // https://github.com/gohugoio/hugo/issues/7656 90 console.error("package.json:", process.env.HUGO_FILE_PACKAGE_JSON ); 91 console.error("PostCSS Config File:", process.env.HUGO_FILE_POSTCSS_CONFIG_JS ); 92 93 module.exports = { 94 plugins: [ 95 require('tailwindcss') 96 ] 97 } 98 99 ` 100 101 func TestTransformPostCSS(t *testing.T) { 102 if !htesting.IsCI() { 103 t.Skip("Skip long running test when running locally") 104 } 105 106 c := qt.New(t) 107 tempDir, clean, err := htesting.CreateTempDir(hugofs.Os, "hugo-integration-test") 108 c.Assert(err, qt.IsNil) 109 c.Cleanup(clean) 110 111 for _, s := range []string{"never", "always"} { 112 113 repl := strings.NewReplacer( 114 "https://example.com", 115 "https://example.com/foo", 116 "useResourceCacheWhen = 'never'", 117 fmt.Sprintf("useResourceCacheWhen = '%s'", s), 118 ) 119 120 files := repl.Replace(postCSSIntegrationTestFiles) 121 122 b := hugolib.NewIntegrationTestBuilder( 123 hugolib.IntegrationTestConfig{ 124 T: c, 125 NeedsOsFS: true, 126 NeedsNpmInstall: true, 127 LogLevel: logg.LevelInfo, 128 WorkingDir: tempDir, 129 TxtarString: files, 130 }).Build() 131 132 b.AssertFileContent("public/index.html", ` 133 Styles RelPermalink: /foo/css/styles.css 134 Styles Content: Len: 770917| 135 `) 136 137 if s == "never" { 138 b.AssertLogContains("Hugo Environment: production") 139 b.AssertLogContains("Hugo PublishDir: " + filepath.Join(tempDir, "public")) 140 } 141 } 142 } 143 144 // 9880 145 func TestTransformPostCSSError(t *testing.T) { 146 if !htesting.IsCI() { 147 t.Skip("Skip long running test when running locally") 148 } 149 150 if runtime.GOOS == "windows" { 151 // TODO(bep) This has started to fail on Windows with Go 1.19 on GitHub Actions for some mysterious reason. 152 t.Skip("Skip on Windows") 153 } 154 155 c := qt.New(t) 156 157 s, err := hugolib.NewIntegrationTestBuilder( 158 hugolib.IntegrationTestConfig{ 159 T: c, 160 NeedsOsFS: true, 161 NeedsNpmInstall: true, 162 TxtarString: strings.ReplaceAll(postCSSIntegrationTestFiles, "color: blue;", "@apply foo;"), // Syntax error 163 }).BuildE() 164 165 //nolint 166 s.AssertIsFileError(err) 167 c.Assert(err.Error(), qt.Contains, "a.css:4:2") 168 } 169 170 func TestTransformPostCSSNotInstalledError(t *testing.T) { 171 if !htesting.IsCI() { 172 t.Skip("Skip long running test when running locally") 173 } 174 175 c := qt.New(t) 176 177 s, err := hugolib.NewIntegrationTestBuilder( 178 hugolib.IntegrationTestConfig{ 179 T: c, 180 NeedsOsFS: true, 181 TxtarString: postCSSIntegrationTestFiles, 182 }).BuildE() 183 184 s.AssertIsFileError(err) // nolint 185 c.Assert(err.Error(), qt.Contains, `binary with name "npx" not found`) 186 } 187 188 // #9895 189 func TestTransformPostCSSImportError(t *testing.T) { 190 if !htesting.IsCI() { 191 t.Skip("Skip long running test when running locally") 192 } 193 194 c := qt.New(t) 195 196 s, err := hugolib.NewIntegrationTestBuilder( 197 hugolib.IntegrationTestConfig{ 198 T: c, 199 NeedsOsFS: true, 200 NeedsNpmInstall: true, 201 LogLevel: logg.LevelInfo, 202 TxtarString: strings.ReplaceAll(postCSSIntegrationTestFiles, `@import "components/all.css";`, `@import "components/doesnotexist.css";`), 203 }).BuildE() 204 205 //nolint 206 s.AssertIsFileError(err) 207 c.Assert(err.Error(), qt.Contains, "styles.css:4:3") 208 c.Assert(err.Error(), qt.Contains, filepath.FromSlash(`failed to resolve CSS @import "/css/components/doesnotexist.css"`)) 209 } 210 211 func TestTransformPostCSSImporSkipInlineImportsNotFound(t *testing.T) { 212 if !htesting.IsCI() { 213 t.Skip("Skip long running test when running locally") 214 } 215 216 c := qt.New(t) 217 218 files := strings.ReplaceAll(postCSSIntegrationTestFiles, `@import "components/all.css";`, `@import "components/doesnotexist.css";`) 219 files = strings.ReplaceAll(files, `{{ $options := dict "inlineImports" true }}`, `{{ $options := dict "inlineImports" true "skipInlineImportsNotFound" true }}`) 220 221 s := hugolib.NewIntegrationTestBuilder( 222 hugolib.IntegrationTestConfig{ 223 T: c, 224 NeedsOsFS: true, 225 NeedsNpmInstall: true, 226 LogLevel: logg.LevelInfo, 227 TxtarString: files, 228 }).Build() 229 230 s.AssertFileContent("public/css/styles.css", `@import "components/doesnotexist.css";`) 231 } 232 233 // Issue 9787 234 func TestTransformPostCSSResourceCacheWithPathInBaseURL(t *testing.T) { 235 if !htesting.IsCI() { 236 t.Skip("Skip long running test when running locally") 237 } 238 239 c := qt.New(t) 240 tempDir, clean, err := htesting.CreateTempDir(hugofs.Os, "hugo-integration-test") 241 c.Assert(err, qt.IsNil) 242 c.Cleanup(clean) 243 244 for i := 0; i < 2; i++ { 245 files := postCSSIntegrationTestFiles 246 247 if i == 1 { 248 files = strings.ReplaceAll(files, "https://example.com", "https://example.com/foo") 249 files = strings.ReplaceAll(files, "useResourceCacheWhen = 'never'", " useResourceCacheWhen = 'always'") 250 } 251 252 b := hugolib.NewIntegrationTestBuilder( 253 hugolib.IntegrationTestConfig{ 254 T: c, 255 NeedsOsFS: true, 256 NeedsNpmInstall: true, 257 LogLevel: logg.LevelInfo, 258 TxtarString: files, 259 WorkingDir: tempDir, 260 }).Build() 261 262 b.AssertFileContent("public/index.html", ` 263 Styles Content: Len: 770917 264 `) 265 266 } 267 }