Gruntfile.js 10 KB

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