I'm trying to execute some tests with Pact library and I'm getting some errors. Here is the test configuration:
const path = require('path');
const Pact = require('pact');
const expect = require('expect.js');
const config = require('../../../src/server/config');
const service = require('../../../src/routes/interactions/interactions.service');
describe('#component/interactions tests', () => {
const url = 'http://localhost';
const port = 8989;
const provider = Pact({
port: port,
log: path.resolve(process.cwd(), 'test/component/interactions/log/interactions-pact.log'),
dir: path.resolve(process.cwd(), 'test/component/interactions/pacts'),
spec: 2,
consumer: 'cx_issue',
provider: 'interaction',
// logLevel: 'WARN'
});
config.settingsToExport.INTERACTION_URL = `${url}:${port}`;
before(done => {
provider.setup()
.then(() => {
done();
})
.catch(err => {
done(err);
});
});
after(done => {
provider.finalize()
.then(() => {
done();
})
.catch(err => {
done(err);
});
});
describe('#createInteraction', () => {
before(done => {
const INTERACTION_BODY = {
contact: 'contact1'
};
const TERM = {
generate: '0dae5b93-9451-4b08-b7bb-f0b944fbcdf2',
matcher: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
};
const pactInteractionCreate = {
state: 'Creates a new interaction',
uponReceiving: 'a new interaction is created successfully',
withRequest: {
method: 'POST',
path: '/interactions',
body: INTERACTION_BODY
},
willRespondWith: {
status: 201,
body: {
id: Pact.Matchers.term(TERM)
}
}
};
const promises = [
provider.addInteraction(pactInteractionCreate)
];
Promise.all(promises)
.then(() => {
done();
});
});
it('/api/interactions POST', done => {
const interaction = {
contact: 'The xx'
};
service.createInteraction(interaction)
.then(response => {
expect(response.id).to.be.equal(TERM.generate);
done();
})
.catch(done);
});
});
});
This is my package.json file content, with all dependencies I've installed:
{
"name": "issueAPI",
"version": "1.0.0",
"private": true,
"main": "./src/index.js",
"scripts": {
"dev": "nodemon -e js ./src/index.js",
"start": "node ./src/index.js",
"linter": "node ./node_modules/eslint/bin/eslint.js ./src",
"test": "mocha test",
"test-component": "mocha test/component",
"install-test-build": "npm install && npm test && npm run linter",
"test-build": "npm test && npm run linter"
},
"jshintConfig": {
"esversion": 6
},
"dependencies": {
"ajv": "^4.11.3",
"body-parser": "^1.17.2",
"express": "^4.15.3",
"express-winston": "^2.4.0",
"request": "^2.81.0",
"winston": "^2.3.1",
"yamljs": "^0.2.9"
},
"devDependencies": {
"#pact-foundation/pact-node": "^4.8.3",
"dotenv": "^4.0.0",
"eslint": "^4.2.0",
"eslint-config-node": "^1.6.0",
"expect.js": "^0.3.1",
"mocha": "^3.2.0",
"nodemon": "^1.11.0",
"pact": "^2.3.3",
"sinon": "^2.3.8",
"supertest": "^3.0.0"
}
}
And this is the error I get:
Basically, right now I don't mind at all if the tests are well or not. The main problem right now is that the pact mock server is not being started.
The weird thing here is that I have other project where the pact tests run properly. I've moved the service I want to test from the project where is failing to the one which executes those tests fine, and it is working (at least the pact mock server is launched). The dependencies in this other project are almost the same as the problemathic project:
"dependencies": {
"ajv": "^4.11.3",
"body-parser": "^1.16.1",
"dotenv": "^4.0.0",
"express": "^4.14.0",
"jsonwebtoken": "^7.4.1",
"jwt-simple": "^0.5.1",
"morgan": "^1.8.1",
"mustache-express": "^1.2.4",
"node-env-file": "^0.1.8",
"request": "^2.79.0",
"when": "^3.7.8"
},
"devDependencies": {
"#pact-foundation/pact-node": "^4.8.3",
"eslint": "^3.17.1",
"eslint-config-node": "^1.6.0",
"expect.js": "^0.3.1",
"mocha": "^3.2.0",
"nodemon": "^1.11.0",
"pact": "^2.3.3",
"sinon": "^1.17.7",
"supertest": "^3.0.0",
"nock": "^9.0.13"
}
What's going on with this situation?
EDIT: I've launched the pact tests with DEBUG flag and this is the log generated:
It looks like the server is unable to start up correctly, judging by the exit code of 1. This could be a port conflict on port 8989, so that's worth checking.
It could be related to https://github.com/pact-foundation/pact-js/issues/64 (Windows file paths limited in length).
Could you please enable DEBUG logging with logLevel: 'DEBUG' and note what it outputs, and also share any *.log file. It could be an argument is not being correctly formatted when starting the server.
As you note, it is unable to start the underlying Ruby process so we need to get to the bottom of that.
Finally, after #Matthew Fellows answer and after reading his link to https://github.com/pact-foundation/pact-js/issues/64, I moved my project to a shorter path location, simimlar to D:\myproject\, and then the pact mock server was launched and my tests was passed. So until a better solution is discovered I'll work under that short path directory in order to avoid more problems.
Please, read the previous link in order to get more information about this bug because there is very well explained.
Looks to me that the server isn't starting up properly, this is normally because the port is already being used. To see if this is the case, in your node command line (in cmd, type node to go to the node command line), copy/paste the following:
require('http').createServer(function(){}).listen(11108);
The 'listen' function takes in the port number, which I took from your screenshot. Look at what node outputs; my guess is it will show something like this:
Error: listen EADDRINUSE :::11108
at Object.exports._errnoException (util.js:1018:11)
at exports._exceptionWithHostPort (util.js:1041:20)
at Server._listen2 (net.js:1258:14)
at listen (net.js:1294:10)
at Server.listen (net.js:1390:5)
at repl:1:44
at sigintHandlersWrap (vm.js:22:35)
at sigintHandlersWrap (vm.js:73:12)
at ContextifyScript.Script.runInThisContext (vm.js:21:12)
at REPLServer.defaultEval (repl.js:340:29)
This means that there is in fact a port conflict. Look at your task manager and make sure there aren't any instances of node running in the background that might be interfering with your tests spinning up a new server. You might also want to check for any versions of the ruby.exe running; sadly, we have to package the ruby.exe with pact-node, and it spins up a new instance of the mock server using ruby, since that's the language it's written in. From time to time, it does happen that node simply "loses track" of the ruby instance and doesn't shut it off properly.
This is a problem that is well known to us and is something we're actively trying to fix by consolidating all core pact code into a single shared library that can be used across all languages and operating systems without the need to spin up an extra instance. Please bear with us as we get some of these kinks out :)
Related
I have project with nodejs loopback 3.x version and I am recently turned dev in nodejs. I have written the models, server aspects (server.js, server/root.js) etc. Following are the dependencies:
"dependencies" : {
"#types/async": "2.0.40",
"#types/lodash": "4.14.139",
"#types/loopback": "3.1.3",
"#types/loopback-boot": "2.23.0",
"loopback-connector-rest": "3.0.0",
"loopback-model-binder": "1.4.0",
"#types/multiparty": "0.0.31",
"rimraf": "2.6.1",
"sinon": "3.2.1",
"ts-node": "3.3.0",
"typescript": "2.8.3",
"gulp-sequence": "0.4.6",
"gulp-symlink": "2.1.4",
"gulp-typescript": "4.0.1",
"request": "2.81.0",
"shelljs": "0.8.1",
"yargs": "11.0.0",
"os-locale": "3.1.0",
"loopback-connector": "4.4.0",
"strong-globalize": "2.10.0",
"strong-remoting": "3.14.0"
}
This is my code snippet in server.ts:
const app: any = loopback();
boot(app, __dirname, (err) => {
if (err) throw err;
});
app.start = () => {
return app.listen(() => {
const BASE_URL = app.get('url').replace(/\/$/, '');
const explorer = app.get('loopback-component-explorer');
if (explorer) {
Logger.info(`Browse your REST API at ${BASE_URL}${explorer.mountPath}`);
}
});
};
Following are the steps for installing and starting app:
npm install
npm run build
npm run start
But the application is not starting, no errors but returns at command prompt. I enabled the verbose output for the npm run start -verbose command and I found following:
loopback:datasource Module ./connectors/rest not found, will try another candidate. +10ms
loopback:datasource Initializing connector RequestBuilder +561ms
loopback:datasource Connector is initialized for dataSource rest +7ms
loopback:datasource DataSource rest is now connected to undefined +1ms
lifecycle port-app#2.0.0~start: unsafe-perm in lifecycle true
Please let me know about any pointers regarding the above issue.
it was a silly miss from my part. Once you create the app and then in boot process you need to start the application.
boot(app, __dirname, (err) => {
if (err) throw err;
app.start(); // <-- Fix
});
I have a Firebase Node.js backend deployed and running locally using >firebase serve (which I use for preliminary development). I am able to add and update documents locally (using Postman to emulate an external REST API). The same is true up on my Firebase server. What does not work are my delete document routines when run locally. They work fine when run against the server version in Google. (Note. the delete routines were working locally when I was running an earlier 8.x version of Node.
Here is my package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"dependencies": {
"actions-on-google": "^2.7.0",
"firebase-admin": "^8.0.0",
"firebase-client": "0.1.1",
"firebase-functions": "^3.0.2",
"moment": "^2.24.0",
"request-promise-native": "^1.0.7",
"sprintf-js": "^1.1.2",
"twilio": "^3.32.0"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.1.6"
},
"private": true
}
My local env is Windows 7. I am using Postman to invoke local and served versions and the logs for both are the same, showing no errors.
My local Node version is v10.16.0
Finally here is on of my delete routines.
'use strict'
const functions = require('firebase-functions')
var firebaseClient = require('firebase-client')
var moment = require('moment');
const serviceAccount = require("./myconfiguration Info");
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "my db url"
});
var db = admin.firestore()
db.settings({ timestampsInSnapshots: true })
var sessionRef = db.collection('Sessions')
exports.clearSessions = async function(){
const response = await sessionRef.get().then(snapshot=>{
snapshot.forEach((doc=>{
if (doc.exists){
doc.ref.delete()
}
}))
return true
}).catch(err=>{
console.error(err)
console.log('return false')
return false
})
console.log(response)
return response
}
I am not certain if this is the problem, but you are ignoring the promises returned from delete(). The clearSessions will return before they are resolved. It's not clear from your who code calls clearSessions or what happens after that, but if your program terminates after it returns, the work might not complete. If you intend to call this from a cloud function, the work almost certainly will not complete before the function terminates, if the promises are not taking into account.
Also, you are using a slightly outdated version of firebase-admin. Try upgrading it.
I would like to deploy a Node.JS app on Cloud Foundry.
I follow the following steps:
Add the engines part in the package.json
{
"name": "vsapc",
"version": "1.0.0",
"description": "Application Name",
"main": "server/app.js",
"scripts": {
"start": "node server/app.js",
"backup": "node backup.js",
"restore": "node restore.js",
"seed": "node server/seed/Seed.js",
"postinstall": "node install.js"
},
"directories": {
"test": "test"
},
"dependencies": {
"bcrypt-nodejs": "0.0.3",
"body-parser": "^1.15.2",
"cfenv": "^1.0.3",
"express": "^4.14.0",
"jsonwebtoken": "^7.1.9",
"mongodb": "^2.2.5",
"mongoose": "^4.6.3",
"mongoose-seed": "^0.3.1",
"morgan": "^1.7.0",
"promise": "^7.1.1",
"prompt": "^1.0.0",
"winston": "^2.2.0",
"winston-daily-rotate-file": "^1.4.0"
},
"engines": {
"node": "6.11.*",
"npm": "5.*"
},
"author": "",
"license": "ISC"
}
I create the manifest.yml
---
applications:
- name: Policy_Studio
memory: 2048MB
env:
NODE_ENV: production
I used the following to connect in install.js:
const vcapServices = JSON.parse(process.env.VCAP_SERVICES);
let mongoUrl = '';
mongoUrl = vcapServices.mongodb[0].credentials.uri;
mongoose.connect(mongoUrl,{useMongoClient: true}, function (err){
if (err) {
console.log("Database connection responded with: " + err.message);
console.log("Is your server.config.json up to date?");
process.exit(1);
return
}
console.log("Connected to database.");
and the following in app.js:
Server.prototype.connectDatabase = function (url) {
mongoose.Promise = Promise;
const vcapServices = JSON.parse(process.env.VCAP_SERVICES);
let mongoUrl = '';
mongoUrl = vcapServices.mongodb[0].credentials.uri;
mongoose.connect(mongoUrl,{useMongoClient: true});
mongoose.connection.on("error", function (err) {
log.error(err)
});
mongoose.connection.once("openUri", function () {
log.info("Connected to DB")
})
};
connect by command line to SCAPP and push the app with cf push
As i don't have the MongoDB on the cloud i have an error
I build a MOngoDB service on the cloud and bind directly the app through the web GUI
On the gui i click restage button for my app
I have the error
Database connection responded with: failed to connect to server
[2xtorvw9ys7tg9pc.service.consul:49642] on first connect [MongoError:
connect ECONNREFUSED 10.98.250.54:49642]
I add the service mongoDB in my manifest and cf push my application
Still the same error as in point 9
I tried to change the connection in install.js
Thank you for your help
While your parsing of VCAP_SERVICES appears to work (you get a URL containing a hostname & port), i highly recommend to leverage one of the existing libraries for it for further projects:
https://www.npmjs.com/package/cfenv
Still, please that the parsing of your mongo credentials is properly working (cf e ${app_name}, look for VCAP_SERVICES, manually compare)
If you want to test your service with independent code, here is a sample app i quickly threw together to test all mongodb services bound to it:
package.json:
{
"name": "mongo-tester",
"version": "1.0.0",
"description": "tests all mongodbs via VCAP_SERVICES",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Michael Erne",
"license": "MIT",
"dependencies": {
"async": "^2.5.0",
"cfenv": "^1.0.4",
"lodash": "^4.17.4",
"mongodb": "^2.2.31"
}
}
server.js:
var cfenv = require('cfenv'),
_ = require('lodash'),
http = require('http'),
async = require('async'),
MongoClient = require('mongodb').MongoClient
var appEnv = cfenv.getAppEnv();
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Return something for CF Health Check\n');
}).listen(appEnv.port);
var services = _.values(appEnv.getServices());
var mongodbs = _.filter(services, { label: 'mongodb' });
async.eachLimit(mongodbs, 1, function (m, callback) {
MongoClient.connect(m.credentials.database_uri, function (err, db) {
if (err) {
return callback(err);
}
db.collection("debug").insertOne({"test": true}, function(err, res) {
if (err) return callback(err);
console.log("document inserted successfully into " + m.credentials.database_uri);
db.close();
return callback(null);
});
});
}, function (err) {
if (err) {
console.log(err.stack || err);
console.log('---> mongodb connection failed <---');
return;
}
console.log('---> connection to all BOUND mongodb successful <---');
});
It should print something like the following in its logs if it can connect to any of the bound mongodb services:
document inserted successfully into mongodb://xxx:yyy#zzz.service.consul:1337/databaseName
---> connection to all BOUND mongodb successful <---
If this fails with similar errors, the service instance seems broken (wrong url/port being reported). I would just recreate the service instance in that case and try again.
Finally we have found the problem. The cloud foundry is not allowing to access the MongoDB service during the postinstall phase. So we changed it to prestart and it worked.
Thank you for your help
I need some help to resolve my problem with testing on nodejs codes. I'm using mocha and supertest. I'm confused with the implementation in supertest. I don't know to resolved it. I'm trying to automate downloading a file.
describe('GET /entry/:entryId/file/:id/download', function(){
it('should pass download function', function(done){
this.timeout(15000);
request(app.webServer)
.get('/entry/543CGsdadtrE/file/wDRDasdDASAS/download')
.set('Authorization', 'Bearer eyJ0eXAiOiJKV1QiLCJhbGco')
.expect(200)
.end(function(err, res) {
if (err) return done(err);
console.log(err, res);
done();
});
});
});
I received a similar error from mocha when testing an express app. Full text of error:
0 passing (185ms)
2 failing
1) loading express responds to /:
TypeError: app.address is not a function
at Test.serverAddress (test.js:55:18)
at new Test (test.js:36:12)
at Object.obj.(anonymous function) [as get] (index.js:25:14)
at Context.testSlash (test.js:12:14)
2) loading express 404 everything else:
TypeError: app.address is not a function
at Test.serverAddress (test.js:55:18)
at new Test (test.js:36:12)
at Object.obj.(anonymous function) [as get] (index.js:25:14)
at Context.testPath (test.js:17:14)
I fixed it by adding this to my express server.js, i.e. export the server object
module.exports = app
Typescript users, who are facing this error, check two things:
The express server should have module.exports = app (thanks to #Collin D)
Use import * as app from "./app"
instead of wrong import app from "./app"
I was facing same problem, above solution didn't work for me, some one in my shoes
kindly follow this guy's
exports in server.js should be
module.exports.app = app;
If you have multiple modules than use es6 feature
module.exports = {
app,
something-else,
and-so-on
}
my package.json for version cross ref..
{
"name": "expressjs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "mocha **/*.test.js",
"start": "node app.js",
"test-watch": "nodemon --exec npm test"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.4",
"hbs": "^4.0.1"
},
"devDependencies": {
"mocha": "^5.2.0",
"supertest": "^3.3.0"
}
}
I am running into a protractor issue i.e. Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL
From my protractor.conf.js:
onPrepare: function () {
//Mail config
require('./test/e2e/config/mailin.js');
}
Here is the mailin.js config:
var mailin = require('mailin');
mailin.start({
port: 2525,
disableDNSValidation: true,
disableWebhook: true // Disable the webhook posting.
});
mailin.on('startMessage', function (connection) {
console.log(connection);
});
/* Event emitted after a message was received and parsed. */
mailin.on('message', function (connection, data, content) {
console.log(data);
/* Do something useful with the parsed message here.
* Use parsed message `data` directly or use raw message `content`. */
});
var getLastEmail = function () {
var deferred = protractor.promise.defer();
console.log("Waiting for an email...");
mailin.on('message', function (connection, data, content) {
deferred.fulfill(data);
});
return deferred.promise;
};
var extractToken = function (email) {
var deferred = protractor.promise.defer();
var pattern = /\/#\/useraccount\/activate\/(\S+)">/g;
var result = pattern.exec(email.html);
var token = result[1];
deferred.fulfill(token);
return deferred.promise;
};
global.getLastEmail = getLastEmail;
global.extractToken = extractToken;
And finally my test case:
describe('Signup page', function () {
var signupPage = new SignupPage();
beforeEach(function () {
signupPage.get();
});
it('should allow user to signup', function () {
signupPage.chooseParentsType();
signupPage.typeFirstName('Julien');
signupPage.typeEmail('me#bignibou.localhost');
signupPage.typePassword('------');
signupPage.typeAddress('5 rue Sainte Anast');
signupPage.scroll();
signupPage.firstAddress();
signupPage.signup();
browser.controlFlow().execute(getLastEmail).then(extractToken).then(showToken);
});
function showToken(token){
console.log('And the token is... ', token);
};
});
I get the following error from protractor:
Using the selenium server at http://localhost:4444/wd/hub
[launcher] Running 1 instances of WebDriver
warn: Either spamassassin or spamc are not available. Spam score computation is disabled.
Started
info: Mailin Smtp server listening on port 2525
. Waiting for an email...
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
F
Failures:
1) Signup page should allow user to signup
Message:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
Stack:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at [object Object]._onTimeout (/Users/julien/Documents/projects/bignibou/bignibou-site/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1812:23)
2 specs, 1 failure
Can someone please help?
edit: Here are the versions used by my app:
package.json
{
"name": "bignibou-client",
"private": true,
"engines": {
"node": "0.12.x"
},
"devDependencies": {
"assemble-less": "~0.7.0",
"bower": "1.6.2",
"flow": "~0.2.3",
"grunt": "~0.4.5",
"grunt-angular-templates": "^0.5.7",
"grunt-contrib-clean": "~0.6.0",
"grunt-contrib-concat": "~0.5.0",
"grunt-contrib-copy": "~0.7.0",
"grunt-contrib-cssmin": "~0.10.0",
"grunt-contrib-uglify": "~0.6.0",
"grunt-filerev": "~2.1.2",
"grunt-karma": "~0.12.1",
"grunt-mkdir": "~0.1.2",
"grunt-usemin": "~2.6.2",
"karma": "~0.13.15",
"karma-coverage": "^0.5.3",
"karma-htmlfile-reporter": "~0.1.2",
"karma-jasmine": "~0.3.6",
"karma-junit-reporter": "~0.3.7",
"karma-phantomjs-launcher": "~0.2.1",
"mailin": "^3.0.1",
"phantomjs": "~1.9.18",
"protractor": "2.5.1"
},
"scripts": {
"postinstall": "node_modules/.bin/bower install"
}
}