Gruntfile.js 14 KB

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