UNPKG

14.4 kBJavaScriptView Raw
1"use strict";
2
3var resolve = require('resolve');
4var path = require('path');
5
6var testFolder = path.relative(process.cwd(), path.dirname(resolve.sync('@less/test-data')));
7var lessFolder = path.join(testFolder, 'less');
8
9module.exports = function(grunt) {
10 grunt.option("stack", true);
11
12 // Report the elapsed execution time of tasks.
13 require("time-grunt")(grunt);
14
15 var COMPRESS_FOR_TESTS = false;
16 var git = require("git-rev");
17
18 // Sauce Labs browser
19 var browsers = [
20 // Desktop browsers
21 {
22 browserName: "chrome",
23 version: "latest",
24 platform: "Windows 7"
25 },
26 {
27 browserName: "firefox",
28 version: "latest",
29 platform: "Linux"
30 },
31 {
32 browserName: "safari",
33 version: "9",
34 platform: "OS X 10.11"
35 },
36 {
37 browserName: "internet explorer",
38 version: "8",
39 platform: "Windows XP"
40 },
41 {
42 browserName: "internet explorer",
43 version: "11",
44 platform: "Windows 8.1"
45 },
46 {
47 browserName: "edge",
48 version: "13",
49 platform: "Windows 10"
50 },
51 // Mobile browsers
52 {
53 browserName: "ipad",
54 deviceName: "iPad Air Simulator",
55 deviceOrientation: "portrait",
56 version: "8.4",
57 platform: "OS X 10.9"
58 },
59 {
60 browserName: "iphone",
61 deviceName: "iPhone 5 Simulator",
62 deviceOrientation: "portrait",
63 version: "9.3",
64 platform: "OS X 10.11"
65 },
66 {
67 browserName: "android",
68 deviceName: "Google Nexus 7 HD Emulator",
69 deviceOrientation: "portrait",
70 version: "4.4",
71 platform: "Linux"
72 }
73 ];
74
75 var sauceJobs = {};
76
77 var browserTests = [
78 "filemanager-plugin",
79 "visitor-plugin",
80 "global-vars",
81 "modify-vars",
82 "production",
83 "rootpath-relative",
84 "rootpath-rewrite-urls",
85 "rootpath",
86 "relative-urls",
87 "rewrite-urls",
88 "browser",
89 "no-js-errors",
90 "legacy"
91 ];
92
93 function makeJob(testName) {
94 sauceJobs[testName] = {
95 options: {
96 urls:
97 testName === "all"
98 ? browserTests.map(function(name) {
99 return (
100 "http://localhost:8081/tmp/browser/test-runner-" +
101 name +
102 ".html"
103 );
104 })
105 : [
106 "http://localhost:8081/tmp/browser/test-runner-" +
107 testName +
108 ".html"
109 ],
110 testname:
111 testName === "all" ? "Unit Tests for Less.js" : testName,
112 browsers: browsers,
113 public: "public",
114 recordVideo: false,
115 videoUploadOnPass: false,
116 recordScreenshots: process.env.TRAVIS_BRANCH !== "master",
117 build:
118 process.env.TRAVIS_BRANCH === "master"
119 ? process.env.TRAVIS_JOB_ID
120 : undefined,
121 tags: [
122 process.env.TRAVIS_BUILD_NUMBER,
123 process.env.TRAVIS_PULL_REQUEST,
124 process.env.TRAVIS_BRANCH
125 ],
126 statusCheckAttempts: -1,
127 sauceConfig: {
128 "idle-timeout": 100
129 },
130 throttled: 5,
131 onTestComplete: function(result, callback) {
132 // Called after a unit test is done, per page, per browser
133 // 'result' param is the object returned by the test framework's reporter
134 // 'callback' is a Node.js style callback function. You must invoke it after you
135 // finish your work.
136 // Pass a non-null value as the callback's first parameter if you want to throw an
137 // exception. If your function is synchronous you can also throw exceptions
138 // directly.
139 // Passing true or false as the callback's second parameter passes or fails the
140 // test. Passing undefined does not alter the test result. Please note that this
141 // only affects the grunt task's result. You have to explicitly update the Sauce
142 // Labs job's status via its REST API, if you want so.
143
144 // This should be the encrypted value in Travis
145 var user = process.env.SAUCE_USERNAME;
146 var pass = process.env.SAUCE_ACCESS_KEY;
147
148 git.short(function(hash) {
149 require("phin")(
150 {
151 method: "PUT",
152 url: [
153 "https://saucelabs.com/rest/v1",
154 user,
155 "jobs",
156 result.job_id
157 ].join("/"),
158 auth: { user: user, pass: pass },
159 data: {
160 passed: result.passed,
161 build: "build-" + hash
162 }
163 },
164 function(error, response) {
165 if (error) {
166 console.log(error);
167 callback(error);
168 } else if (response.statusCode !== 200) {
169 console.log(response);
170 callback(
171 new Error("Unexpected response status")
172 );
173 } else {
174 callback(null, result.passed);
175 }
176 }
177 );
178 });
179 }
180 }
181 };
182 }
183
184 // Make the SauceLabs jobs
185 ["all"].concat(browserTests).map(makeJob);
186
187 var semver = require('semver');
188 var path = require('path');
189
190 // Handle async / await in Rollup build for tests
191 // Remove this when Node 6 is no longer supported for the build/test process
192 const nodeVersion = semver.major(process.versions.node);
193 const tsNodeRuntime = path.resolve(path.join('node_modules', '.bin', 'ts-node'));
194 let scriptRuntime = 'node';
195 if (nodeVersion < 8) {
196 scriptRuntime = tsNodeRuntime;
197 }
198
199 // Project configuration.
200 grunt.initConfig({
201 shell: {
202 options: {
203 stdout: true,
204 failOnError: true,
205 execOptions: {
206 maxBuffer: Infinity
207 }
208 },
209 build: {
210 command: [
211 /** Browser runtime */
212 scriptRuntime + " build/rollup.js --dist",
213 /** Copy to repo root */
214 "npm run copy:root",
215 /** Node.js runtime */
216 "npm run build"
217 ].join(" && ")
218 },
219 testbuild: {
220 command: [
221 "npm run build",
222 scriptRuntime + " build/rollup.js --browser --out=./tmp/browser/less.min.js"
223 ].join(" && ")
224 },
225 testcjs: {
226 command: "npm run build"
227 },
228 testbrowser: {
229 command: scriptRuntime + " build/rollup.js --browser --out=./tmp/browser/less.min.js"
230 },
231 test: {
232 command: [
233 tsNodeRuntime + " test/test-es6.ts",
234 "node test/index.js"
235 ].join(' && ')
236 },
237 generatebrowser: {
238 command: 'node test/browser/generator/generate.js'
239 },
240 runbrowser: {
241 command: 'node test/browser/generator/runner.js'
242 },
243 benchmark: {
244 command: "node benchmark/index.js"
245 },
246 opts: {
247 // test running with all current options (using `opts` since `options` means something already)
248 command: [
249 // @TODO: make this more thorough
250 // CURRENT OPTIONS
251 `node bin/lessc --ie-compat ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`,
252 // --math
253 `node bin/lessc --math=always ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`,
254 `node bin/lessc --math=parens-division ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`,
255 `node bin/lessc --math=parens ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`,
256 `node bin/lessc --math=strict ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`,
257 `node bin/lessc --math=strict-legacy ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`,
258
259 // DEPRECATED OPTIONS
260 // --strict-math
261 `node bin/lessc --strict-math=on ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`
262 ].join(" && ")
263 },
264 plugin: {
265 command: [
266 `node bin/lessc --clean-css="--s1 --advanced" ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`,
267 "cd lib",
268 `node ../bin/lessc --clean-css="--s1 --advanced" ../${lessFolder}/_main/lazy-eval.less ../tmp/lazy-eval.css`,
269 "cd ..",
270 // Test multiple plugins
271 `node bin/lessc --plugin=clean-css="--s1 --advanced" --plugin=autoprefix="ie 11,Edge >= 13,Chrome >= 47,Firefox >= 45,iOS >= 9.2,Safari >= 9" ${lessFolder}/_main/lazy-eval.less tmp/lazy-eval.css`
272 ].join(" && ")
273 },
274 "sourcemap-test": {
275 // quoted value doesn't seem to get picked up by time-grunt, or isn't output, at least; maybe just "sourcemap" is fine?
276 command: [
277 `node bin/lessc --source-map=test/sourcemaps/maps/import-map.map ${lessFolder}/_main/import.less test/sourcemaps/import.css`,
278 `node bin/lessc --source-map ${lessFolder}/sourcemaps/basic.less test/sourcemaps/basic.css`
279 ].join(" && ")
280 }
281 },
282
283 eslint: {
284 target: [
285 "test/**/*.js",
286 "src/less*/**/*.js",
287 "!test/less/errors/plugin/plugin-error.js"
288 ],
289 options: {
290 configFile: ".eslintrc.json",
291 fix: true
292 }
293 },
294
295 connect: {
296 server: {
297 options: {
298 port: 8081
299 }
300 }
301 },
302
303 "saucelabs-mocha": sauceJobs,
304
305 // Clean the version of less built for the tests
306 clean: {
307 test: ["test/browser/less.js", "tmp", "test/less-bom"],
308 "sourcemap-test": [
309 "test/sourcemaps/*.css",
310 "test/sourcemaps/*.map"
311 ],
312 sauce_log: ["sc_*.log"]
313 }
314 });
315
316 // Load these plugins to provide the necessary tasks
317 grunt.loadNpmTasks("grunt-saucelabs");
318
319 require("jit-grunt")(grunt);
320
321 // by default, run tests
322 grunt.registerTask("default", ["test"]);
323
324 // Release
325 grunt.registerTask("dist", [
326 "shell:build"
327 ]);
328
329 // Create the browser version of less.js
330 grunt.registerTask("browsertest-lessjs", [
331 "shell:testbrowser"
332 ]);
333
334 // Run all browser tests
335 grunt.registerTask("browsertest", [
336 "browsertest-lessjs",
337 "connect",
338 "shell:runbrowser"
339 ]);
340
341 // setup a web server to run the browser tests in a browser rather than phantom
342 grunt.registerTask("browsertest-server", [
343 "browsertest-lessjs",
344 "shell:generatebrowser",
345 "connect::keepalive"
346 ]);
347
348 var previous_force_state = grunt.option("force");
349
350 grunt.registerTask("force", function(set) {
351 if (set === "on") {
352 grunt.option("force", true);
353 } else if (set === "off") {
354 grunt.option("force", false);
355 } else if (set === "restore") {
356 grunt.option("force", previous_force_state);
357 }
358 });
359
360 grunt.registerTask("sauce", [
361 "browsertest-lessjs",
362 "shell:generatebrowser",
363 "connect",
364 "sauce-after-setup"
365 ]);
366
367 grunt.registerTask("sauce-after-setup", [
368 "saucelabs-mocha:all",
369 "clean:sauce_log"
370 ]);
371
372 var testTasks = [
373 "clean",
374 "eslint",
375 "shell:testbuild",
376 "shell:test",
377 "shell:opts",
378 "shell:plugin",
379 "connect",
380 "shell:runbrowser"
381 ];
382
383 if (
384 isNaN(Number(process.env.TRAVIS_PULL_REQUEST, 10)) &&
385 (process.env.TRAVIS_BRANCH === "master")
386 ) {
387 testTasks.push("force:on");
388 testTasks.push("sauce-after-setup");
389 testTasks.push("force:off");
390 }
391
392 // Run all tests
393 grunt.registerTask("test", testTasks);
394
395 // Run shell option tests (includes deprecated options)
396 grunt.registerTask("shell-options", ["shell:opts"]);
397
398 // Run shell plugin test
399 grunt.registerTask("shell-plugin", ["shell:plugin"]);
400
401 // Quickly build and run Node tests
402 grunt.registerTask("quicktest", [
403 "shell:testcjs",
404 "shell:test"
405 ]);
406
407 // generate a good test environment for testing sourcemaps
408 grunt.registerTask("sourcemap-test", [
409 "clean:sourcemap-test",
410 "shell:build:lessc",
411 "shell:sourcemap-test",
412 "connect::keepalive"
413 ]);
414
415 // Run benchmark
416 grunt.registerTask("benchmark", [
417 "shell:testcjs",
418 "shell:benchmark"
419 ]);
420};