integration_test.go (7472B)
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 js_test
15
16 import (
17 "path/filepath"
18 "strings"
19 "testing"
20
21 qt "github.com/frankban/quicktest"
22 "github.com/gohugoio/hugo/htesting"
23 "github.com/gohugoio/hugo/hugolib"
24 )
25
26 func TestBuildVariants(t *testing.T) {
27 c := qt.New(t)
28
29 mainWithImport := `
30 -- config.toml --
31 disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT"]
32 -- assets/js/main.js --
33 import { hello1, hello2 } from './util1';
34 hello1();
35 hello2();
36 -- assets/js/util1.js --
37 import { hello3 } from './util2';
38 export function hello1() {
39 return 'abcd';
40 }
41 export function hello2() {
42 return hello3();
43 }
44 -- assets/js/util2.js --
45 export function hello3() {
46 return 'efgh';
47 }
48 -- layouts/index.html --
49 {{ $js := resources.Get "js/main.js" | js.Build }}
50 JS Content:{{ $js.Content }}:End:
51
52 `
53
54 c.Run("Basic", func(c *qt.C) {
55 b := hugolib.NewIntegrationTestBuilder(hugolib.IntegrationTestConfig{T: c, NeedsOsFS: true, TxtarString: mainWithImport}).Build()
56
57 b.AssertFileContent("public/index.html", `abcd`)
58 })
59
60 c.Run("Edit Import", func(c *qt.C) {
61 b := hugolib.NewIntegrationTestBuilder(hugolib.IntegrationTestConfig{T: c, Running: true, NeedsOsFS: true, TxtarString: mainWithImport}).Build()
62
63 b.AssertFileContent("public/index.html", `abcd`)
64 b.EditFileReplace("assets/js/util1.js", func(s string) string { return strings.ReplaceAll(s, "abcd", "1234") }).Build()
65 b.AssertFileContent("public/index.html", `1234`)
66 })
67
68 c.Run("Edit Import Nested", func(c *qt.C) {
69 b := hugolib.NewIntegrationTestBuilder(hugolib.IntegrationTestConfig{T: c, Running: true, NeedsOsFS: true, TxtarString: mainWithImport}).Build()
70
71 b.AssertFileContent("public/index.html", `efgh`)
72 b.EditFileReplace("assets/js/util2.js", func(s string) string { return strings.ReplaceAll(s, "efgh", "1234") }).Build()
73 b.AssertFileContent("public/index.html", `1234`)
74 })
75 }
76
77 func TestBuildWithModAndNpm(t *testing.T) {
78 if !htesting.IsCI() {
79 t.Skip("skip (relative) long running modules test when running locally")
80 }
81
82 c := qt.New(t)
83
84 files := `
85 -- config.toml --
86 baseURL = "https://example.org"
87 disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT"]
88 [module]
89 [[module.imports]]
90 path="github.com/gohugoio/hugoTestProjectJSModImports"
91 -- go.mod --
92 module github.com/gohugoio/tests/testHugoModules
93
94 go 1.16
95
96 require github.com/gohugoio/hugoTestProjectJSModImports v0.10.0 // indirect
97 -- package.json --
98 {
99 "dependencies": {
100 "date-fns": "^2.16.1"
101 }
102 }
103
104 `
105 b := hugolib.NewIntegrationTestBuilder(
106 hugolib.IntegrationTestConfig{
107 T: c,
108 NeedsOsFS: true,
109 NeedsNpmInstall: true,
110 TxtarString: files,
111 Verbose: true,
112 }).Build()
113
114 b.AssertFileContent("public/js/main.js", `
115 greeting: "greeting configured in mod2"
116 Hello1 from mod1: $
117 return "Hello2 from mod1";
118 var Hugo = "Rocks!";
119 Hello3 from mod2. Date from date-fns: ${today}
120 Hello from lib in the main project
121 Hello5 from mod2.
122 var myparam = "Hugo Rocks!";
123 shim cwd
124 `)
125
126 // React JSX, verify the shimming.
127 b.AssertFileContent("public/js/like.js", filepath.FromSlash(`@v0.10.0/assets/js/shims/react.js
128 module.exports = window.ReactDOM;
129 `))
130 }
131
132 func TestBuildWithNpm(t *testing.T) {
133 if !htesting.IsCI() {
134 t.Skip("skip (relative) long running modules test when running locally")
135 }
136
137 c := qt.New(t)
138
139 files := `
140 -- assets/js/included.js --
141 console.log("included");
142 -- assets/js/main.js --
143 import "./included";
144 import { toCamelCase } from "to-camel-case";
145
146 console.log("main");
147 console.log("To camel:", toCamelCase("space case"));
148 -- assets/js/myjsx.jsx --
149 import * as React from 'react'
150 import * as ReactDOM from 'react-dom'
151
152 ReactDOM.render(
153 <h1>Hello, world!</h1>,
154 document.getElementById('root')
155 );
156 -- assets/js/myts.ts --
157 function greeter(person: string) {
158 return "Hello, " + person;
159 }
160 let user = [0, 1, 2];
161 document.body.textContent = greeter(user);
162 -- config.toml --
163 disablekinds = ['taxonomy', 'term', 'page']
164 -- content/p1.md --
165 Content.
166 -- data/hugo.toml --
167 slogan = "Hugo Rocks!"
168 -- i18n/en.yaml --
169 hello:
170 other: "Hello"
171 -- i18n/fr.yaml --
172 hello:
173 other: "Bonjour"
174 -- layouts/index.html --
175 {{ $options := dict "minify" false "externals" (slice "react" "react-dom") }}
176 {{ $js := resources.Get "js/main.js" | js.Build $options }}
177 JS: {{ template "print" $js }}
178 {{ $jsx := resources.Get "js/myjsx.jsx" | js.Build $options }}
179 JSX: {{ template "print" $jsx }}
180 {{ $ts := resources.Get "js/myts.ts" | js.Build (dict "sourcemap" "inline")}}
181 TS: {{ template "print" $ts }}
182 {{ $ts2 := resources.Get "js/myts.ts" | js.Build (dict "sourcemap" "external" "TargetPath" "js/myts2.js")}}
183 TS2: {{ template "print" $ts2 }}
184 {{ define "print" }}RelPermalink: {{.RelPermalink}}|MIME: {{ .MediaType }}|Content: {{ .Content | safeJS }}{{ end }}
185 -- package.json --
186 {
187 "scripts": {},
188
189 "dependencies": {
190 "to-camel-case": "1.0.0"
191 }
192 }
193 `
194
195 b := hugolib.NewIntegrationTestBuilder(
196 hugolib.IntegrationTestConfig{
197 T: c,
198 NeedsOsFS: true,
199 NeedsNpmInstall: true,
200 TxtarString: files,
201 }).Build()
202
203 b.AssertFileContent("public/js/myts.js", `//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJz`)
204 b.AssertFileContent("public/js/myts2.js.map", `"version": 3,`)
205 b.AssertFileContent("public/index.html", `
206 console.log("included");
207 if (hasSpace.test(string))
208 var React = __toESM(__require("react"));
209 function greeter(person) {
210 `)
211 }
212
213 func TestBuildError(t *testing.T) {
214 c := qt.New(t)
215
216 filesTemplate := `
217 -- config.toml --
218 disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT"]
219 -- assets/js/main.js --
220 // A comment.
221 import { hello1, hello2 } from './util1';
222 hello1();
223 hello2();
224 -- assets/js/util1.js --
225 /* Some
226 comments.
227 */
228 import { hello3 } from './util2';
229 export function hello1() {
230 return 'abcd';
231 }
232 export function hello2() {
233 return hello3();
234 }
235 -- assets/js/util2.js --
236 export function hello3() {
237 return 'efgh';
238 }
239 -- layouts/index.html --
240 {{ $js := resources.Get "js/main.js" | js.Build }}
241 JS Content:{{ $js.Content }}:End:
242
243 `
244
245 c.Run("Import from main not found", func(c *qt.C) {
246 c.Parallel()
247 files := strings.Replace(filesTemplate, "import { hello1, hello2 }", "import { hello1, hello2, FOOBAR }", 1)
248 b, err := hugolib.NewIntegrationTestBuilder(hugolib.IntegrationTestConfig{T: c, NeedsOsFS: true, TxtarString: files}).BuildE()
249 b.Assert(err, qt.IsNotNil)
250 b.Assert(err.Error(), qt.Contains, `main.js:2:25": No matching export`)
251 })
252
253 c.Run("Import from import not found", func(c *qt.C) {
254 c.Parallel()
255 files := strings.Replace(filesTemplate, "import { hello3 } from './util2';", "import { hello3, FOOBAR } from './util2';", 1)
256 b, err := hugolib.NewIntegrationTestBuilder(hugolib.IntegrationTestConfig{T: c, NeedsOsFS: true, TxtarString: files}).BuildE()
257 b.Assert(err, qt.IsNotNil)
258 b.Assert(err.Error(), qt.Contains, `util1.js:4:17": No matching export in`)
259 })
260
261 }