I have just discovered the gulp-prompt task. While it makes it easy to prompt the user in different ways, the examples don't hint at how to make use of the user's input. For instance I would like to offer two setups (e.g. CDN-hosted or local assets) to the user and run my tasks conditionally. How can you do that in Gulp? This could save me from looking into a Yeoman generator.
Exemple
...
...
var inject = require('gulp-inject');
var cdnizer = require('gulp-cdnizer');
gulp.task('mytask', function(){
var target = gulp.src('./src/index.html');
return gulp.src('*')
.pipe(prompt.prompt({
type: 'input',
name: 'type',
message: 'What you like to do? [cdn/assets]'
}, function(res){
var sources;
if(res.type === 'cdn'){
sources = ...
target.pipe(inject(sources))
.pipe(gulp.dest('./src'));
}else{
target.pipe(cdnizer({...});
}
}));
});
This is another implementation. It will ask you to choose the task with a keyboard
gulp.task('default', function() {
var taskNames = [];
for (var taskName in gulp.tasks) {
if (gulp.tasks.hasOwnProperty(taskName)) {
taskNames.push(taskName);
}
}
return gulp.src('*').pipe(
prompt.prompt({
type: 'checkbox',
name: 'tasks',
message: 'Choose task name',
choices: taskNames
}, function(res){
//value is in res.task (the name option gives the key)
console.log(res);
res.tasks.forEach(function(taskName){
console.log(taskName);
gulp.tasks[taskName].fn();
});
}));
});
Related
I'm trying to build a simple yeoman task that copies a template directory into the destination directory where the user is running the command. The prompt method is working but nothing is being written or copied. Any idea where I'm going wrong here?
'use strict';
//Require dependencies
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');
module.exports = class extends yeoman {
//Ask for user input
prompting() {
var done = this.async();
this.prompt({
type: 'input',
name: 'name',
message: 'Your project name',
//Defaults to the project's folder name if the input is skipped
default: this.appname
}, function(answers) {
this.props = answers
this.log(answers.name);
done();
}.bind(this));
}
//Writing Logic here
writing() {
this.fs.copyTpl(
this.templatePath('testfile'),
this.destinationPath('testfile')
);
}
};
The prompt method doesn't take a callback since release 1.0
Instead you want this.prompt([...]).then(callback)
I am asking the user for a directory name, and then if the directory exists I want to ask them if they want to archive it. However I am not sure what function I can use inside Yeoman to achieve this. Here is my code.
prompting: function () {
return this.prompt([{
type: 'input',
name: 'project_directory',
message: 'What is the project directory name?'
}, {
type: 'confirm',
name: 'archive',
message: 'That project already exists. Do you want to archive it?',
when: function (answers) {
var destDir = 'project/' + answers.project_directory.replace(/[^0-9a-zA-Z\-.]/g, "").toLowerCase();
var fso = new ActiveXObject("Scripting.FileSystemObject");
//Return true if the folder exists
return (fso.FolderExists(destDir));
}
}]).then(function (answers) {
}.bind(this));
}
Yeoman doesn't provide any built-in methods to verify if a file or a directory exists.
But Yeoman is just Node.js, it's just JavaScript.
So you actually want to ask how to detect if a directory exist with Node.
If you inherited from Generator, you have this.fs object that has exists() method.
module.exports = class extends Generator {
/* ... */
default() {
this.alreadyCopied = this.fs.exists(this.destination('myfile.txt'));
}
}
Actually, as mentioned by Simon Boudrias, Yeoman doesn't provide a built-in method for it, but you can do the following:
var Generator = require('yeoman-generator');
var fs = require('fs');
module.exports = class extends Generator{
checkIfFolderExists(){
fs.stat('YourDirectoryHere'), function(error, stats){
if(stats!=undefined && stats.isDirectory()){
// your directory already exists.
}else{
// create your directory.
}
}) ;
}
}
I am trying to work on a custom jasmine reporter and get a list of all the failed specs in the specDone function:
specDone: function(result) {
if(result.status == 'failed') {
failedExpectations.push(result.fullName);
console.log(failedExpectations);
}
}
where failedExpectations will store an entire list of the failed specs and i need to access this in the afterLaunch function in the protractor config file. But due to the fact that the config file loads everytime a new spec runs it basically gets overwritten and scoping is such that I cannot access it in the afterLaunch function, that is where I am making the call to the slack api. Is there a way to achieve this?
This is what i have it based on : http://jasmine.github.io/2.1/custom_reporter.html
I think the best way is to post the results asynchronously after each spec (*or every "it" and "describe") using #slack/web-api. This way you don't have to worry about overwriting. Basically you "collect" all the results during the test run and send it before the next suite starts.
Keep in mind all of this should be done as a class.
First you prepare your you '#slack/web-api', so install it (https://www.npmjs.com/package/#slack/web-api).
npm i -D '#slack/web-api'
Then import it in your reporter:
import { WebClient } from '#slack/web-api';
And initialize it with your token. (https://slack.com/intl/en-pl/help/articles/215770388-Create-and-regenerate-API-tokens):
this.channel = yourSlackChannel;
this.slackApp = new WebClient(yourAuthToken);
Don't forget to invite your slack app to the channel.
Then prepare your result "interface" according to your needs and possibilities. For example:
this.results = {
title: '',
status: '',
color: '',
successTests: [],
fails: [],
};
Then prepare a method / function for posting your results:
postResultOnSlack = (res) => {
try {
this.slackApp.chat.postMessage({
text: `Suit name: ${res.title}`,
icon_emoji: ':clipboard:',
attachments: [
{
color: res.color,
fields: [
{
title: 'Successful tests:',
value: ` ${res.successTests}`,
short: false
},
{
title: 'Failed tests:',
value: ` ${res.fails}`,
short: false
},
]
}
],
channel: this.channel
});
console.log('Message posted!');
} catch (error) {
console.log(error);
}
When you got all of this ready it's time to "collect" your results.
So on every 'suitStart' remember to "clear" the results:
suiteStarted(result) {
this.results.title = result.fullName;
this.results.status = '';
this.results.color = '';
this.results.successTests = [];
this.results.fails = [];
}
Then collect success and failed tests:
onSpecDone(result) {
this.results.status = result.status
// here you can push result messages or whole stack or do both:
this.results.successTests.push(`${test.passedExpectations}`);
for(var i = 0; i < result.failedExpectations.length; i++) {
this.results.fails.push(test.failedExpectations[i].message);
}
// I'm not sure what is the type of status but I guess it's like this:
result.status==1 ? this.results.color = #DC143C : this.results.color = #048a04;
}
And finally send them:
suiteDone() {
this.postResultOnSlack(this.results);
}
NOTE: It is just a draft based on reporter of mine. I just wanted to show you the flow. I was looking at Jasmine custom reporter but this was based on WDIO custom reporter based on 'spec reporter'. They are all very similar but you probably have to adjust it. The main point is to collect the results during the test and send them after each part of test run.
*You can look up this explanation: https://webdriver.io/docs/customreporter.html
I highly recommend this framework, you can use it with Jasmine on top.
i am fiddleing around with yeoman and want to write my first generator for a simple html5 boilerplate. My problem is, that the two functions in my generator work well on their own but not together and i don't know why. I checked some generators from the yeoman page, but i don't see what i am doing wrong. I hope you can help me. This is my code:
'use strict';
var generators = require('yeoman-generator');
var yosay = require('yosay');
module.exports = generators.Base.extend({
initializing: function(){
this.log(yosay("\'Allo \'allo I will create your HTML5 Boilerplate..."));
},
prompting: function() {
var done = this.async();
this.prompt({
type: 'input',
name: 'name',
message: 'Your project name',
//Defaults to the project's folder name if the input is skipped
default: this.appname
}, function(answers) {
this.props = answers
this.log(answers.name);
done();
}.bind(this));
},
writing: function(){
this.fs.copyTpl(
this.templatePath('_page/_index.html'),
this.destinationPath('index.html'),
{ title: "answers.name" }
);
},
});
Thanks in advance!
Try using the Promises version of the prompting function, as shown on yeoman.io.
Example:
prompting: function() {
return this.prompt({
type: 'input',
name: 'name',
message: 'Your project name',
//Defaults to the project's folder name if the input is skipped
default: this.appname
}).then(function(answers) {
this.props = answers
this.log(answers.name);
}.bind(this));
},
Changes:
add return before this.prompt().
change this.prompt(prompts, callback); to this.prompt(prompts).then(callback);
I'm trying that when the user enters a command in the Web console, I get this command in the script of my addon before to be executed?
For example, when the user enters the command line "screenshot --fullpage" this command to be sent to a function of the script of my addon before being executed.
I did some research but I only found an event on the opening of the web console.
https://developer.mozilla.org/en-US/docs/Observer_Notifications#Developer_tools
Solution posted here - https://discourse.mozilla-community.org/t/firefox-addon-event-on-a-specific-command-line/6028/10?u=noitidart
Alrighty here we go, this works:
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
var tmp = {};
Cu.import("resource://devtools/client/shared/DeveloperToolbar.jsm", tmp);
var gcliInit = require('devtools/shared/gcli/commands/index');
var { TargetFactory } = require("devtools/client/framework/target");
var a = new tmp.DeveloperToolbar(window, document.getElementById("developer-toolbar"));
var sysTarget= TargetFactory.forTab(a._chromeWindow.gBrowser.selectedTab);
gcliInit.getSystem(sysTarget).then(
system => {
console.log('system:',system);
system.addItems([{
name: 'greet',
description: 'Show a greeting',
params: [{
name: 'name',
type: 'string',
description: 'The name to greet'
}],
returnType: 'string',
exec: function(args, context) {
return 'Hello, ' + args.name;
}
}]);
},
y => console.error('y:',y)
);
Note, the path changes in Firefox 45. So this code is for Fx45+ prior to this you would use resource://gre/modules/devtools/Loader.jsm instead of resource://devtools/shared/Loader.jsm.
TargetFactor was the key component I was missing, it's important, it's got these methods:
Object { forTab: function (), forRemoteTab: function (), forWorker: function (), isKnownTab: function () }