Gruntfile.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. module.exports = function(grunt) {
  2. // Load all grunt modules
  3. require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
  4. // Tell our Express server that Grunt launched it
  5. process.env.GRUNTED = true;
  6. // Project configuration.
  7. grunt.initConfig({
  8. pkg: grunt.file.readJSON('package.json'),
  9. settings: grunt.file.readJSON('./server_config/settings.json'),
  10. webfont: {
  11. icons: {
  12. src: 'front/src/fonts/svg-icons/*.svg',
  13. dest: 'tmp',
  14. destCss: 'front/src/less',
  15. options: {
  16. engine: 'node',
  17. types: 'woff',
  18. stylesheet: 'less',
  19. embed: true,
  20. htmlDemo: false,
  21. syntax: 'bootstrap'
  22. }
  23. }
  24. },
  25. less: {
  26. all: {
  27. files: [
  28. {
  29. expand: true,
  30. cwd: 'front/src/less/',
  31. src: ['**/*.less'],
  32. dest: 'front/src/css/',
  33. ext: '.css'
  34. }
  35. ]
  36. }
  37. },
  38. replace: {
  39. dist: {
  40. options: {
  41. patterns: [
  42. {
  43. match: 'googleAnalyticsId',
  44. replacement: '<%= settings.googleAnalyticsId %>'
  45. },
  46. {
  47. match: 'version',
  48. replacement: 'v<%= pkg.version %>'
  49. }
  50. ]
  51. },
  52. files: [
  53. {expand: true, flatten: true, src: ['front/src/main.html'], dest: 'front/build/'}
  54. ]
  55. }
  56. },
  57. jshint: {
  58. all: [
  59. '*.js',
  60. 'app/lib/*.js',
  61. 'bin/*.js',
  62. 'lib/**/*.js',
  63. 'app/nodeControllers/*.js',
  64. 'app/public/scripts/*.js',
  65. 'phantomas_custom/**/*.js',
  66. 'test/api/*.js',
  67. 'test/core/*.js',
  68. 'test/fixtures/*.js',
  69. 'front/src/js/**/*.js'
  70. ]
  71. },
  72. clean: {
  73. tmp: {
  74. src: ['.tmp']
  75. },
  76. dev: {
  77. src: ['front/src/css']
  78. },
  79. coverage: {
  80. src: ['.tmp', 'coverage/']
  81. },
  82. build: {
  83. src: ['front/build']
  84. }
  85. },
  86. copy: {
  87. beforeCoverage: {
  88. files: [
  89. {src: ['bin/server.js'], dest: '.tmp/'}
  90. ]
  91. },
  92. coverage: {
  93. files: [
  94. {cwd: 'test', src: '**/*', dest: 'coverage/test', expand: true},
  95. {cwd: 'lib/metadata', src: '**/*', dest: 'coverage/lib/metadata', expand: true},
  96. {cwd: 'node_modules/phantomas', src: '**/*', dest: 'coverage/node_modules/phantomas', expand: true},
  97. {cwd: 'lib/tools/phantomas/custom_modules', src: '**/*', dest: 'coverage/lib/tools/phantomas/custom_modules', expand: true}
  98. ]
  99. },
  100. build: {
  101. files: [
  102. {src: ['./front/src/img/favicon.png'], dest: './front/build/img/favicon.png'},
  103. {src: ['./front/src/img/logo-large.png'], dest: './front/build/img/logo-large.png'},
  104. ]
  105. }
  106. },
  107. lineremover: {
  108. beforeCoverage: {
  109. files: {
  110. '.tmp/bin/cli.js': 'bin/cli.js'
  111. },
  112. options: {
  113. exclusionPattern: /#!\/usr\/bin\/env node/
  114. }
  115. }
  116. },
  117. blanket: {
  118. coverageApp: {
  119. src: ['app/'],
  120. dest: 'coverage/app/'
  121. },
  122. coverageLib: {
  123. src: ['lib/'],
  124. dest: 'coverage/lib/'
  125. },
  126. coverageBin: {
  127. src: ['.tmp/bin/'],
  128. dest: 'coverage/bin/'
  129. }
  130. },
  131. mochaTest: {
  132. test: {
  133. options: {
  134. reporter: 'spec',
  135. },
  136. src: ['coverage/test/core/*.js', 'coverage/test/api/*.js']
  137. },
  138. 'test-current-work': {
  139. options: {
  140. reporter: 'spec',
  141. },
  142. src: ['test/core/offendersHelpersTest.js']
  143. },
  144. coverage: {
  145. options: {
  146. reporter: 'html-cov',
  147. quiet: true,
  148. captureFile: 'coverage/coverage.html'
  149. },
  150. src: ['coverage/test/core/*.js', 'coverage/test/api/*.js']
  151. }
  152. },
  153. env: {
  154. dev: {
  155. NODE_ENV: 'development'
  156. },
  157. built: {
  158. NODE_ENV: 'production'
  159. }
  160. },
  161. express: {
  162. dev: {
  163. options: {
  164. port: 8383,
  165. server: './bin/server.js',
  166. serverreload: true,
  167. showStack: true
  168. }
  169. },
  170. built: {
  171. options: {
  172. port: 8383,
  173. server: './bin/server.js',
  174. serverreload: true,
  175. showStack: true
  176. }
  177. },
  178. test: {
  179. options: {
  180. port: 8387,
  181. server: './coverage/bin/server.js',
  182. showStack: true
  183. }
  184. },
  185. 'test-current-work': {
  186. options: {
  187. port: 8387,
  188. server: './bin/server.js',
  189. showStack: true
  190. }
  191. },
  192. testSuite: {
  193. options: {
  194. port: 8388,
  195. bases: 'test/www'
  196. }
  197. }
  198. },
  199. useminPrepare: {
  200. html: './front/src/main.html',
  201. options: {
  202. dest: './front/build',
  203. root: ['./', './front/src']
  204. }
  205. },
  206. usemin: {
  207. html: './front/build/main.html',
  208. css: './front/build/css/*.css',
  209. options: {
  210. assetsDirs: ['front/build']
  211. }
  212. },
  213. htmlmin: {
  214. options: {
  215. removeComments: true,
  216. collapseWhitespace: true,
  217. conservativeCollapse: true
  218. },
  219. main: {
  220. files: [{
  221. expand: true,
  222. cwd: './front/build/',
  223. src: 'main.html',
  224. flatten: true,
  225. dest: './front/build'
  226. }]
  227. },
  228. views: {
  229. files: [{
  230. expand: true,
  231. cwd: './front/src/views',
  232. src: '*.html',
  233. flatten: true,
  234. dest: '.tmp/views/'
  235. }]
  236. }
  237. },
  238. inline_angular_templates: {
  239. build: {
  240. options: {
  241. base: '.tmp',
  242. method: 'append'
  243. },
  244. files: {
  245. './front/build/main.html': ['.tmp/views/*.html']
  246. }
  247. }
  248. },
  249. filerev: {
  250. options: {
  251. algorithm: 'md5',
  252. length: 8
  253. },
  254. assets: {
  255. src: './front/build/*/*.*'
  256. }
  257. }
  258. });
  259. // Custom task: copies the test settings.json file to the coverage folder, and checks if there's no missing fields
  260. grunt.registerTask('copy-test-server-settings', function() {
  261. var mainSettingsFile = './server_config/settings.json';
  262. var testSettingsFile = './test/fixtures/settings.json';
  263. var mainSettings = grunt.file.readJSON(mainSettingsFile);
  264. var testSettings = grunt.file.readJSON(testSettingsFile);
  265. // Recursively compare keys of two objects (not the values)
  266. function compareKeys(original, copy, context) {
  267. for (var key in original) {
  268. if (!copy[key] && copy[key] !== '' && copy[key] !== 0) {
  269. grunt.fail.warn('Settings file ' + testSettingsFile + ' doesn\'t contain key ' + context + '.' + key);
  270. }
  271. if (original[key] !== null && typeof original[key] === 'object') {
  272. compareKeys(original[key], copy[key], context + '.' + key);
  273. }
  274. }
  275. }
  276. compareKeys(mainSettings, testSettings, 'settings');
  277. var outputFile = './coverage/server_config/settings.json';
  278. grunt.file.write(outputFile, JSON.stringify(testSettings, null, 4));
  279. grunt.log.ok('File ' + outputFile + ' created');
  280. });
  281. grunt.registerTask('icons', [
  282. 'webfont:icons',
  283. 'less',
  284. 'clean:tmp'
  285. ]);
  286. grunt.registerTask('build', [
  287. 'jshint',
  288. 'clean:build',
  289. 'copy:build',
  290. 'less',
  291. 'useminPrepare',
  292. 'concat',
  293. 'uglify',
  294. 'cssmin',
  295. 'replace',
  296. 'htmlmin:views',
  297. 'inline_angular_templates',
  298. 'filerev',
  299. 'usemin',
  300. 'htmlmin:main',
  301. 'clean:tmp'
  302. ]);
  303. grunt.registerTask('hint', [
  304. 'jshint'
  305. ]);
  306. grunt.registerTask('dev', [
  307. 'env:dev',
  308. 'express:dev'
  309. ]);
  310. grunt.registerTask('built', [
  311. 'env:built',
  312. 'express:built'
  313. ]);
  314. grunt.registerTask('test', [
  315. 'build',
  316. 'express:testSuite',
  317. 'clean:coverage',
  318. 'copy-test-server-settings',
  319. 'lineremover:beforeCoverage',
  320. 'copy:beforeCoverage',
  321. 'blanket',
  322. 'copy:coverage',
  323. 'express:test',
  324. 'mochaTest:test',
  325. 'mochaTest:coverage',
  326. 'clean:tmp'
  327. ]);
  328. grunt.registerTask('test-current-work', [
  329. 'jshint',
  330. 'express:testSuite',
  331. 'clean:coverage',
  332. 'copy-test-server-settings',
  333. 'express:test-current-work',
  334. 'mochaTest:test-current-work',
  335. 'clean:tmp'
  336. ]);
  337. };