I have a very simple Koa application:
var app = module.exports = require("koa")();
app.use(function *(){
this.body = "Koa says Hi!";
});
var port = process.env.PORT || (process.argv[2] || 3000);
port = (typeof port === "number") ? port : 3000;
app.listen(port);
console.log("Application started. Listening on port:" + port);
that I test with mocha and supertest like this;
var app = require("../");
var request = require("supertest").agent(app.listen());
describe("Our amazing site", function () {
it("has a nice welcoming message", function (done) {
request
.get("/")
.expect("Koa says Hi!")
.end(done);
});
});
I want to watch my files for changes and use the -w flag like this
mocha -u bdd -R min -w
That works fine. I change a file, the test is reexcuted and all is well.
But, very strangely, if I move that command into my package.json file as a script, like this:
"scripts": {
"watch:test": "mocha -u bdd -R min -w"
},
The first time I run the command it works, when I make a change that is picked up but now the test fails with:
1) Uncaught error outside test suite:
Uncaught Error: listen EADDRINUSE :::3000
at Object.exports._errnoException (util.js:837:11)
at exports._exceptionWithHostPort (util.js:860:20)
at Server._listen2 (net.js:1231:14)
at listen (net.js:1267:10)
at Server.listen (net.js:1363:5)
at Application.app.listen (node_modules/koa/lib/application.js:70:24)
at Object.<anonymous> (index.js:10:5)
at Object.<anonymous> (test/site.spec.js:1:73)
at Array.forEach (native)
at StatWatcher._handle.onchange (fs.js:1285:10)
That error will not go away until I stop mocha and then restart it.
Why does it behave differently when run via npm?
What can I do to fix this?
Ok - I found the solution. This has to do with that I'm starting an app twice, when under test. And not closing both.
To start testing with Supertest you construct a request like this: var request = require("supertest").agent(app.listen());. Btw the app.listen() is the same thing as we do in our application.
Since we are watching our files for changes the server never gets close. On the next run of the test it starts again: var request = require("supertest").agent(app.listen()); and the "Address is in use".
The solution is simple: just start listening when you are not running under test. A simple way to do that is by checking for a module parent in your application:
if(!module.parent) {
app.listen();
}
Related
I am getting an error message:
listen EADDRINUSE: address already in use :::3000.
When I tried after removing the server starting code(i.e app.listen part) nothing is happening
const path = require('path')
const express = require('express')
//var publicPathDirectory = path.join(__dirname,"../public")
const app = express()
app.listen(3000,()=>{
console.log('server started')
})
process.on('SIGINT', function() {
console.log( "\nGracefully shutting down from SIGINT (Ctrl-C)" );
// some other closing procedures go here
process.exit(1);
});
I've had this happen to me before, where even though I quit the node server with CTRL+C, it still is hogging port 3000. You can kill node with:
pkill -f node
Potentially related to Node.js Port 3000 already in use but it actually isn't?
Use number 1 inside exit only when you have an exit with failure. To force exit do not use number inside exit().
process.exit()
Please take a look at here. May be you can understand. link
I have created a simple html application on nodejs. Here is the code os server.ts
import express = require('express');
import http = require('http');
import path = require('path');
import cookieParser = require('cookie-parser');
export class Server {
static startServer() {
let app = express();
app.use(cookieParser());
app.use(express.static(__dirname + "/public"));
let server = http.createServer(app);
server.listen(7000, () => {
console.log('Up and running on port : ' + 7000);
});
}
}
exports.startServer = Server.startServer;
// Call a module's exported functions directly from the command line.
require('make-runnable');
I have used make-runnable module to run exported functions directly from the command line. And this is my start script in package.json
"start": "concurrently \"tsc --watch \" \"nodemon server.js startServer\""
the application is working fine, but this is printing undefined on the screen that annoying and this should be solved.
[1] [nodemon] restarting due to changes...
[1] [nodemon] starting `node server.js startServer`
[1] Up and running on port : 7000
[1] --------make-runnable-output--------
[1] undefined
[1] ------------------------------------
[0] 4:08:52 PM - Compilation complete. Watching for file changes.
What is the reason for this?
Solution
The make-runnable package provides you with the ability to clear the output frame by import the "custom" module and specifying a boolean value for printOutputFrame. Rather than require('make-runnable'), use:
require('make-runnable/custom')({
printOutputFrame: false
})
However, this doesn't remove the "undefined" (or output) message because make-runnable is expecting some return value to log as it resolves the promise.
Instead, return some value from your function for Bluebird (or make-runnable) to print on its own:
static startServer() {
let app = express();
app.use(cookieParser());
app.use(express.static(__dirname + "/public"));
let server = http.createServer(app);
- server.listen(7000, () => {
- console.log('Up and running on port : ' + 7000);
- });
+ server.listen(7000)
+ return 'Up and running on port : ' + 7000;
}
Note: I haven't verified that this won't cause the server to stop listening, but this is rather illustrating what the package will expect from your function.
Explanation
*Bit of an older question but I came across the same issue recently so I figured I'd provide a solution.
The reason why "undefined" is being printed is that it's expecting some return value from the function that you're calling. Consider this snippet of a function (that I was working on and ran across this issue):
generate: function() {
// ... some preliminary code
fs.writeFile(file, modifiedFileData, error => {
if (error) throw error
console.log('App key generated successfully.')
})
}
Output:
$ node utils/EncryptionKey.js generate
--------make-runnable-output--------
undefined
------------------------------------
App key generated successfully.
Done in 0.27s.
By default, I just want that message to be logged to the console. Without make-runnable it worked fine since I initially just ran the function, but wanted to put this into an export. Looking at the source code (engine.js) for make-runnable, the following function:
function printOutput(returnValue) {
Bluebird.resolve(returnValue)
.then(function (output) {
if (options.printOutputFrame) {
console.log('--------make-runnable-output--------');
}
console.log(output);
if (options.printOutputFrame) {
console.log('------------------------------------');
}
}).catch(printError);
}
expects some return value, since Bluebird wraps the function you're executing as a promise. I instead changed my initial code to:
generate: function () {
// ... some preliminary code
fs.writeFile(file, modifiedFileData, error => {
if (error) throw error
return true
})
return 'App key generated successfully.'
}
and removed the "undefined" value, and printed my app key message.
Output:
$ node utils/EncryptionKey.js generate
App key generated successfully.
Done in 0.26s.
I created a simple Webapp using express.js and want to test it with jasmine-node. Works fine so far but my problem is that I have to start the server manually every time before I can run my tests.
Could you help me on how to write a spec-helper that runs the server (with another port then my development one) just for the tests and then kills it afterwards?
This is what I do:
I have a server.js file inside the root of my node project that sets up the node application server (with express) and exports 2 methods:
exports.start = function( config, readyCallback ) {
if(!this.server) {
this.server = app.listen( config.port, function() {
console.log('Server running on port %d in %s mode', config.port, app.settings.env);
// callback to call when the server is ready
if(readyCallback) {
readyCallback();
}
});
}
};
exports.close = function() {
this.server.close();
};
The app.js file will be simple at this point:
var server = require('./server');
server.start( { port: 8000 } );
So the files/folder basic structure would be the following:
src
app.js
server.js
Having this separation will allow you to run the server normally:
node src/app.js
..and/or require it from a custom node script, which could be a node script (or a jake/grunt/whatever task) that executes your tests like this:
/** my-test-task.js */
// util that spawns a child process
var spawn = require('child_process').spawn;
// reference to our node application server
var server = require('./path/to/server.js');
// starts the server
server.start( { port: 8000 }, function() {
// on server ready launch the jasmine-node process with your test file
var jasmineNode = spawn('jasmine-node', [ '.path/to/test/file.js' ]);
// logs process stdout/stderr to the console
function logToConsole(data) {
console.log(String(data));
}
jasmineNode.stdout.on('data', logToConsole);
jasmineNode.stderr.on('data', logToConsole);
jasmineNode.on('exit', function(exitCode) {
// when jasmine-node is done, shuts down the application server
server.close();
}
});
I use Mocha - which is damn similar - but the same principle should apply: you could try requireing your app.js file in a 'beforeEach' hook inside the main describe. That should fire it up for you.
Assuming you use some code that invokes app.listen() in server.js, don't require the file on each run but only once and then have two functions like
startServer = -> app.listen(3000)
stopServer = -> app.close()
Then you can use these in beforeEach and afterEach
If you want then to go one step further in automating your testing while you develop, you can go to your terminal line and execute
jasmine-node . --autotest
Jasmine then will stay listening to every file inside your project and whenever you make changes to one it will tell if that piece of your code breaks any of your tests ;)
I installed node.js and now.js successfully.
For now.js, this is how I did:
npm install now -g
npm install now (had to add this one. Without it, I get a "Cannot find now..." error message)
When I start the node server and provide a server.js file like this:
var httpServer = require('http');
httpServer.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('Node is ok');
res.end();
}).listen(8080);
console.log('Server runs on http://xxxxx:8080/');
Everything is fine.
Now, I'm trying to add to this file a basic use of now.js:
var nowjs = require("now");
var everyone = nowjs.initialize(httpServer);
everyone.now.logStuff = function(msg){
console.log(msg);
}
I create an index.html file in the same folder (for testing purposes)
<script type="text/javascript" src="nowjs/now.js"></script>
<script type="text/javascript">
now.ready(function(){
now.logStuff("Now is ok");
});
</script>
This time, this is what I get on the terminal when starting the server:
Server runs on http://xxxxx:8080/
[TypeError: Object #<Object> has no method 'listeners']
TypeError: Object #<Object> has no method 'listeners'
at Object.wrapServer (/home/xxxx/node_modules/now/lib/fileServer.js:23:29)
at [object Object].initialize (/home/xxxx/node_modules/now/lib/now.js:181:14)
at Object.<anonymous> (/home/xxxx/server.js:10:22)
at Module._compile (module.js:444:26)
at Object..js (module.js:462:10)
at Module.load (module.js:351:32)
at Function._load (module.js:309:12)
at module.js:482:10
at EventEmitter._tickCallback (node.js:245:11)
Please keep in mind that I'm an absolute beginner.
Thank you for your help
'npm install -g' installs modules at a global level, often with the intent of providing system-wide binaries for terminal usage. Think Ruby Gems. If you want to include a module as part of your project you need to remove the -g.
Also, your httpServer variable is not your server but rather the http module. createServer() returns a server object which you want to capture with a variable to use in your nowjs.initialize() method as follows:
var http = require('http')
, now = require('now')
// Returns an Http Server which can now be referenced as 'app' from now on
var app = http.createServer(
//... blah blah blah
)
// listen() doesn't return a server object so don't pass this method call
// as the parameter to the initialize method below
app.listen(8080, function () {
console.log('Server listening on port %d', app.address().port)
})
// Initialize NowJS with the Http Server object as intended
var everyone = nowjs.initialize(app)
I would like to use CasperJS in node.js.
I have referred to the following URL's to use CasperJS in node.js:
https://github.com/sgentle/phantomjs-node
http://casperjs.org/index.html#faq-executable
With the help of the above URLs I have written the following code:
//DISPLAY=:0 node test2.js
var phantom = require('phantom');
console.log('Hello, world!');
phantom.create(function (ph) {
ph.casperPath = '/opt/libs/casperjs'
ph.injectJs('/opt/libs/casperjs/bin/bootstrap.js');
var casper = require('casper').create();
casper.start('http://google.fr/');
casper.thenEvaluate(function (term) {
document.querySelector('input[name="q"]').setAttribute('value', term);
document.querySelector('form[name="f"]').submit();
}, {
term: 'CasperJS'
});
casper.then(function () {
// Click on 1st result link
this.click('h3.r a');
});
casper.then(function () {
console.log('clicked ok, new location is ' + this.getCurrentUrl());
});
casper.run();
});
When I run this code, I got the following error:
ERROR MSG:
tz#tz-ubuntu:/opt/workspaces/TestPhantomjs$ DISPLAY=:0 node test2.js
Hello, world!
Error: Cannot find module 'casper'
at Function._resolveFilename (module.js:332:11)
at Function._load (module.js:279:25)
at Module.require (module.js:354:17)
at require (module.js:370:17)
at /opt/workspaces/TestPhantomjs/test2.js:6:14
at Object.<anonymous> (/opt/workspaces/TestPhantomjs/node_modules/phantom/phantom.js:82:43)
at EventEmitter.<anonymous> (/opt/workspaces/TestPhantomjs/node_modules/phantom/node_modules/dnode/index.js:215:30)
at EventEmitter.emit (events.js:67:17)
at handleMethods (/opt/workspaces/TestPhantomjs/node_modules/phantom/node_modules/dnode-protocol/index.js:138:14)
at EventEmitter.handle (/opt/workspaces/TestPhantomjs/node_modules/phantom/node_modules/dnode-protocol/index.js:98:13)
phantom stdout: Unable to load casper environment: Error: Failed to resolve module fs, tried fs
You can use SpookyJS to drive CasperJS from Node.
https://groups.google.com/group/casperjs/browse_thread/thread/641e9e6dff50fb0a/e67aaef5ab4ec918?hl=zh-CN#e67aaef5ab4ec918
Nicolas Perriault
2012/2/27 天猪 蓝虫. :
I wan to use casperjs in nodejs.
and refs to:
https://github.com/sgentle/phantomjs-node and
http://casperjs.org/index.html#faq-executable
You can't run CasperJS that way; QtWebKit and V8 don't share the same
js environment (and event loop), so your node.js app won't be able to
load and use a CasperJS module. You have to run your CasperJS script
separately using a subprocess call, like this one on github. I
don't plan to make CasperJS compatible with phantomjs-node because it
uses alert()-based dirty hacks I'm not easy with.
Cheers,
-- Nicolas Perriault
CasperJS includes a web server to talk to the outside world. Node (using request, superagent etc) can now talk to casper over HTTP.
In scraper.js:
#!/usr/bin/env casperjs
// I AM NOT NODEJS
// I AM CASPER JS
// I RUN IN QTWEBKIT, NOT V8
var casper = require('casper').create();
var server = require('webserver').create();
var ipAndPort = '127.0.0.1:8585';
server.listen(ipAndPort, function(request, response) {
casper.start('https://connect.data.com/login');
casper.userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36");
casper.then(function(){
// lots of code here, and a few more cassper.then()s
});
casper.run(function(){
console.log('\n\nFinished')
response.statusCode = 200;
var body = JSON.stringify({
phoneNumber: '1800-YOLO-SWAG'
})
response.write(body);
response.close();
});
});
You can now run scraper.js as a web server:
chmod +x scraper.js
./scraper.js
You should run it as a Linux service just like you would for a node app.
One solution (which worked for me) is to start and stop your server on a per-test basis. For example, I have a runtests.coffee which looks like:
http = require 'http'
glob = require 'glob'
spawn = require('child_process').spawn
db = require './db' # Contains all database stuff.
webapp = require './webapp' # Contains all of the Express stuff.
db.connect 'test' # Connects to the db server and creates an empty test db.
server = http.createServer webapp.makeApp()
server.listen 0, ->
port = server.address().port
process.env.URL = "http://localhost:#{ port }"
glob 'tests/*', (err, filenames) ->
child = spawn 'casperjs', ['test'].concat(filenames)
child.stdout.on 'data', (msg) -> process.stdout.write msg
child.stderr.on 'data', (msg) -> process.stderr.write msg
child.on 'exit', (code) ->
db.disconnect() # Drops the test db.
server.close()
process.exit code
And my CasperJS tests in tests/ look like:
URL = require('system').env.URL # Note, Casper code here, not Node.
casper.test.begin 'Test something', 1, (test) ->
casper.start "#{ URL }/welcome"
casper.then ->
test.assertHttpStatus 200
# ....
casper.run ->
test.done()
It basically means that your script can't find Casper; have you checked the path and made sure that
/opt/libs/casperjs
and:
/opt/libs/casperjs/bin/bootstrap.js
Are accessible by a website user ? considering the location it's probably not likely.
/opt is a unix path, but the website will be looking in {websiterootpath}/opt.
I'd create a subfolder 'casperjs' in the root folder of your website and copy the contents of
/opt/libs/casperjs
To there.
Then change your paths from
/opt/libs/casperjs
To
/casperjs
I tried to run casper by node cron job too,
here's my solution
in casper.js echo your response:
casper.then(function() {
var comments = this.evaluate(getComments);
this.echo(JSON.stringify(comments));
})
use node-cmd in node file casper_wrapper.js:
var cmd = require('node-cmd');
module.exports = function(url) {
return new Promise(function(resolve, reject) {
cmd.get(
'casperjs casper.js ' + url, // casper takes args to run the script
function(err, data, stderr){
if (err) {
reject(err);
return;
}
var obj = JSON.parse(data);
resolve(obj);
}
);
});
}