Related
I have implemented in a controller a route to upload files from axios. For that I use FileInterceptor. Everything works properly but as soon as I activate network throttling in the browser the uploader does not work. Here is the snippet:
#Post('/upload')
#UseInterceptors(
FileInterceptor("file", {
storage: diskStorage({
destination: './src/uploads',
// editFileName is a function that changes the name of the file
filename: editFileName,
}),
})
)
uploadFile(#UploadedFile() file) {
try {
console.log(file)
return 'ok';
} catch(e) {
console.log(e)
}
}
This is the following error that I get:
POST http://localhost:3003/user/file/upload net::ERR_CONNECTION_RESET
It seems, it tries to connect twice to complete the process. First connection time is 60s and the second one also but after that it throws the above error.
I try many ways changing the timeout param but in none of them not success.
The first one is changing the destination config param of diskStorage from string to function:
destination: (req, file, callback) => {
console.log(file);
// That output I see when it uploads successfully in a normal network condition (wifi)
// but it ignores the timer time. Usually is after 5 seconds.
req.socket.setTimeout(30000, () => console.log('Socket ErrorTimeout'))
req.setTimeout(5000, () => console.log('Error req timeout'))
callback(null, './src/uploads')
}
Next one is, inside of bootstrap function on the main file adding the following snippet:
const server = await app.listen(3003);
server.on('connection', (socket) => {
console.log('Connected!')
socket.setTimeout(5*10*1000)
})
And finally adding another module in FileUploader module but also not success:
#Module({
imports: [
MulterModule.register({
dest: './src/uploads'
}),
HttpModule.register({
timeout: 90000,
maxRedirects: 5,
})
],
controllers: [FilesController]
})
export class FilesModule {}
I recommend to use minio, its so good to store files and very good documentation
Given the following gulp tasks I'm able to successfully start the gulp, webpack and nodemon process, but the webpack tasks are open ended, so they will continue to fire the completion handler when their watch / compile cycle is complete.
The server task depends on the client task output, so I need these operations to be synchronous, hence the done
function onBuild(done) {
return function(err, stats) {
if(err) {
gutil.log('Error', err);
if(done) {
done();
}
} else {
Object.keys(stats.compilation.assets).forEach(function(key){
gutil.log('Webpack: output ', gutil.colors.green(key));
});
gutil.log('Webpack: ', gutil.colors.blue('finished ', stats.compilation.name));
if(done) {
done();
}
}
}
}
//dev watch
gulp.task('webpack-client-watch', function(done) {
webpack(devConfig[0]).watch(100, function(err, stats) {
onBuild(done)(err, stats);
});
});
gulp.task('webpack-server-watch', function(done) {
webpack(devConfig[1]).watch(100, function(err, stats) {
onBuild(done)(err, stats);
nodemon.restart();
});
});
gulp.task('webpack-watch',function(callback) {
runSequence(
'webpack-client-watch',
'webpack-server-watch',
callback
);
});
gulp.task('nodemon', ['webpack-watch'], function() {
nodemon({
script: path.join('server/dist/index.js'),
//ignore everything
ignore: ['*'],
watch: ['foo/'],
ext: 'noop'
}).on('restart', function() {
gutil.log(gutil.colors.cyan('Restarted'));
});
});
When I change a file, the watcher does its thing and gulp complains about the callback being called yet again.
[15:00:25] Error: task completion callback called too many times
I've looked at this, but not sure if its applicable.
Why might I be getting "task completion callback called too many times" in gulp?
Basically, I just want this to work synchronously and continuously without error.
gulp nodemon
This solved it for me: Just don't call the callback parameter in your webpack-watch task. Leave it out completely.
After that, the watcher works fine and fast without complaining.
If public folder exists in your application. Please remove and re-run, after you can see this issue resolved.
Coming from the world of express, if there was an error when compiling a Jade template, the error would output to the browser with details of the template error including line number. I would like to see this level of error detail in Hapi.js when the view template compiler encounters an error.
Instead, with Hapi.js, I receive a 500 Internal Server Error instead. The only output I see in the logs is the following:
150511/005652.910, [response], http://localhost:3000: get /abc123 {} 500 (24ms)
This is the basics of my setup.
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 3000 });
server.views({
engines: { jade: require('jade') },
path: __dirname + '/views',
compileOptions: {
pretty: true,
debug: true,
compileDebug: true
}
});
server.route({
method: 'GET',
path: '/{name}',
handler: function (request, reply) {
reply.view('page', {name: request.params.name});
}
});
// I know putting my plugins in an array is not necessary but I like it.
var plugins = [{
register: Good,
options: {
reporters: [{
reporter: require('good-console'),
events: {
response: '*',
log: '*'
}
}]
}
}];
server.register(plugins, function (err) {
if (err) {
throw err; // something bad happened loading the plugin
}
server.start(function () {
server.log('info', 'Server running at: ' + server.info.uri);
});
});
Had the same problem this week too.
var server = new Hapi.Server({
debug: {
request: ['error']
}
});
It won't output to the client (you'll still get a 500 error), but the compilation error will show up in the terminal console.
One possible solution is to log on server 'request-error'. For instance:
server.on('request-error', function (request, err) {
//logs the object
server.log('error', err);
//logs the view compiler error line number and details
server.log('error', err.toString());
});
I would still prefer to see this in the browser (while in "development mode") in addition to the logs.
Because the rendering of the template happens after onPreResponse, it's not possible to catch the error at that point. A way of sending the error to the browser, albeit slightly hacky, is to do a dry run of the compilation inside an extension point, and then transmit the error to the browser at that point:
server.ext('onPreResponse', function (request, reply) {
var response = request.response;
if (response.variety === 'view') {
var source = response.source;
// Let's pre-render the template here and see if there's any errors
return server.render(source.template, source.context, function (err) {
if (err) {
return reply(err.message); // transmit the compile error to browser
}
reply.continue();
});
}
reply.continue();
});
Obviously this has a performance impact because you're rendering the view twice under normal conditions, so you'll want to disable it in production.
Trying to get up to speed with node.js and nodeunit but am finding an issue with nodeunit where it's not seeing the call to test.done() in one of the tests.
The code:
// Added for clarity.
var client = require("restify").createJsonClient({
"version": "*",
"url": "http://localhost:" + server.Port
});
exports["tests"] = {
"setUp": function (callback) {
server.StartServer();
callback();
},
"tearDown": function (callback) {
callback();
},
"CanIHaveSomeTeaPlease?": function (test) {
test.expect(4);
client.get("/tea", function (err, req, res, data) {
test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
test.equal(err.restCode, "ImATeapotError");
test.equal(err.name, "ImATeapotError");
test.done();
});
},
// Note: I expect this test to fail as it is a copy of the above
// test on a different url that doesn't return the ImATeapot
// HTTP error. But it doesn't look like it's detecting it
// properly.
"TakeThisInfo": function (test) {
test.expect(4);
client.put("/push", {
"hello": "world"
}, function (err, req, res, data) {
test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
test.equal(err.restCode, "ImATeapotError");
test.equal(err.name, "ImATeapotError");
test.done();
});
}
};
Output:
FAILURES: Undone tests (or their setups/teardowns):
- tests - TakeThisInfo
To fix this, make sure all tests call test.done()
I'm hoping it is something stupid.
Versions:-
Node: 0.10.21
NPM: 1.3.11
Nodeunit: 0.8.2
Grunt-CLI: 0.1.10
Grunt: 0.4.1
First, I don't know what "server" is in your code, but I would expect it to be asynchronous, so to have something more like this in your setUp function:
function (callback) {
server.StartServer(function(){
callback();
});
}
Second, keep present that nodeunit executes the startUp and the tearDown functions after and before EVERY test so I suspect you are starting your server 2 times (as in the tearDown you are not really closing it).
I've spent the last couple of hours messing with this issue, and what has become clear is that nodeunit has no ability to catch and display exceptions thrown in functions which are triggered later by an IO or setTimeout type process. Considering the way JavaScript runs, this isn't surprising. Everything works once you are sure there are no exceptions, but if you have an error in your code, you will get "undone tests" message and nothing else. Here is what I did to resolve my issues (using a restify route as an example):
function myRoute(req, res, next) {
try {
// your code goes here...
}
catch (err) {
// write it to the console (for unit testing)
console.log(err);
// pass the error to the next function.
next(err);
}
}
Once I understood the problem in this way, fixing it because a lot more clear and I was able to get all of my tests to pass!
I suspect you're not actually calling test.done() in that second test. Put a console.log() call in there to verify you're actually making that call.
FWIW, I repro'd the described problem using a simplified version of your test, below. If you omit the on('error', function() {...}) handler, then the 2nd test fails to complete. Thus, my theory is that your /push endpoint is triggering a different behavior in the restify module. I.e. are you sure restify is invoking your callback with an err property there, or is it doing something different? ... like, for example, emitting an event like http.get does, below.
var http = require('http');
exports.test1 = function (test) {
test.expect(1);
http.get({hostname: "www.broofa.com", path: "/"}, function (res) {
test.equal(res.statusCode, 200, 'got 200');
test.done();
});
};
exports.test2 = function (test) {
test.expect(1);
http.get({hostname: "www.no-such-domain.com", path: "/"}, function (res) {
test.equal(res.statusCode, 200, 'got 200');
test.done();
}).on('error', function() {
// Comment line below out to repro the "Undone tests" error
test.done();
});
};
I'm working around it by forking the server into it's own process in the setup and then killing it in the teardown. Think the issue was to do with the server being created and not shutdown. Thanks #matteofigus for that.
var cp = null; // child process
exports["tests"] = {
"setUp": function (callback) {
cp = fork("./lib/server.js", {"silent": true});
callback();
},
"tearDown": function (callback) {
cp.kill("SIGHUP");
callback();
},
"CanIHaveSomeTeaPlease?": function (test) {
test.expect(4);
client.get("/tea", function (err, req, res, data) {
test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
test.equal(err.restCode, "ImATeapotError");
test.equal(err.name, "ImATeapotError");
test.done();
});
},
"TakeThisInfo": function (test) {
test.expect(1);
client.put("/push", {
"hello": "world"
}, function (err, req, res, data) {
test.ok(false);
test.done();
});
}
};
In my node application I'm using mocha to test my code. While calling many asynchronous functions using mocha, I'm getting timeout error (Error: timeout of 2000ms exceeded.). How can I resolve this?
var module = require('../lib/myModule');
var should = require('chai').should();
describe('Testing Module', function() {
it('Save Data', function(done) {
this.timeout(15000);
var data = {
a: 'aa',
b: 'bb'
};
module.save(data, function(err, res) {
should.not.exist(err);
done();
});
});
it('Get Data By Id', function(done) {
var id = "28ca9";
module.get(id, function(err, res) {
console.log(res);
should.not.exist(err);
done();
});
});
});
You can either set the timeout when running your test:
mocha --timeout 15000
Or you can set the timeout for each suite or each test programmatically:
describe('...', function(){
this.timeout(15000);
it('...', function(done){
this.timeout(15000);
setTimeout(done, 15000);
});
});
For more info see the docs.
I find that the "solution" of just increasing the timeouts obscures what's really going on here, which is either
Your code and/or network calls are way too slow (should be sub 100 ms for a good user experience)
The assertions (tests) are failing and something is swallowing the errors before Mocha is able to act on them.
You usually encounter #2 when Mocha doesn't receive assertion errors from a callback. This is caused by some other code swallowing the exception further up the stack. The right way of dealing with this is to fix the code and not swallow the error.
When external code swallows your errors
In case it's a library function that you are unable to modify, you need to catch the assertion error and pass it onto Mocha yourself. You do this by wrapping your assertion callback in a try/catch block and pass any exceptions to the done handler.
it('should not fail', function (done) { // Pass reference here!
i_swallow_errors(function (err, result) {
try { // boilerplate to be able to get the assert failures
assert.ok(true);
assert.equal(result, 'bar');
done();
} catch (error) {
done(error);
}
});
});
This boilerplate can of course be extracted into some utility function to make the test a little more pleasing to the eye:
it('should not fail', function (done) { // Pass reference here!
i_swallow_errors(handleError(done, function (err, result) {
assert.equal(result, 'bar');
}));
});
// reusable boilerplate to be able to get the assert failures
function handleError(done, fn) {
try {
fn();
done();
} catch (error) {
done(error);
}
}
Speeding up network tests
Other than that I suggest you pick up the advice on starting to use test stubs for network calls to make tests pass without having to rely on a functioning network. Using Mocha, Chai and Sinon the tests might look something like this
describe('api tests normally involving network calls', function() {
beforeEach: function () {
this.xhr = sinon.useFakeXMLHttpRequest();
var requests = this.requests = [];
this.xhr.onCreate = function (xhr) {
requests.push(xhr);
};
},
afterEach: function () {
this.xhr.restore();
}
it("should fetch comments from server", function () {
var callback = sinon.spy();
myLib.getCommentsFor("/some/article", callback);
assertEquals(1, this.requests.length);
this.requests[0].respond(200, { "Content-Type": "application/json" },
'[{ "id": 12, "comment": "Hey there" }]');
expect(callback.calledWith([{ id: 12, comment: "Hey there" }])).to.be.true;
});
});
See Sinon's nise docs for more info.
If you are using arrow functions:
it('should do something', async () => {
// do your testing
}).timeout(15000)
A little late but someone can use this in future...You can increase your test timeout by updating scripts in your package.json with the following:
"scripts": {
"test": "test --timeout 10000" //Adjust to a value you need
}
Run your tests using the command test
For me the problem was actually the describe function,
which when provided an arrow function, causes mocha to miss the
timeout, and behave not consistently. (Using ES6)
since no promise was rejected I was getting this error all the time for different tests that were failing inside the describe block
so this how it looks when not working properly:
describe('test', () => {
assert(...)
})
and this works using the anonymous function
describe('test', function() {
assert(...)
})
Hope it helps someone, my configuration for the above:
(nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)
My issue was not sending the response back, so it was hanging. If you are using express make sure that res.send(data), res.json(data) or whatever the api method you wanna use is executed for the route you are testing.
Make sure to resolve/reject the promises used in the test cases, be it spies or stubs make sure they resolve/reject.