Cancel all protractor tests on condition met - node.js

I have a basic Angular 6 app with e2e tests setup by default.
We make CRUD operations on a test database (the backend with the test environment should be running before starting the e2e tests).
The idea is to request a specific endpoint that returns true if the test environment is running. (backend in an express server)
In the very first spec I can make that request but throw new Error() doesn't stop the tests.
I've found some npm packages forcing the tests to exit on the first failure (jasmine fail whale and jasmine fail fast) but I don't want my tests to stop on any other exception than the wrong environment.
I tried making this test in protractor.conf.js in the onPrepare() method. I can throw new Error() there but I cannot make an http request (even basic XmlHTTPRequest is not defined)
What are my solutions to make sure the tests are run only when the right environment is running?

process.exit() seems to be a good enough solution for your use case.

You can use the jasmine done function for your case.
it('should do something', (done) => {
try {
// doing something and an error happend
throw Error('failure');
} catch (error) {
done.fail(error);
}
});
Test will fail and be marked as failed and will abort future testing in the current suite "describe"

Related

Node.JS: Refreshing the nodemailer-mock after each test in Jest

I am building a Node JS application using Express.js framework. My application is sending email using the nodemailer package, https://nodemailer.com/about/. I am writing test using supertest and Jest. I am using nodemailer-mock package, https://www.npmjs.com/package/nodemailer-mock to mock my application.
I can mock the logic for sending email for Jest as mentioned in the nodemailer-mock documentation. The only issue is that it is not resetting the data/ count after each test. For example, I have two tests and both are sending emails and when I do the following assertion, it is failing.
const sentEmails = mock.getSentMail();
// there should be one
expect(sentEmails.length).toBe(1);
It is failing because an email was sent in the previous test. How can I reset it?
Assuming your mock variable is set (or even imported) at the module level, this should cover it:
afterEach(() => {
mock.reset();
});
Keep in mind that this method also seems to reset anything else you have configured on the mock (success response, fail response, etc.), so you may need to perform that setup each time too. That would be a good fit for a beforeEach block.

How to run multiple integration tests using mocha recursively without getting their hooks all combined?

I have made a few integration test using mocha which run fine when run independently but when i try to run them using : mocha test --recursively .
The behaviour I noticed here is that all the after hooks (probably the before too) are getting combined.
I drop my db in the after hook of each test so I check in between tests and I can find data from the previous tests.
It gets cleared up after the last test somehow.
I have already tried importing them into one file but even that won't serve the purpose.
Here are my hooks.
before(async () => {
app.set('port', SERVER_PORT);
server = http.createServer(app);
server.listen(SERVER_PORT, () => console.log(`API running on localhost:${SERVER_PORT}`));
// Initial feeding of the database
await dookie.push('mongodb://localhost:27017/tests', SEEDDATA);
});
after(async () => {
await mongoose.connection.db.dropDatabase();
server.close();
process.exit(0);
});
THANKS
Use jest as it provides the functionality you're looking for inbuilt.
It's hard to tell what is wrong with your tests without having a closer look at the code, so I'm going to drop here a few ideas that come to my mind, with no guarantee that anything will help.
Possibility 1
Use beforeEach and afterEach rather than before and after. This will ensure that your DB cleanup code is executed after each test, rather than after the last test in a describe function block. Details here.
Possibility 2
You are running your tests in multiple threads with mocha-parallel-tests or some other tool. Make sure that the tests where the DB is being accessed are not being parallelized.
Possibility 3
Your db.dropDatabase call returns before the database is actually dropped, while the request is still pending. You'll have to check your connection or database settings.
If nothing helps, try inserting log statements at the start of each unit test and before/after hook, this will help you understand when the code is actually being run and see what is happening in the wrong order.

How to finish/kill Mocha/Istanbul test cycle with Node.js

I've been working on getting an Azure Mobile App with Node.js backend running locally and testable. I finally got everything working well and started writing my tests. Then, I learned about Istanbul/NYC for testing code coverage.
All appears to be working well, and I am able to get the code coverage file generated for all my *.js files, but only after I manually press Ctrl+C.
Is this the normal way for a set of mocha tests to end? It would seem that there would/should be some way to get to the end of a set of tests and auto-kill the Node.js/express server that was created for the test session.
I'm new to the nuts-and-bolts side of Node.js/express/mocha/nyc. Is my expectation wrong? Is there a way to do what I'd like?
I'm not sure where you are lifting your server (server.listen) but stopping your server on a "global" after should be enough.
What I usually do is create a bootstrap.test.js and specify what should happen before and after tests there and run mocha like this:
mocha /test/bootstrap.test.js /test/unit/**/*.test.js /test/integration/**/*.test.js.
You need to make sure that that after is not inside a describe, so it runs after all tests have completed.
So your bootstrap.test.js should look something like this:
/*
imports and stuff
*/
before(function () {
// LIFT YOUR SERVER //
});
after(function () {
server.close();
});
EDIT:
As for the programmatic equivalent of Ctrl-c, that is process.exit(0)

Mocha browser tests with Node.js command-line runner?

I have a suite of client-side Mocha tests that currently run with the browser test runner. But I also have a suite of server-side Mocha tests that run with the Node.js command-line test runner.
I know I can run the client-side tests from the command-line in a headless browser like PhantomJS (e.g. like this), but they'd still run separately from the server-side tests.
Is there any way to run the client-side tests as part of the command-line run?
E.g. always run both sets of tests, and have one combined output like "all 100 tests passed" or "2 tests failed" — across both client-side and server-side suites.
I imagine if this were possible, there'd need to be some sort of "proxy" layer to dynamically describe to the command-line runner each browser test, and notify it of each result (maybe even any console.log output too) as the tests ran in the browser.
Does there exist anything that achieves this? I've had a hard time finding anything. Thanks!
I use Zombie for this. There's surely a way to do it with Phantom too. Just write your client-side tests under the same directory as your server-side tests and they'll get picked up by Mocha and executed along with the rest.
I'm not sure whether you need some sample test code but here's some just in case:
var app = require('../server').app; // Spin up your server for testing
var Browser = require('zombie');
var should = require('should');
describe('Some test suite', function () {
it('should do what you expect', function (done) {
var browser = new Browser();
browser.visit('http://localhost:3000', function (err) {
// Let's say this is a log in page
should.not.exist(err);
browser
.fill('#username', 'TestUser')
.fill('#password', 'TestPassword')
.pressButton('#login', function (err) {
should.not.exist(err);
// etc...
return done();
});
});
});
});

How to get grunt.js to start an express app for testing

My current situation is that I use grunt to make a production version of my express app (minimize and merge all the js/css, copy all the files in place) and then I have to run a script which sets an environment variables (my app only serves the test harness when running in TEST mode), creates an empty Mongo test database and then calls npm start on the application directory, and then I manually have to run the tests from either Chrome or Phantom, what I want to do is have grunt set the environment variable and run the server, run the tests, and then stop the server (in the future if all is successful it would be nice to have it deploy as well). However when I try to run the app in grunt, it gets stopped as soon as it is completed.
How do I have grunt start the app, wait until it is started and then run tests?
If you check grunt-express which is a plugin for express web-server tasks via grunt.
express-keepalive
Note that this server only runs as long as grunt is running. Once
grunt's tasks have completed, the web server stops. This behavior can
be changed by appending a express-keepalive task at the end of your
task list like so
grunt.registerTask('myServer', ['express', 'express-keepalive']);
Now when you run grunt myServer, your express server will be kept alive
until you manually terminate it.
Such feature can also be enabled ad-hoc by running the task like grunt express express-keepalive.
This design gives you the flexibility to use grunt-express in
conjunction with another task that is run immediately afterwards, like
the grunt-contrib-qunit plugin qunit task. If we force express task to
be always async, such use case can no longer happen.
From the guide grunt-contrib-qunit package is used to run QUnit unit tests in a headless PhantomJS instance. Also mind the last line, if you force express to be always async it would be of no use.
npm link for grunt-express.
I'm not sure if I understand your problem correctly, but probably this helps:
Do you know about Grunt's async function? For some time I used the following approach to start (and stop) my Express app. I used it with watch, so it automatically restarted on save. In this case you have to set watch's nospawn option to true.
var server = null;
grunt.registerTask('server', 'Start server', function() {
var done = this.async();
if (server !== null) {
server.close();
clearCache();
}
var app = require('./my-express-app.js');
server = http.createServer(app).listen(app.get('port'), function(){
done();
});
});
function clearCache() {
for (key in require.cache) {
if (key.indexOf(__dirname + '/node_modules/') == -1) {
delete require.cache[key];
}
}
}
It is ugly because of this require-cache-hack. However, it works.

Resources