I'm trying to gather 3 tasks needed to debug in a 1. Of course, since nature of gulp is asynchronous, I have problems with that. So I searched and find a soulution to use run-sequence module for solving that issue. I tried the following code, but it doesn't seem to be working as intended. It's not getting synchronous.
Here's what I tried. Any thoughts guys? I don't want to run all this three commands to complete all the tasks. How can I do that?
var gulp = require('gulp'),
useref = require('gulp-useref'),
gulpif = require('gulp-if'),
debug = require('gulp-debug'),
rename = require("gulp-rename"),
replace = require('gulp-replace'),
runSequence = require('run-sequence'),
path = '../dotNet/VolleyManagement.UI';
gulp.task('debug', function () {
gulp.src('client/*.html')
.pipe(debug())
.pipe(gulp.dest(path + '/Areas/WebAPI/Views/Shared'));
});
gulp.task('rename', function () {
gulp.src(path + '/Areas/WebAPI/Views/Shared/index.html')
.pipe(rename('/Areas/WebAPI/Views/Shared/_Layout.cshtml'))
.pipe(gulp.dest(path));
gulp.src(path + '/Areas/WebAPI/Views/Shared/index.html', {read: false})
.pipe(clean({force: true}));
});
gulp.task('final', function(){
gulp.src([path + '/Areas/WebAPI/Views/Shared/_Layout.cshtml'])
.pipe(replace('href="', 'href="~/Content'))
.pipe(replace('src="', 'src="~/Scripts'))
.pipe(gulp.dest(path + '/Areas/WebAPI/Views/Shared/'));
});
gulp.task('debugAll', runSequence('debug', 'rename', 'final'));
In gulp you can actually set dependant task. Try this:
gulp.task('debug', function () {
//run debug task
});
gulp.task('rename',['debug'], function () {
//run rename once debug is done
});
I think you are not defining the 'debugAll' task right. Try like this:
gulp.task('debugAll', function () {
runSequence('debug', 'rename', 'final');
});
And also you need to return the stream for those tasks, just add 'return' in front of gulp.src for each of them: debug, rename, final. Here is the example for 'debug' task:
gulp.task('debug', function () {
return gulp.src('client/*.html')
.pipe(debug())
.pipe(gulp.dest(path + '/Areas/WebAPI/Views/Shared'));
});
Both items are mentioned in the docs: https://www.npmjs.com/package/run-sequence
Related
I have a simple gulpfile.js, that defines only two tasks, buildLess and watchFiles:
var gulp = require('gulp');
var less = require('gulp-less');
var watch = require('gulp-watch');
var plumber = require('gulp-plumber');
var filter = require('gulp-filter');
function buildLess(done) {
const fileFilter = filter(['**/*', '!**/mixins.less', '!**/variables.less']);
gulp.src('./public/less/*.less')
.pipe(fileFilter)
.pipe(plumber())
.pipe(less())
.pipe(gulp.dest('./public/css/'))
;
done();
};
function watchFiles() {
gulp.watch(['public/less/*.less'], gulp.series('build-less'));
// gulp.watch(['./public/less/*.less'], gulp.series(buildLess));
};
gulp.task('build-less', buildLess);
gulp.task('watch-files', watchFiles);
The first one ($ gulp build-less) is working fine. The watchFiles ($ gulp watch-files) can be started and doesn't cause any errors, but changes on the public/less/style.less are ignored.
What is wrong at this gulpfile.js and how to get the watch-files task working?
The gulp.series API allows you to pass a string of a previously registered task. In your code, you haven't registered build-less yet.
var gulp = require('gulp');
var less = require('gulp-less');
var watch = require('gulp-watch');
var plumber = require('gulp-plumber');
var filter = require('gulp-filter');
function buildLess(done) {
const fileFilter = filter(['**/*', '!**/mixins.less', '!**/variables.less']);
gulp.src('./public/less/*.less')
.pipe(fileFilter)
.pipe(plumber())
.pipe(less())
.pipe(gulp.dest('./public/css/'))
;
done();
};
gulp.task('build-less', buildLess);
function watchFiles() {
gulp.watch(['public/less/*.less'], gulp.series('build-less'));
// gulp.watch(['./public/less/*.less'], gulp.series(buildLess));
};
gulp.task('watch-files', watchFiles);
I would note that Gulp does not recommend using the gulp.task API anymore to register tasks, but instead to use exports.
Secondly, you don't need gulp-watch, as gulp now comes with its own gulp.watch method (which you are already using).
Lastly, you should make sure to your correctly signaling async completion in your buildLess function. Below, I've changed that function to return a Stream, rather than calling a done() callback since as you have it written, you have a race condition where done() may be called before the Less compilation has finished.
var gulp = require('gulp');
var less = require('gulp-less');
var plumber = require('gulp-plumber');
var filter = require('gulp-filter');
function buildLess() {
const fileFilter = filter(['**/*', '!**/mixins.less', '!**/variables.less']);
return gulp
.src('./public/less/*.less')
.pipe(fileFilter)
.pipe(plumber())
.pipe(less())
.pipe(gulp.dest('./public/css/'));
}
exports['build-less'] = buildLess;
function watchFiles() {
gulp.watch(['public/less/*.less'], buildLess);
}
exports['watch-files'] = watchFiles;
Overall, I'd go through Gulp's documentation. They recently updated their website, and updated their documentation along with it. Going through that might clear up some other questions you may be having.
I want to run an executable or a "non-javascript script" on the event add using gulp-watch(so server/developer-side, not user-side). From searching around I'm guessing I need to use ajax as I want to avoid php, but this seems a bit roundabout. Is it possible to do this using node.js instead?
Supposing that you use it with gulp:
var gulp = require('gulp');
var watch = require('gulp-watch');
var filter = require('gulp-filter');
var exec = require('gulp-exec');
function isAdded(file) {
return file.event === 'add';
}
var filterAdded = filter(isAdded);
gulp.task('default', function () {
return gulp.src('**/*.js')
.pipe(watch('**/*.js'))
.pipe(filterAdded)
.pipe(exec('ls -la'))
.pipe(filterAdded.restore());
});
I try to refactor my code. I know that if I have several expectations they should be isolate in 'it'. I try to understand how I can write instead this:
describe('my scenario should make', function () {
var config = browser.params;
var url = config.listOfReferencesUrl,
grid,
numberField;
it('test1', function () {
browser.get(url);
browser.executeScript("icms.go('WEB_INQ_PROC', 'InquiryList', null, 0)");
grid = psGrid(by.css("table[class='n-grid']"));
numberField = grid.getQuickFilter(1);
numberField.click().sendKeys("Hello!");
since('fail1').expect(numberField.getInputText()).toEqual("");
});
it('test2', function () {
since('fail2').expect(numberField.getInputText()).toEqual("Hello!");
});
});
Something like this:
describe('my scenario should make', function () {
var config = browser.params;
var url = config.listOfReferencesUrl,
grid,
numberField;
*********Make this part of code ONES before all tests in spec ****
browser.get(url);
browser.executeScript("icms.go('WEB_INQ_PROC', 'InquiryList', null, 0)");
grid = psGrid(by.css("table[class='n-grid']"));
numberField = grid.getQuickFilter(1);
numberField.click().sendKeys("Hello!");
*******************************************************************
it('test1', function () {
since('fail1').expect(numberField.getInputText()).toEqual("");
});
it('test2', function () {
since('fail2').expect(numberField.getInputText()).toEqual("Hello!");
});
});
Maybe somebody have an idea how I can do this?
To answer your question, if you want to run your code once before all tests then use beforeAll() function available in Jasmine 2. Here's a sample -
beforeAll(function(){
//Write your code here that you need to run once before all specs
});
You can use beforeEach() function available in Jasmine to run it each time before a test spec. Here's a sample -
beforeEach(function(){
//Write your code here that you need to run everytime before each spec
});
If you are facing issue in getting these functions to work, then update your plugins to latest version and then try running it. Also use the framework: 'jasmine2' in your conf.js file
Hope this helps.
I'm trying to integrate Gulp with Tape (https://github.com/substack/tape), the NodeJs test harness.
How can I do this? There doesn't seem to be an existing gulp plugin.
I've see this, but it looks really inelegant:
var shell = require('gulp-shell')
gulp.task('exec-tests', shell.task([
'tape test/* | faucet',
]));
gulp.task('autotest', ['exec-tests'], function() {
gulp.watch(['app/**/*.js', 'test/**/*.js'], ['exec-tests']);
});
I've tried this, which looks like it should work:
var tape = require('tape');
var spec = require('tap-spec');
gulp.task('test', function() {
return gulp.src(paths.serverTests, {
read: false
})
.pipe(tape.createStream())
.pipe(spec())
.pipe(process.stdout);
});
but I get a TypeError: Invalid non-string/buffer chunk error
Your "inelegant" answer is the best one. Not every problem can be best solved with streams, and using gulp just as a wrapper is not a sin.
Right, your task won't work because gulp streams are based on vinyl, a virtual file abstraction. I don't really think there's a good way of handling this in gulp, it seems like you should be using the tape API directly. I mean, you could put some gulp task sugar around it if you wish:
var test = require('tape');
var spec = require('tap-spec');
var path = require('path');
var gulp = require('gulp');
var glob = require('glob');
gulp.task('default', function () {
var stream = test.createStream()
.pipe(spec())
.pipe(process.stdout);
glob.sync('path/to/tests/**/*.js').forEach(function (file) {
require(path.resolve(file));
});
return stream;
});
Seems kind of messy to me; not only because we're not using any of gulp's streaming abstractions, but we're not even putting it into a way that could hook into a gulp pipeline afterwards. Furthermore, you can't get gulp's task finished message when using this code either. If anyone knows a way around that then, please, be my guest. :-)
I think I would prefer to use tape on the command line. But, if you want all of your build step tasks in your gulpfile this might be the route to go.
Just use code below and gulp tdd and having TDD :) with tape
const tapNotify = require('tap-notify');
const colorize = require('tap-colorize');
const tape = require('gulp-tape');
const through = require('through2');
gulp.task('test',function(){
process.stdout.write('\x1Bc');
const reporter = through.obj();
reporter.pipe(tapNotify({
passed: {title: 'ok', wait:false},
failed: {title: 'missing',wait:false}
}));
reporter
.pipe(colorize())
.pipe(process.stdout);
return gulp.src('test/**/*.js')
.pipe(tape({
outputStream: through.obj(),
reporter: reporter
}));
});
gulp.task('tdd', function() {
gulp.run('test');
gulp.watch(['app/scripts/**/*.js*', 'test/**/*.js'],['test']);
});
In a GitHub issue for tape jokeyrhyme mentions that gulp tasks can be Promises, and suggests a way to use that for running tape tests. Based upon that advice I've done this:
gulpfile.babel.js:
import glob from "glob";
gulp.task("test", () => {
let module = process.argv[process.argv.length - 1];
return new Promise(resolve => {
// Crude test for 'gulp test' vs. 'gulp test --module mod'
if (module !== "test") {
require(`./js/tape/${module}.js`);
resolve();
return;
}
glob.sync("./js/tape/*.js").forEach(f => require(f)));
resolve();
});
});
Looking at Ben's answer I suspect what I've done isn't very nice though, for one thing I've noticed that failing tests don't result in a non-zero exit code (although I've not tried Ben's approach to validate whether that does).
// npm i --save-dev gulp-tape
// npm i --save-dev faucet (just an example of using a TAP reporter)
import gulp from 'gulp';
import tape from 'gulp-tape';
import faucet from 'faucet';
gulp.task('test:js', () => {
return gulp.src('src/**/*test.js')
.pipe(tape({
reporter: faucet()
}));
});
Here's an example of my solution:
var gulp = require('gulp');
var tape = require('tape');
var File = require('vinyl');
var through = require('through2');
var exec = (require('child_process')).execSync;
function execShell(shcmd, opts) {
var out = '';
try {
out = exec(shcmd, opts);
} catch (e) {
if (e.error) throw e.error;
if (e.stdout) out = e.stdout.toString();
}
return out;
};
gulp.task('testreport', function(){
return gulp.src(
'testing/specs/tape_unit.js', {read: false}
).pipe(
through.obj(function(file, encoding, next) {
try{
// get tape's report
var tapout = execShell(
"./node_modules/.bin/tape " + file.path
);
// show the report in a console with tap-spec
execShell(
"./node_modules/.bin/tap-spec", { input: tapout, stdio: [null, 1, 2] }
);
// make a json report
var jsonout = execShell(
"./node_modules/.bin/tap-json", { input: tapout }
);
// do something with report's object
// or prepare it for something like Bamboo
var report = JSON.parse(jsonout.toString());
// continue the stream with the json report
next(null, new File({
path: 'spec_report.json',
contents: new Buffer(JSON.stringify(report, null, 2))
}));
}catch(err){ next(err) }
})
).pipe(
gulp.dest('testing/reports')
);
});
I have the following tasks as part of my gulp file:
gulp.task('jshint', function() {
return gulp.src(jsSrc)
.pipe(jshint())
.pipe(jshint.reporter('jshint-stylish'));
});
gulp.task('jscs', function() {
return gulp.src(jsSrc)
.pipe(jscs());
});
gulp.task('jslint', [ 'jshint', 'jscs' ]);
As I understand it, if I run jslint I'm not going to get the benefit of only reading from disc one. To do that, I would have to rewrite it to look like this:
gulp.task('jslint', function() {
return gulp.src(jsSrc)
.pipe(jshint())
.pipe(jscs())
.pipe(jshint.reporter('jshint-stylish'));
});
This is fine, except that it doesn't allow me to run the jshint task independently of the jscs if I wanted to.
Hence I'm wondering what best practice is around this? I was thinking that I could break things out into different functions and orchestrate things together, but that doesn't seem like the right approach.
A solution I have seen and used is:
var merge = require('merge-stream');
gulp.task('analyze', function() {
var jshint = analyzejshint(config.js);
var jscs = analyzejscs(config.css);
return merge(jshint, jscs);
});
function analyzejshint(sources, overrideRcFile) {
var jshintrcFile = overrideRcFile || './.jshintrc';
console.log('Running JSHint');
return gulp
.src(config.js)
.pipe(plug.jshint(jshintrcFile))
.pipe(plug.jshint.reporter('jshint-stylish'));
}
function analyzejscs(sources, overrideRcFile) {
var jscsrcFile = overrideRcFile || './.jscsrc';
console.log('Running JSCS');
return gulp
.src(config.js)
.pipe(jscs(jscsrcFile))
}
If you wanted to perform just one, you can just return the stream from one of the functions instead.