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