How to separate commands into files Vorpal.js - vorpal.js

I have many commands and each of them is long.
For example, I have:
create
read
update
delete
I want to put them in separate files:
./commands/create.js
./commands/read.js
./commands/update.js
./commands/delete.js
and I want to require them in app.js:
require('./commands/create.js');
// ...
so I can:
node app.js create HelloWorld
How can I achieve this?

I would do something like this:
// create.js
function create(args, cb) {
// ... your logic
}
module.exports = function (vorpal) {
vorpal
.command('create')
.action(create);
}
Then in your main file, you can do:
// main.js
const vorpal = Vorpal();
vorpal
.use(require('./create.js'))
.use(require('./read.js'))
.show();
More on this here.

Related

Adding to module.exports on cypress/plugins/index.js file Cypress

I am struggling to add a second module.export cypress/plugin/index.js
My Current cypress/plugin/index.js file look like this
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* #type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
const { on } = require('events');
const fs = require('fs-extra');
const path = require('path');
function getConfigurationByFile(file) {
const pathToConfigFile = path.resolve('config', `${file}.json`);
return fs.readJson(pathToConfigFile);
}
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
const file = config.env.configFile || 'qa';
return getConfigurationByFile(file);
};
I want to add the following to cypress/plugin/index.js:
require('cypress-grep/src/plugin')(config)
// make sure to return the config object
// as it might have been modified by the plugin
return config
I believe that you can pass in the config from your function to your require and then return that new config.
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
const file = config.env.configFile || 'qa';
let newConfig = getConfigurationByFile(file);
require('cypress-grep/src/plugin')(newConfig);
return newConfig;
};
Since your getConfigurationByFile() function returns a JSON Object like the original config, and the cypress-grep plugin takes in a JSON Object, you can probably just add the resolved JSON from getConfigurationByFile instead of the standard one provided by config.
If you have your plugins set up correctly, then it may be the environment variables passed via command line. Here is an example repo of using cypress-grep and configuration files.

Using pageBase with nightwatch.js

I'm trying to create an end-2-end test suite using nightwatch.js
I've looked around a bit and haven't really figured out how to use a pageBase, like is usually used when implementing POM.
I'm using the page_object that is built in to nightwatch, but can't seem to get it to use a pageBase.
Here is the code example.
To simplify things, let's say I have a common.js file, and a test.js file
I want test.js to inherit all of common.js commands and elements and implement some commands and elements of it's own, but I'm struggling with the syntax.
this is the common.js file
let commonCommands = {
clickOnMe: function () {
return this.waitForElementVisible('#someElement', 2000)
}
};
module.exports = {
commands: [commonCommands],
elements: {
someElement: '#elementId'
},
};
this is the test.js file
const common = require('./common');
let testCommands = {
doStuffFromTest: function () {
return this;
}
};
module.exports = {
url: function () {
return this.api.launch_url ;
},
commands: common.commands,
elements: common.elements
};
How can I add commands and elements to the test.js ?
You generally don't want to access those commands from your test, but rather from your other page objects. Since that's where all of your commands will be happening, common actions like clicking on an element or checking if something is present will be done at the page object level.

Ecma 6 Promise complete

I am experimenting with Promise from ES6, but I can't find any alternative to complete as in jQuery ajax. I need to execute function after all the registered handlers with "then".
Thanks!
As mentioned by Bergi, what you want is the disposer pattern. Your central conception of a promise appears to be a bit off, and I think that is making this harder for you to reason about. When you call .then, you are not conceptually "attaching a handler", you are creating a new promise that will by definition resolve after all of its .then handlers have run.
Given your central issue based on code like this:
// a.js
module.exports = function(){
// Where 'Promise.resolve()' is a stand in for your ajax.
return Promise.resolve()
.then(function(){
// Want this to run after 'B'.
});
}
// b.js
var makePromise = require('./a');
module.exports = function specialMakePromise(){
return makePromise().then(function(){
// Should run first.
});
}
They will always run in the wrong order, because by definition, the .then handler from a.js must run and complete before the .then handler from b.js.
One way to approach this problem would instead to structure your code like this:
// a.js
module.exports = function(callback){
return Promise.resolve()
.then(callback)
.then(function(){
// Want this to run after 'B'.
});
}
// b.js
var makePromise = require('./a');
module.exports = function specialMakePromise(){
return makePromise(function(){
// Should run first.
});
}

How to do test coverage with blanket and mocha in sailsjs

I have a Sails project with a test/ folder containing all my mocha tests and want to create a test coverage report using following command:
mocha --require blanket --reporter html-cov > coverage.html
The blanket configuration inside my package.json looks following:
"blanket": {
"pattern": ["lib", "api", "config"],
"data-cover-never": "node_modules",
"data-cover-reporter-options": {
"shortnames": true
}
}
I included both Sails folders api/ and config/ as they probably contain testable code and a folder lib/ containing most of my application's logic.
Sadly the blanket coverage module only covers files that are directly included in my test files. Since Sails loads most of my files in api/ and config/ dynamically they don't show up in my coverage reports.
Any ideas in how to integrate the Sails framework with blanket?
I am unfamilair with Sails but I had the same problem using Blanket.js and posted a comment with a work-around on the Blanket.js bugtracker, here it is:
https://github.com/alex-seville/blanket/issues/361#issuecomment-34002054
The workaround I suggested there felt very much like a hack. I eventually abandoned Blanket in favor of Istanbul: https://github.com/gotwarlost/istanbul
Istanbul gives you both more metrics (statement, line, function and branch coverage) and outputs an excellent bunch of .html files allowing you to analyze how to improve your code.
Blanket.js appears not to be maintained very well given the 79+ open issues currently.
If you do want to stick to blanket.js you can follow the suggestion I posted on the Blanket.js bug tracker and try to include all files within the test run by recursively looping through all relevant code directories. The code I used to do that at the time was as the following (I would definitely refactor this, but it shows the intent):
'use strict';
/**
* This file is loaded by blanket.js automatically before it instruments code to generate a code coverage report.
*/
var fs = require('fs');
var log = require('winston');
var packageJson = require('./package.json');
// For some reason the blanket config in package.json does not work automatically, set the settings manually instead
require('blanket')({
// Only files that match this pattern will be instrumented
pattern: packageJson.config.blanket.pattern
});
/**
* Walks through a directory structure recursively and executes a specified action on each file.
* #param dir {(string|string[])} The directory path or paths.
* #param action {function} The function that will be executed on any files found.
* The function expects two parameters, the first is an error object, the second the file path.
*/
function walkDir(dir, action) {
// Assert that action is a function
if (typeof action !== "function") {
action = function (error, file) {
};
}
if (Array.isArray(dir)) {
// If dir is an array loop through all elements
for (var i = 0; i < dir.length; i++) {
walkDir(dir[i], action);
}
} else {
// Make sure dir is relative to the current directory
if (dir.charAt(0) !== '.') {
dir = '.' + dir;
}
// Read the directory
fs.readdir(dir, function (err, list) {
// Return the error if something went wrong
if (err) return action(err);
// For every file in the list, check if it is a directory or file.
// When it is a directory, recursively loop through that directory as well.
// When it is a file, perform action on file.
list.forEach(function (file) {
var path = dir + "/" + file;
fs.stat(path, function (err, stat) {
if (stat && stat.isDirectory()) {
walkDir(path, action);
} else {
action(null, path);
}
});
});
});
}
};
// Loop through all paths in the blanket pattern
walkDir(packageJson.config.blanket.pattern, function (err, path) {
if (err) {
log.error(err);
return;
}
log.error('Including ' + path + ' for blanket.js code coverage');
require(path);
});
My advice would be to drop Blanket.js for something else.

Is there a way to add a Jasmine matcher to the whole environment

There are plenty of documents that show how to add a matcher to a Jasmine spec (here, for example).
Has anyone found a way to add matchers to the whole environment; I'm wanting to create a set of useful matchers to be called by any and all tests, without copypasta all over my specs.
Currently working to reverse engineer the source, but would prefer a tried and true method, if one exists.
Sure, you just call beforeEach() without any spec scoping at all, and add matchers there.
This would globally add a toBeOfType matcher.
beforeEach(function() {
var matchers = {
toBeOfType: function(typeString) {
return typeof this.actual == typeString;
}
};
this.addMatchers(matchers);
});
describe('Thing', function() {
// matchers available here.
});
I've made a file named spec_helper.js full of things like custom matchers that I just need to load onto the page before I run the rest of the spec suite.
Here's one for jasmine 2.0+:
beforeEach(function(){
jasmine.addMatchers({
toEqualData: function() {
return {
compare: function(actual, expected) {
return { pass: angular.equals(actual, expected) };
}
};
}
});
});
Note that this uses angular's angular.equals.
Edit: I didn't know it was an internal implementation that may be subjected to change. Use at your own risk.
jasmine.Expectation.addCoreMatchers(matchers)
Based on previous answers, I created the following setup for angular-cli. I also need an external module in my matcher (in this case moment.js)
Note In this example I added an equalityTester, but it should work with a customer matcher
Create a file src/spec_helper.ts with the following contents:
// Import module
import { Moment } from 'moment';
export function initSpecHelper() {
beforeEach(() => {
// Add your matcher
jasmine.addCustomEqualityTester((a: Moment, b: Moment) => {
if (typeof a.isSame === 'function') {
return a.isSame(b);
}
});
});
}
Then, in src/test.ts import the initSpecHelper() function add execute it. I placed it before Angular's TestBed init, wich seems to work just fine.
import { initSpecHelper } from './spec_helper';
//...
// Prevent Karma from running prematurely.
__karma__.loaded = function () {};
// Init our own spec helper
initSpecHelper();
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
//...

Resources