Related
I've got several projects that each use an identical Gruntfile to run tasks and put the output in their own dist folder. Folder setup:
MyProjects
- Project1
- src
- dist
- Project2
- src
- dist
.....
I can't figure out how to run Grunt at the top level (MyProjects) and still have the output generated in the correct dist folder dynamically.
Is there a way I can have Grunt put the output in the correct dist folder without having to hard code it into the Gruntfile? Something like:
dist: {
files: {
// destination : source js
'<% ProjectName %>/dist/app.js': '<% ProjectName %>/src/app.js'
},
Thanks
module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
// Project configuration.
grunt.initConfig({
watch: {
scripts: {
files: ['src/**/*.js'],
tasks: ['browserify', 'file_append', 'concat'],
options: {
spawn: false
}
},
sass: {
files: "src/scss/*.scss",
tasks: ['sass', 'file_append', 'concat']
}
},
sass: {
dist: {
options: {
style: 'expanded'
},
files: {
// destination // source file
"format/css/styles.css": "src/scss/styles.scss"
}
},
options: {
sourcemap: "none",
style: "compact",
noCache: true
}
},
file_append: {
default_options: {
files: [
// Development build
{
append: "",
prepend: "",
input: "format/app.js",
output: "format/dev.app.js"
},
{
append: "</style>`)",
prepend: "document.body.insertAdjacentHTML('afterbegin', `\n<style>\n",
input: "format/css/styles.css",
output: "format/css/dev.styles.html"
},
// Production build
{
append: "</script>",
prepend: "<script>\n",
input: "format/app.js",
output: "format/prod.app.html"
},
{
append: "</style>",
prepend: "<style>\n",
input: "format/css/styles.css",
output: "format/css/prod.styles.html"
}
]
}
},
concat: {
options: {
seperator: '\n'
},
// Development build
dev: {
src: ['format/dev.app.js', 'format/css/dev.styles.html'],
dest: 'dev/dev.app.js'
},
// Production build
prod: {
src: ['format/prod.app.html', 'format/css/prod.styles.html'],
dest: 'dist/prod.app.html'
}
},
browserify: {
dist: {
files: {
// destination for transpiled js : source js
'format/app.js': 'src/app.js'
},
options: {
transform: [
[
'babelify', {
presets: "es2015",
comments: false,
plugins: "transform-object-rest-spread"
}
]
],
browserifyOptions: {
debug: false
}
}
}
}
});
grunt.registerTask('default', [
'sass',
'browserify:dist',
'file_append',
'concat',
'watch'
]);
};
There's a couple ways you can tackle this.
One option is to overload the arguments you pass to the task & include the folder name you wish to target.
grunt sass:dist:Project1
The additional argument is accessible via lodash templates which are a part of the GruntJS framework, and allows the configuration to be set at the time the task is ran:
sass: {
dist: {
options: {
style: 'expanded'
},
files: {
// destination // source file
"MyProjects/<%= grunt.task.current.args[0] %>/format/css/styles.css": "MyProjects/<%= grunt.task.current.args[0] %>/src/scss/styles.scss"
}
},
options: {
sourcemap: "none",
style: "compact",
noCache: true
}
}
This approach works in the context of the function that's executing, but it wouldn't continue to pass the args to the next task. To do that, we need to add a custom task which will set a configuration object before executing the task list:
grunt.registerTask("build", (project) => {
const buildConfig = { project };
grunt.config.set("build", buildConfig);
grunt.task.run([
'sass',
'browserify:dist',
'file_append',
'concat',
'watch'
]);
});
Now when we run grunt build:Project1, your custom task build will run and set the property we passed in the grunt config object. We can then reference that value in our other grunt config objects using lodash like we did for the first option. To access config values with lodash templates, we just have to provide the config pointer in json notation:
files: {
"MyProjects/<%= build.project %>/format/css/styles.css": "MyProjects/<%= build.project %>/src/scss/styles.scss"
}
Grunt compiles the configs required for a task at the time they're run & will process the lodash templates then, allowing you to inject your project name into a task. Since we stored the value in the config object, the value will persist through until grunt completes and exits.
I am using Grunt with php and am using a package to version my css with a date stamp as style.min.20160913230349.css.
However how do I find a package that will update the new string to the header in my php page. style.min.{grunt_this_string}.css.
I'm looking a usemin but can't see how I could implement it.
<link rel="stylesheet" media="all" href="/css/style.min.20160913230349.css" type="text/css"/>
Gruntfile.js
module.exports = function (grunt) {
grunt.initConfig({
/*=============================================
= Proxy server =
=============================================*/
php: {
dist: {
options: {
hostname: 'sau.dev',
base: 'website-v2', // Project root
keepalive: false,
open: false
}
}
},
browserSync: {
dev: {
bsFiles: {
src: [
'website-v2/*.php',
'website-v2/*/*.php',
'website-v2/css/*.css'
]
},
options: {
proxy: 'sau.dev',//<%= php.dist.options.hostname %>:<%= php.dist.options.port %>
ghostMode: {
clicks: false,
forms: false,
scroll: true
},
logLevel: 'info',//client
logConnections: true,
watchTask: true,
open: 'ui',
xip: true,
}
}
},
watch: {
html: {
files: ['src/*.html'],
}
},
cssmin: {
dist: {
files: {
'website-v2/css/style.min.css': ['website-v2/css/all.css']
}
}
},
uglify: {
dist: {
files: {
'website-v2/js/main.min.js': ['website-v2/js/jquery- 1.9.1.min.js','jquery-ui.min.js','main.js','featherlight.js']
}
}
},
assets_versioning: {
options: {
tag: 'date',
dateFormat: 'YYYYMMDDHH',
timezoneOffset: 10
},
dist: {
options: {
tasks: ['cssmin:dist']
}
},
},
});
//grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browser-sync');
grunt.loadNpmTasks('grunt-php');
grunt.loadNpmTasks('grunt-assets-versioning');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-string-replace');
//grunt.loadNpmTasks('usemin');
//Static Server
grunt.registerTask('dist', ['versioning']);
//Proxy Server
grunt.registerTask('server', ['php:dist','browserSync','watch']);
};
After understand your problem, I think that you need to create a assets.map
You need to add this in gruntfile.js.
options: {
...
versionsMapFile: 'assets.json',
...
}
I would like to believe that grunt-assets-versioning create a version taken the date.
You need to replace in your html with the version that provide assest.json.
I recommend to use grunt-string-replace for this.
replace: {
dist: {
options: {
patterns: [
{
match: 'style.min.css',
replacement: replacement()
}
]
},
files: [
{src: ['src/assets/index.html'], dest: 'build/index.html'}
]
}
}
...
grunt.registerTask('versioning', ['assets_versioning']);
grunt.registerTask('replace', ['string-replace']
...
function replacements() {
var projectFile = "assets.json";
if (!grunt.file.exists(projectFile)) {
grunt.log.error("file " + projectFile + " not found");
return true;//return false to abort the execution
}
var project = grunt.file.readJSON(projectFile);//get file as json object
var version = project[0].version;
var replace = ''
// continue with the algorithm that you need
return replace;
}
I hope that helps.
I am trying to configure Grunt & Browserify to output a standalone bundle containing, among other things, React as CommonJS module so that it can be referenced by other bundles.
The problem that I am having now is that the aliasing does not seem to work. Despite having specified aliases in my external bundle vendor below, and having specified that those modules should be loaded externally in all the other models, I'm still getting an error at run time, stating that the 'react' module cannot be found.
It would be great if anyone knows what might be wrong about my grunt-browserify syntax here:
var externals = [
'react',
'react/addons',
'jquery',
'backbone',
'react-router'
];
module.exports = function(grunt) {
grunt.config.set('browserify', {
main: {
src: 'assets/js/main.jsx',
dest: '.tmp/public/js/main.js',
options: {
debug: true,
extensions: ['.jsx'],
external: externals,
transform: [
['babelify', {'stage': 0}]
]
}
},
signup: {
src: 'assets/js/signup.jsx',
dest: '.tmp/public/js/signup.js',
options: {
debug: true,
extensions: ['.jsx'],
external: externals,
transform: [
['babelify', {'stage': 0}]
]
}
},
login: {
src: 'assets/js/login.jsx',
dest: '.tmp/public/js/login.js',
options: {
debug: true,
insertGlobals: true,
extensions: ['.jsx'],
external: externals,
transform: [
['babelify', {'stage': 0}]
]
}
},
vendor: {
src: [
'./node_modules/react/dist/react.js',
'./node_modules/react/dist/react-with-addons.js',
'./node_modules/jquery/dist/jquery.js',
'./node_modules/backbone/backbone.js',
],
dest: '.tmp/public/js/dependencies/vendor.js',
options: {
debug: false,
alias: {
'react:': './node_modules/react/dist/react.js',
'react/addons': './node_modules/react/dist/react-with-addons.js',
'jquery': './node_modules/jquery/dist/jquery.js',
'backbone': './node_modules/backbone/backbone.js',
'react-router': './node_modules/react-router/lib/index.js'
},
shim: {
react_router: {
path: './node_modules/react-router/lib/index.js',
exports: 'react-router'
}
},
external: null
}
}
});
grunt.loadNpmTasks('grunt-browserify');
};
I've found this link helpful for me. Following this approach your vendor section should look like
vendor: {
src: ['.'],
dest: '.tmp/public/js/dependencies/vendor.js',
options: {
debug: false,
alias: externals.map(function(module) {
return module + ':';
}),
shim: {
react_router: {
path: './node_modules/react-router/lib/index.js',
exports: 'react-router'
}
},
external: null
}
}
I'm not sure about the shim section above, because I've tried this only for the react module.
I am working on a Sails 0.11.0 project with ReactJS. I start my grunt watchify task to handle rebundling/transforming my app code, while using the vendor task to bundle the moduled code. I additionally had to add the vendor.js to my layout file.
I am fairly new to the grunt world, so there may be more efficient ways to do this.
browserify.js
var externals = [
'react',
'react/addons',
'jquery',
'react-router',
'events'
]
module.exports = function(grunt){
grunt.config.set('browserify', {
dist: {
options: {
external: externals,
transform: [
['babelify', {
loose: 'all'
}]
]
},
files: {
".tmp/public/js/bundle.js": ["assets/js/bundle.js", "react/**/*"]
}
},
vendor: {
src: [
'./node_modules/react/dist/react.js',
'./node_modules/react/dist/react-with-addons.js',
'./node_modules/jquery/dist/jquery.js',
'./node_modules/react-router/lib/index.js',
'./node_modules/events/events.js'
],
dest: '.tmp/public/js/dependencies/vendor.js',
options: {
alias: {
'react': './node_modules/react/dist/react.js',
'react/addons': './node_modules/react/dist/react-with-addons.js',
'jquery': './node_modules/jquery/dist/jquery.js',
'react-router': './node_modules/react-router/lib/index.js',
'events': './node_modules/events/events.js'
}
}
}
});
grunt.loadNpmTasks('grunt-browserify');
}
tasks/config:
module.exports = function(grunt) {
grunt.config.set('watch', {
api: {
// API files to watch:
files: ['api/**/*', '!**/node_modules/**']
},
assets: {
// Assets to watch:
files: ['assets/**/*', 'tasks/pipeline.js', '!**/node_modules/**'],
// When assets are changed:
tasks: ['syncAssets' , 'linkAssets', 'browserify:dist']
},
react: {
files: ['react/**/*'],
tasks: ['browserify:dist']
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
};
Here is the full Grunt configuration for the React:
https://github.com/koshkarov/reactjs-grunt-configuration
I've created a dummy project so you can build it to test.
Gruntfile.js for the project:
module.exports = function (grunt) {
let concat = {};
let clean = {};
let uglify = {};
let copy = {};
let htmlmin = {};
let cssmin = {};
let browserify = {};
let watch = {};
let template = {};
let run = {};
/* React configuration. */
const reactSourcePath = './source';
const reactCompiledPath = './client';
const reactHtmlPathDest = './client/index.html'
const reactTargetName = "react";
const reactFileName = "react_main";
/* ### TASK CONFIGURATIONS ### */
/* Clean compiled files. */
clean[reactTargetName] = [
`${reactCompiledPath}`
];
/* Concatenate all CSS files to one. */
const cssConcatSourceTemplate = `${reactSourcePath}/**/**.css`;
const cssDestinationFile = `${reactCompiledPath}/css/${reactFileName}.css`;
concat[reactTargetName] = {
src: [cssConcatSourceTemplate],
dest: cssDestinationFile
};
/* Convert JSX to JS, prepare JS files for a browser and copy to the destination. */
const jsSourceFile = `${reactSourcePath}/index.js`;
const jsDestinationFile = `${reactCompiledPath}/js/${reactFileName}.js`;
browserify[reactTargetName] = {
options: {
transform: [['babelify', {presets: ['es2015', 'react']}]]
},
files: {
[jsDestinationFile]: jsSourceFile
}
};
/* Replace js/css placeholders and copy html file to destination. */
const applicationData = {
css: [
'./css/react_main.css'
],
js: [
'./js/react_main.js'
]
};
var jsFiles = "";
var cssFiles = "";
applicationData.css.forEach(function(item) {
cssFiles = cssFiles + `\n<link rel="stylesheet" type="text/css" href=${item}>`;
});
applicationData.js.forEach(function(item) {
jsFiles = jsFiles + `\n<script type="text/javascript" src=${item}></script>`;
});
template[reactTargetName] = {
options: {
data: {
appName: '<%= pkg.name %>' + '-react',
productVersion: '<%= pkg.version %>',
reactEmbeddedCssFiles: cssFiles,
reactEmbeddedJsFiles: jsFiles
}
},
files: {
[`${reactHtmlPathDest}`]: `${reactSourcePath}/index.template.html`,
}
};
/* Uglify react JS file. */
uglify[reactTargetName] = {
files: {
[jsDestinationFile]: jsDestinationFile
}
};
/* Copy bootstrap CSS/JS files. */
copy[reactTargetName] = {
files: {
[`${reactCompiledPath}/css/bootstrap.min.css`]: 'node_modules/bootstrap/dist/css/bootstrap.min.css',
[`${reactCompiledPath}/js/bootstrap.min.js`]: 'node_modules/bootstrap/dist/js/bootstrap.min.js',
[`${reactCompiledPath}/js/jquery.min.js`]: 'node_modules/jquery/dist/jquery.min.js',
}
}
/* Minify HTML files. */
htmlmin[reactTargetName] = {
options: {
removeComments: true,
collapseWhitespace: true
},
files: {
[`${reactHtmlPathDest}`]: `${reactHtmlPathDest}`
}
};
/* Minify react CSS file. */
cssmin[reactTargetName] = {
files: {
[cssDestinationFile]: cssDestinationFile
}
};
/* Watch for any changes in react app.
There are three separate watches for css, js, and html files. */
watch[reactTargetName + '_css'] = {
files: [`${reactSourcePath}/**/*.css`],
tasks: [`concat:${reactTargetName}`],
options: {
livereload: true
}
};
watch[reactTargetName + '_js'] = {
files: [`${reactSourcePath}/**/*.js`],
tasks: [`browserify:${reactTargetName}`],
options: {
livereload: true
}
};
watch[reactTargetName + '_hmtl'] = {
files: [`${reactSourcePath}/**/*.html`],
tasks: [`template:${reactTargetName}`],
options: {
livereload: true
}
};
/* Jest tests */
jestTestsTaskName = reactTargetName + '_jest_tests';
run[jestTestsTaskName] = {
exec: 'npm test'
};
/* Generate task names for react. */
var reactTasks = {
debug: [
"clean",
"browserify",
"concat",
"copy",
"template"
].map(x => x + `:${reactTargetName}`),
release: [
"clean",
"browserify",
"concat",
"copy",
"template",
"htmlmin",
"uglify",
"cssmin"
].map(x => x + `:${reactTargetName}`)
};
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch:watch,
copy:copy,
concat:concat,
clean:clean,
uglify:uglify,
template:template,
browserify: browserify,
htmlmin: htmlmin,
cssmin: cssmin,
run:run
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-template');
grunt.loadNpmTasks("grunt-browserify");
grunt.loadNpmTasks("grunt-contrib-htmlmin");
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-run');
grunt.registerTask('react_build_debug', reactTasks.debug);
grunt.registerTask('react_build_release', reactTasks.release);
}
I was wondering if anyone has got grunt karma to run just one spec that is changed on watch. This is my config below. The problem is that the line grunt.config('karma.unit.options.files', filepath); doesn't seem to be doing anything as all the specs still get run however foo does get output before the karma:unit:run gets fired.
grunt.initConfig({
karma: {
unit: {
configFile: 'karma.conf.js',
background: true,
singleRun: false,
options: {
files: allFilesArray
}
}
},
watch: {
options: {
spawn: false,
livereload: true
},
karma: {
files: ['js/spec/**/*.spec.js', 'js/src/**/*.js'],
tasks: ['karma:unit:run']
}
}
})
grunt.event.on('watch', function (action, filepath){
console.log('foo');
grunt.config('karma.unit.options.files', filepath);
});
Is there anyone out there who has achieved running one spec in the terminal on file change? We have thousands of tests so it is starting to get slow.
Thanks,
Alex
I got this to work. Basically, you use watch with an event handler to dynamically change the karma config whenever a file changes. Here's the rundown:
My Grunt config has two karma tasks: "all" and "one". "all" runs all of them, and "one" only runs a single file which it does not know beforehand.
grunt.initConfig({
// ...
karma: {
all: {
configFile: 'karma.conf.js',
browsers: ['PhantomJS'],
singleRun: true,
options: {
files: [
'bower_components/jquery/dist/jquery.js', // dependencies
'src/js/**/*.js', // js source files
'src/js/**/*.spec.js' // unit test files
]
}
},
one: {
configFile: 'karma.conf.js',
browsers: ['PhantomJS'],
singleRun: true,
files: [
{src: 'bower_components/jquery/dist/jquery.js'}, // dependencies
{src: ['src/js/**/*.js','!src/js/**/*.spec.js']} // source files
// (exclude the unit test files)
// watchEventListener will add the unit test file to run
]
}
},
// ...
});
And then later in my gruntfile, I add a listener for watch events. This listener updates the karma:one task and adds the unit test file. We keep a copy of the original files array, or else our additions would persist and accumulate through the lifetime of the watch task.
// when a unit test changes, execute only it
var original_karmaOne_files = grunt.config.get('karma.one.files'); // keep the original files array
grunt.event.on('watch', function watchEventListener(action, filepath, target){
// this handler handles ALL watch changes. Try to filter out ones from other watch tasks
if (target == 'js_spec') handleJSHintSpec();
// ---------------------
function handleJSHintSpec() {
if (action == 'deleted') return; // we don't need to run any tests when a file is deleted
// this will probably fail if a watch task is triggered with multiple files at once
// dynamically change the config
grunt.config.set('karma.one.files', [].concat(original_karmaOne_files, [{src: filepath}]));
}
});
And here is my gruntfile's watch task:
watch: {
// ...
// when js spec files change,
// lint them
// run unit tests
js_spec: {
options: {
interrupt: true
},
files: 'src/js/**/*.spec.js',
tasks: ['jshint:js_spec', 'karma:one']
},
// ...
}
My karma.conf.js file is pretty default, but its files array is empty. Actually, I commented it out, so the property is undefined.
// list of files / patterns to load in the browser
//files: [], // specified in the gruntfile
TL; DR: Use karma:unit everywhere instead of karma:unit:run and use grunt.event.on('watch', function(){}); to edit the karma config to only include the test files you want to run.
I have this working, but it might not be what you want. I'm starting the server up again every time I save a file. Further explanation is below. Here is some of the config:
watch: {
tests: {
files: 'tests/**/*.js',
tasks: ['karma:unit']
},
tsChanged: {
files: config.tsFiles,
tasks: [
'ts',
'karma:unit'
]
}
}
grunt.event.on('watch', function(action, filepath){
grunt.config(['karma', 'unit', 'files'], [{
src: [
path/to/your/source/files,
path/to/your/test/file,
]
}]);
});
It seems to me that karma loads all of the app files and the test files into the browser whenever it starts the server. In your case, that would be when you enter "grunt karma:unit:start watch" into the command line. So here, I used "grunt watch" and just added a "karma:unit" to the process. Then I caught the save event and updated the karma config before it started up the server.
Hope this helps.
Using a combination of yargs and some runtime-magic, I do this:
var argv = require('yargs')
.default('t', '*.js')
.alias('t', 'tests')
.describe('t', 'A file or file pattern of the test files to run, relative to the test/unit dir')
.help('?')
.alias('?', 'help')
.argv;
var filesToLoad = ['src/**/*.js', 'test/unit/helpers/*.js'];
filesToLoad.push(path.join('test/unit/**', argv.t));
gulp.task('tdd', function (done) {
karma.start({
configFile: __dirname + '/../../karma.conf.js',
jspm: {
loadFiles: filesToLoad,
}
}, function(e) {
done();
});
});
Which takes a test file / path pattern as an argument to gulp and loads that in preference to all the files.
Based on the answer of Matthias and the comments my Grundfile.js is:
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
karma: {
all: {
configFile: 'karma.conf.js',
background: true,
files: [
{ src: './Leen.Managementsystem/bower_components/jquery/dist/jquery.js' },
{ src: './Leen.Managementsystem/bower_components/globalize/lib/globalize.js' },
{ src: './Leen.Managementsystem/bower_components/**/*.js', included: false },
{ src: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false },
{ src: './Leen.Managementsystem/App/**/*.js', included: false },
{ src: './Leen.Managementsystem.Tests/App/test/*.js', included: false },
{ src: './Leen.Managementsystem.Tests/App/**/*.spec.js', included: false },
{ src: './Leen.Managementsystem.Tests/App/test-main.js' }
]
},
one: {
configFile: 'karma.conf.js',
files: [
{ src: './Leen.Managementsystem/bower_components/jquery/dist/jquery.js' },
{ src: './Leen.Managementsystem/bower_components/globalize/lib/globalize.js' },
{ src: './Leen.Managementsystem/bower_components/**/*.js', included: false },
{ src: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false },
{ src: './Leen.Managementsystem/App/**/*.js', included: false },
{ src: './Leen.Managementsystem.Tests/App/test/*.js', included: false },
// (do not inlcude the *.spec.js files here! The watch event listener will add the single spec file to run)
{ src: './Leen.Managementsystem.Tests/App/test-main.js' }
]
}
},
watch: {
spec_js: {
options: {
interrupt: true,
spawn: false
},
files: 'Leen.Managementsystem.Tests/App/**/*.spec.js',
tasks: ['karma:one:start']
}
}
});
var originalKarmaOneFiles = grunt.config.get('karma.one.files'); // keep the original files array
grunt.event.on('watch', function watchEventListener(action, filepath, target) {
if (target === 'spec_js') {
handleChangedSpecFile();
}
function handleChangedSpecFile() {
if (action === 'deleted') {
return;
}
var testFilePath = "./" + filepath.replace(/\\/g, "/");
grunt.log.writeln(['Running single karma test for: ' + testFilePath]);
var updatedFiles = originalKarmaOneFiles.concat([{ src: testFilePath, included: false }]);
grunt.config.set('karma.one.files', updatedFiles);
}
});
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['karma:all','watch']);
};
karma.conf.js:
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '', //the solution root path, e.g. D:\Energienetzwerke\trunk
// frameworks to use
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: [
'./Leen.Managementsystem/bower_components/jquery/dist/jquery.js',
'./Leen.Managementsystem/bower_components/globalize/lib/globalize.js',
{ pattern: './Leen.Managementsystem/bower_components/**/*.js', included: false },
{ pattern: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false },
{ pattern: './Leen.Managementsystem/App/**/*.js', included: false },
{ pattern: './Leen.Managementsystem.Tests/App/test/*.js', included: false},
{ pattern: './Leen.Managementsystem.Tests/App/**/*.spec.js', included: false},
'./Leen.Managementsystem.Tests/App/test-main.js'
],
// list of files to exclude
exclude: [
'./Leen.Managementsystem/App/main.js'
],
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['progress', 'coverage', 'notify', 'htmlDetailed', 'xml'],
coverageReporter: {
dir: './Leen.Managementsystem.Tests/testCoverage',
reporters: [
{ type: 'html',subdir: 'html'},
{ type: 'cobertura',subdir: 'xml', file: 'coverage.xml' },
{ type: 'lcov', subdir: 'lcov' },
{ type: 'text-summary' }
]
},
notifyReporter: {
reportEachFailure: true, // Default: false, Will notify on every failed spec
reportSuccess: false // Default: true, Will notify when a suite was successful
},
htmlDetailed: {
autoReload: true,
dir: './Leen.Managementsystem.Tests/testResults'
},
preprocessors: {
// source files, that you wanna generate coverage for
// do not include tests or libraries
// (these files will be instrumented by Istanbul)
'./Leen.Managementsystem/App/**/*.js': ['coverage']
},
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false, //watching is done by Gruntfile.js to only execute changed tests
usePolling: true,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['Chrome_With_Saved_DevTools_Settings'],
customLaunchers: {
Chrome_With_Saved_DevTools_Settings: {
base: 'Chrome',
chromeDataDir: './.chrome'
}
},
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true
});
};
package.json:
{
"name": "solution",
"version": "1.0.0",
"description": "contains packages that are needed for running karma",
"main": "./Leen.Managementsystem.Tests/App/test-main.js",
"dependencies": {
"grunt": "1.0.1",
"grunt-cli": "1.2.0",
"grunt-contrib-watch": "1.0.0",
"grunt-karma": "2.0.0",
"jasmine-core": "2.6.4",
"karma": "1.7.0",
"karma-chrome-launcher": "2.2.0",
"karma-cli": "1.0.1",
"karma-coverage": "1.1.1",
"karma-firefox-launcher": "1.0.1",
"karma-html-detailed-reporter": "1.1.20",
"karma-ie-launcher": "1.0.0",
"karma-jasmine": "1.1.0",
"karma-notify-reporter": "1.0.1",
"karma-phantomjs-launcher": "1.0.4",
"karma-requirejs": "1.1.0",
"karma-xml-reporter": "0.1.4",
"requirejs": "2.3.4"
},
"devDependencies": {},
"scripts": {
"test": "karma run"
},
"author": "LEEN",
"license": "private"
}
I am trying to define a custom function in the useminPrepare configuration, but no matter what I do, the function is eventually omitted in the build.
I have updated Node(0.10.36) and NPM(2.4.1) to the latest versions.
The config file:
useminPrepare: {
src: options.dist.dir + '/index.html',
options: {
dest: options.dist.dir + '/',
staging: options.temp.dir,
flow: {
steps: {
js: ['concat', 'uglifyjs']
},
post: {
js: [
{
name: 'concat',
createConfig: function(a,b) {
console.log(a,b);
}
},
'uglifyjs'
]
}
}
}
}
Grunt build verbose (notice createConfig is gone):
Running "useminPrepare:useminPrepare" (useminPrepare) task
Verifying property useminPrepare.useminPrepare exists in config...OK
Files: dist/index.html
Options: dest="dist/", staging=".tmp", flow={"steps":{"js":["concat","uglifyjs"]},"post":{"js":[{"name":"concat"},"uglifyjs"]}}
Going through dist/index.html to update the config
Looking for build script HTML comment blocks
Anyone have any idea?
It also omits if I specify my own parameter with a function as value (it wont get omitted if I specify a string):
name: 'concat',
test: function() {
console.log("Hello world");
},
createConfig: function() {
console.log(a,b);
}
I figured out what I did wrong, I should have specified the options outside my subtask, like so:
useminPreprare: {
options: {
dest: options.dist.dir + '/',
staging: options.temp.dir,
flow: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['concat', 'cssmin']
},
post: {
js: [
{
name: 'concat',
createConfig: function(a,b) {
console.log(a,b);
}
},
'uglifyjs'
]
}
}
},
build: {
src: options.dist.dir + '/index.html',
}
}
Now I can execute useminPrepare with the task useminPrepare:build