I am javascript+node beginner and also relatively new to asynchronous programming style. I am comfortable with Ruby and Rails and now trying to teach myself node.
I am working on a node app where I need to fetch data from Facebook for which I am using the 'facebook-api' node package.
I am using a BDD approach ( newcomer here as well, never used rspec much in ruby) with mocha + should.js.
Here is some of the early code I have written:
lib/facebook_adapter.js
var raw = require('facebook-api').raw;
function getFacebookData(facebookpage,callback)
{
raw("GET",facebookpage,[],function(error,data){
if (error)
{
conosle.log(error);
}
else
{
var facebook_data = {};
facebook_data.likes = data.likes;
facebook_data.talking_about = data.talking_about;
}
callback(facebook_data);
});
}
module.exports = {
'getFacebookData' : getFacebookData
};
test/facebook.test.js
'use strict';
var assert = require('assert')
,should = require('should')
,facebook_adapter = require('../lib/facebook_adapter');
describe('FacebookAdapter',function(){
it('should fetch the like and followcount for a brand name from Graph API',function(done){
facebook_adapter.getFacebookData('Edelman', function(facebook_data){
for ( var prop in facebook_data)
{
console.log('meoww');
facebook_data[prop].should.be.a('number');
}
done();
});
});
});
To execute mocha test, I have a makefile in the root directory of the express application. Here is the content:
test:
#./node_modules/.bin/mocha -u tdd
.PHONY: test
Now, when executing the tests, I always end up with the error:
․․․meoww
meoww
․․
✖ 2 of 4 tests failed:
1) FacebookAdapter should fetch the like and followcount for a brand name from Graph API:
Error: global leaks detected: data_array, parsed
at Runner.checkGlobals (/Users/myth/Learn/Code/Projects/socialindex/node_modules/mocha/lib/runner.js:167:21)
at Runner.<anonymous> (/Users/myth/Learn/Code/Projects/socialindex/node_modules/mocha/lib/runner.js:58:44)
at Runner.EventEmitter.emit (events.js:126:20)
at Runner.uncaught (/Users/myth/Learn/Code/Projects/socialindex/node_modules/mocha/lib/runner.js:466:10)
at process.Runner.run (/Users/myth/Learn/Code/Projects/socialindex/node_modules/mocha/lib/runner.js:508:10)
at process.EventEmitter.emit (events.js:126:20)
2) FacebookAdapter should fetch the like and followcount for a brand name from Graph API:
Error: global leaks detected: data_array, parsed
at Runner.checkGlobals (/Users/myth/Learn/Code/Projects/socialindex/node_modules/mocha/lib/runner.js:167:21)
at Runner.<anonymous> (/Users/myth/Learn/Code/Projects/socialindex/node_modules/mocha/lib/runner.js:58:44)
at Runner.EventEmitter.emit (events.js:126:20)
at Runner.uncaught (/Users/myth/Learn/Code/Projects/socialindex/node_modules/mocha/lib/runner.js:466:10)
at process.Runner.run (/Users/myth/Learn/Code/Projects/socialindex/node_modules/mocha/lib/runner.js:508:10)
at process.EventEmitter.emit (events.js:126:20)
Why is the test executing twice? I dont also seem to be misusing any globals as well. Why the error?
Related
I am creating a test suite that will be run by mocha. In the test, I plan on using should and chai at the very least. I am testing JSON objects. I want mocha to be silent about successful tests and I want to control what the errors look like at the end of the run. Right now, there is a lot of red text describing the JSON object and other information. What I want is to override the output.
Here is an example test for an element in the JSON object which I would import from testData.
var should = require("should");
var chai = require("chai");
var expect = chai.expect;
const testData = require("./testData");
for (t of testData.data) {
describe("This will fail", function() {
it("Should have a zipperNut",function(done) {
t.should.have.property('zipperNut');
done();
});
});
}
What I want is to see just this:
$ mocha testSuite.js
zipperNut
$
And so on for all the tests I want to run. Can I do this? Do I need to use a different library?
Mocha's output is determined by something called a "default reporter". If you want to change the output you can specify a different reporter, which is presumably available through npm or similar. To specify a new custom reporter you do this:
$ mocha --reporter my-reporter.js
Where my-reporter.js is the file containing my "reporter". For me, I just want the plain name of the failing tests, so my reporter would look like:
'use strict';
const Mocha = require('mocha');
const {
EVENT_RUN_END,
EVENT_TEST_FAIL,
} = Mocha.Runner.constants;
class MyReporter {
constructor(runner) {
const stats = runner.stats;
runner
.on(EVENT_TEST_FAIL, (test, err) => {
console.log(
`${test.title}`
);
})
.once(EVENT_RUN_END, () => {
console.log(`end: ${stats.passes}/${stats.passes + stats.failures} ok`);
});
}
}
module.exports = MyReporter;
Documentation here:
https://mochajs.org/api/tutorial-custom-reporter.html
I am working on building multiple languages when running a gradle command for an angular application.
Below is the code which is used to build all the localized files.
The buildAllLanguageVersion() method is called to build the language one by one by iterating over all the available build languages.
function buildAllLanguageVersion() {
return new Promise(async (accept, reject) => {
const doneLanguages = [];
const applicationBase = "APPNAME";
for (let language of buildLanguages) {
const ret = await buildingLanguage(language);
doneLanguages.push(ret);
}
accept(doneLanguages);
});
}
function buildingLanguage(buildLanguage) {
return new Promise(accept => {
console.log("Language building" + buildLanguage);
const languagePath = path.resolve(`./src/i18n/messages.${buildLanguage}.xlf`);
const languageFile = fs.existsSync(languagePath) ? buildLanguage : "en";
if (languageFile !== buildLanguage && !fs.existsSync(languagePath)) {
console.error(
"Language file does not exist." +
buildLanguage
);
}
exec.exec(`${folder} build --configuration=dynamic`, (error, stdout, stderror) => {
if (error) {
throw "Build failed: " + error;
}
accept(buildLanguage);
});
});
}
The above code is working fine when I have to build a language in a sequential order. And for a language to build it took almost 3-5 minutes. I am using 7 different languages for now in the application.
My question is how I can call the method in parallel so that I can reduce the build time.
So far i have tried Promise.all() in the method buildAllLanguageVersion() to call the method buildingLanguage() in parallel, but that didn't help. The methods are getting called at a time(in parallel) but the build is getting failed with below error.
14:31:17 D:\ls\workspace\Generic_commit\APP\app-name\tools\build-all.js:129
14:31:17 throw "Build failed: " + error;
14:31:17 ^
14:31:17 Build failed: Error: Command failed: D:\ls\workspace\Generic_commit\APP\app-name\node_modules\.bin\ng.cmd build --configuration=dynamic
14:31:17
14:31:17 ERROR in ngcc is already running at process with id 5252.
14:31:17 If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;
14:31:17 See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.
14:31:17 (If you are sure no ngcc process is running then you should delete the lock-file at D:/ls/workspace/Generic_commit/APP/app-name/node_modules/#angular/compiler-cli/ngcc/_ngcc_lock_file_.)
I tried removing the _ngcc_lock_file_ but that didn't help.
I'm implement cucumber on my framework working with protractor,
this is the tree of my framework
- FM_cucumber
- features
- steps
* my_steps.js
* login.feature
- node_modules
- test
* conf.js
* package.json
Inside of my my_steps.js i have this
var steps = function(){
this.Given(/^Open google$/, function () {
this.browser.get('http://www.google.com').then(function(result){
callback(result);
});
});
};
module.exports = steps;
So to execute this feature i'm using the command cucumber.js of course i'm in the folder where I have my FM_cucumber but after I execute the cucumber.js is displaying this typeError
TypeError: Cannot read property 'get' of undefined
at World.<anonymous> (/Users/myname/Documents/FM_cucumber/features/steps/my_steps.js:4:19)
Is anybody se something wrong in my code?
I think this is because you are binding the protractor browser-object to the this(World) of CucumberJS. Protractor can 'live' on it's own in combination with CucumberJS. You only use CucumberJS to:
create featurefiles
create the binding between the featurefiles and the step implementation (with the RegEx)
use it for Hooks / Reporting
The code within the step implementation can be native Protractor syntax. So for you problem, change this
var steps = function(){
this.Given(/^Open google$/, function () {
this.browser.get('http://www.google.com').then(function(result){
callback(result);
});
});
};
module.exports = steps;
into this
var steps = function(){
this.Given(/^Open google$/, function () {
browser.get('http://www.google.com')
.then(function(result){
callback(result);
});
});
};
module.exports = steps;
Be aware of the fact that the browser.get() doesn't have a result, see here
Hope it helps
I have a module where I load a mustache template file. I would like to write a unit test for this. I am trying to use mocha, chai and rewire.
Here is my module.js:
var winston = require('winston');
var fs = require('fs');
var config = require('./config.js');
exports.logger = new winston.Logger({
transports: [
new winston.transports.File(config.logger_config.file_transport),
new winston.transports.Console(config.logger_config.console_transport)
],
exitOnError: false
});
exports.readTemplateFile = function(templateFile, callback) {
fs.readFile(config.base_directory + templateFile + '.tpl.xml', 'utf8', function (err, data) {
if (err) {
logger.error('Could not read template ' + templateFile + ': ' + err);
}
callback(data);
});
};
In the callback function I use mustache to do something with the template.
What is the best way to test this?
Maybe I will have to rewire the fs.readFile? As the file won't be there when the test will be executed. The Winston logger is also an interesting part I guess, not sure if it will be initialized if I import this within a mocha test. My first test shows the logger is undefined.
One of the most important unit testing principle is testing very small piece of code. To achieve that you should definitely mock or stub calls to functions that not belong to testing code (readFile and logger.error in this case). For provided code you can make three test cases:
calling readFile with proper arguments
calling error if err is present
calling callback function with proper argument
Your callback function should be tested outside this code, for e.g. by providing fake data as parameter:
define('Some test', () => {
it('should return true', () => {
expect(callbackFunction('fakeData').to.be.ok);
});
});
The project is: Backbone + Require + Underscore + Grunt + Grunt-Contrib-Jasmine + Grunt-Lib-PhantomJS
So two serious problems I've been battling. I know that phantomjs is running properly etc. as I get tons of runtime errors if I include my app src files. I've even ordered the deps properly such that Backbone does not barf with _ not being defined etc.
1) When I include my application src, I get the error can't find variable: define for all my source files. I've tried putting requirements into src[] isntead of vendor[] and even tried loading a RequireJSConfig.js that has the deps in it.
2) Here's the cruncher: I'm pretty certain I'm pointing at my spec files properly. If I just point to one test, it still says No Specs Executed. Is there a configuration error? In my case, I just point at my UserModelUnitTest.js, which is very simple. It does not execute. I'm going absolutely nuts!
The Spec (UserModelUnitTest.js):
describe('User Model Unit Tests', function() {
var USER_MODEL,
USER_CLASS,
JSON_OBJ;
beforeEach(function() {
USER_CLASS = testr('models/user/User', {});
});
afterEach(function() {
USER_MODEL = null;
USER_CLASS = null;
JSON_OBJ = null;
});
describe('Given a json object', function() {
it('should create a valid User', function() {
JSON_OBJ = {"databaseId": 123456,"loginName": "god","firstName": "Jesus","lastName": "Christ","phone": "666-666-6666","email": "satan#hell.org","isoCountryCode": "US","languageCode": "en","roles" : ["SALES_REP"]};
USER_MODEL = new USER_CLASS(JSON_OBJ, { parse: true });
expect(USER_MODEL).not.toBe(null);
});
// etc...
});
})
Here's my dir structure
/project
- src
- main
+ test
+ js
+unit
UserModelUnitTest.js
Here's my Gruntfile / Jasmine config
jasmine: {
test:{
vendor:[
'src/main/resources/js/lib-clean/jquery-2.1.0.js',
'src/main/resources/js/lib-clean/require-2.1.1.full.js',
'src/main/resources/js/lib-clean/underscore-1.5.2.min.js',
'src/main/resources/js/lib-clean/backbone-1.1.2.min.js'
],
src : [
// these all error like crazy. Can't find variable 'define' etc.
// 'src/main/**/*.js',
// 'src/main/**/**/*.js',
//'src/test/RequireJSConfig.js'
],
helpers : [
'src/test/js/helpers/dependencyHelper.js',
'src/test/js/helpers/errorHelper.js',
'src/test/js/helpers/requesetHelper.js',
'src/test/lib/testr.js',
// jasmine.js + jasmine-html.js etc
'src/test/lib/*.js',
// stubs
'src/test/js/stubs/*.js'
],
specs : [
'src/test/js/unit/UserModelUnitTest.js'
],
//specs : 'src/test/js/unit-headless.html',
timeout : 10000,
phantomjs : {
'ignore-ssl-errors' : true
}
}
},
I just had the same problem. You need to define vendor, specs, helpers within the options option.
jasmine: {
src: 'path/to/src',
options: {
vendor: 'path/to/vendor',
specs: 'path/to/specs',
helpers: 'path/to/specs'
// etc.
}
}
sometimes happen because: you did not created the spec folder and the spec file, also when you create the spec file you need create the test inside or will not run.