Unit testing for REST API using node Js - api

I want to write unit testing for my REST API calls(Using mocha and chai).
Can anyone provide me better guide or any previously written code ,so that I can perform easily.

There are multiple guides through internet to start with mocha and chai. As, for example, the official documentation:
Mocha documentation
Chai documentation
Using npm you can install both:
Mocha: npm install --save-dev mocha
Chai: npm install chai
Also, for HTTP you need chai-http: npm install chai-http
With this you can start to code your tests.
First of all, into your test file you need import packages
var chai = require('chai'), chaiHttp = require('chai-http');
chai.use(chaiHttp);
And also use the assertion you want, for example:
var expect = chai.expect;.
Tests use this schema:
describe('Test', () => {
it("test1", () => {
})
it("test2", () => {
})
})
Where describe is to declare a 'suite' of tests. And inside every suite you can place multiple tests, even another suite.
If you execute this code using mocha yourFile.js you will get:
Test
√ test1
√ test2
Now you can start to add routes to test. For example somthing like this:
it("test1", () => {
chai.request('yourURL')
.get('/yourEndpoint')
.query({value1: 'value1', value2: 'value2'})
.end(function (err, res) {
expect(err).to.be.null;
expect(res).to.have.status(200);
});
})
And if you want to use your own express app, you can use
var app = require('../your/app')
...
it("test1", () => {
chai.request(app)
...
}
...
And also exists multiple more options describe into Chai documentation.

Related

How do we use expect in WebdriverIO as a standalone script?

WebdriverIO has a sample of using it in a script:
https://webdriver.io/docs/gettingstarted#run-in-a-script
const { remote } = require('webdriverio');
;(async () => {
const browser = await remote({
capabilities: {
browserName: 'chrome'
}
})
await browser.url('https://webdriver.io')
const apiLink = await browser.$('=API')
await apiLink.click()
await browser.saveScreenshot('./screenshot.png')
await browser.deleteSession()
})()
However, there is no mentioning of how we can use expect, such as expect(elementFoo).toHaveText("Hello World") How can we have expect (and have one of mocha, jasmine, or cucumber like when we set up a webdriverio project using
npx wdio ./path/to/new/project
or is it already possible to use expect without using one of those three modules?)
Also, if we used npx wdio ./path/to/new/project to create a whole project, the expect(elementFoo).toHaveText("Hello World") knows how to wait a few seconds to finally say that it doesn't contain the text, which I am not sure if pure mocha, jasmine, or cucumber has that feature too.

Mocking multiple modules in single jest test

I am facing an issue in jest mocking. I can mock 1 module per test file but I am unable to mock multiple modules for single jest test.
E.x.
import mock1 from '../mockClass1';
import mock2 from '../mockClass2';
jest.mock('../mockClass1');
jest.mock('../mockClass2');
mock1.mockImplementation(() => {});
mock2.mockImplementation(() => {});
But this gives error as 1 of the mocks is not working. Is there a way of mocking both modules as I need them both in snapshot test of my class.
Use another mock-method. I suggest to mock the methods:
const mock1: any = {
methodToMock: jest.fn(() => {})
};

TestCafe 'dynamic' tests cases

I created a few e2e sanity tests for my current project using TestCafe. These tests are standard TestCafe tests:
fixture(`Basic checkout flow`)
test('Main Flow', async (t) => {
});
I would like to execute this test for multiple site locales and for multiple channels. i.e. I need this test to run for nl_nl, nl_be, en_gb, .. and also for channels like b2c, b2b, ...
The easiest way is to create a loop in the test itself to loop over the locales and channels, but I want to run these test concurrently.
I tried to create a function to dynamically generate these tests, but TestCafe can't seem to detect the tests then.
dynamicTest('Main Flow', async (t) => {
});
function dynamicTest(testName, testFn) => {
const channels = ['b2c']
channels.forEach((channel) => {
test(`[Channel] ${channel}] ${testName}`, testFn);
});
};
Is there a better way of doing this? The only solution I see is running the test script multiple times from Jenkins to have concurrency.
more detailed code:
import HomePage from '../../page/HomePage/HomePage';
import EnvUtil from '../../util/EnvUtil';
const wrapper = (config, testFn) => {
config.locales.forEach(async locale =>
config.channels.forEach(async channel => {
const tstConfig = {
locale,
channel
};
tstConfig.env = EnvUtil.parse(tstConfig, config.args.env);
testConfig.foo = await EnvUtil.get() // If I remove this line it works!
testFn(config, locale, channel)
})
);
};
fixture(`[Feature] Feature 1`)
.beforeEach(async t => {
t.ctx.pages = {
home: new HomePage(),
... more pages here
};
});
wrapper(global.config, (testConfig, locale, channel) => {
test
.before(async (t) => {
t.ctx.config = testConfig;
})
.page(`foo.bar.com`)
(`[Feature] [Locale: ${locale.key}] [Channel: ${channel.key}] Feature 1`, async (t) => {
await t.ctx.pages.home.header.search(t, '3301');
.. more test code here
});
});
If I run it like this I get a "test is undefined" error. Is there something wrong in the way I'm wrapping "test"?
Using TestCafe of version 0.23.1, you can run tests imported from external libraries or generated dynamically even if the test file you provide does not contain any tests.
You can learn more here: Run Dynamically Loaded Tests

Running Knex Migrations Between Mocha Tests

I was using Mocha to test my Nodejs app with a test database. In order to reset the DB before each test I had the following code, which worked perfectly:
process.env.NODE_ENV = 'test';
var knex = require('../db/knex');
describe("Add Item", function() {
beforeEach(function(done) {
knex.migrate.rollback()
.then(function() {
knex.migrate.latest()
.then(function() {
return knex.seed.run()
.then(function() {
done();
});
});
});
});
...
I've since switched from mocha to mocha-casperjs for my integration tests, and now the knex migrations won't run. I'm given this error message with the exact same before each hook:
undefined is not an object (evaluating 'knex.migrate.rollback')
phantomjs://platform/new-item.js:12:17
value#phantomjs://platform/mocha-casperjs.js:114:20
callFnAsync#phantomjs://platform/mocha.js:4314:12
run#phantomjs://platform/mocha.js:4266:18
next#phantomjs://platform/mocha.js:4630:13
phantomjs://platform/mocha.js:4652:9
timeslice#phantomjs://platform/mocha.js:12620:27
I'm pretty sure that migration functionality is not included in webpack build. If you go to http://knexjs.org/ open up debug console and checkout different clients e.g. mysql.migrate you see that there are no functions declared at all.
Actually you can check it out with node too if you explicitly load webpack build instead of node lib.
// load webpack build instead of node build...
let knex = require('knex/build/knex')({client : 'pg'});
console.log(knex.migrate);
// outputs: {}
So... the question is why are you trying to run your tests on PhantomJS browser instead of node.js?

Jasmine test makes no pass/fail report under webdriver.io

Running the following jasmine test under webdriver.io like this: node path/to/test/script.js, the test executes (web browser is pulled up, target page visited), and thanks to the last line, the jasmine 'it' functions (below) do execute (without the last line, they don't, although the 'describe' function still runs).
But jasmine doesn't provide any kind of report result for the 'it' tests and the 'expect' assertions; there's nothing on the console from jasmine. There's no 'pass/fail' result, and so forth.
How to get jasmine to make a report, and esp. one that is readable by Jenkins?
The problem test script:
var webdriverjs = require('foo-bar/node_modules/webdriverio');
var jasmine = require('foo-bar/node_modules/jasmine-node');
var options = {
port: 4445,
desiredCapabilities: {
browserName: process.argv[2] || 'phantomjs'
}
};
describe('my webdriverjs tests', function () {
var client;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 9999999;
beforeEach(function() {
client = webdriverjs.remote(options);
client.init();
});
it('shows the correct title', function (done) {
client
.url('http://localhost:4444').getTitle(function(err, title) {
expect(title).toBe('foo bar');
}).call( done );
});
afterEach(function(done) {
client.end(done);
});
});
jasmine.getEnv().execute();
Note: Cross-posted here: https://groups.google.com/forum/#!topic/webdriverio/-EOrQ003B9I
I ran into some of the same challenges when I was looking into this. The big issue is that this test needs to be executed as a jasmine test, not a webdriver test.
decribe('my webdriverio tests with jasmine', function(){
var client;
beforeEach(function(){
client = require('path/to/webdriverio').remote({
desiredCapabilities: {browserName:'safari'}
}).init.url('https://www.stackoverflow');
}, 5000);
afterEach(function(done){
client.end(done);
}, 5000);
it('runs a very simple test',function(done){
client.getTitle(function(err,result){
expect(result).toBe('Stack Overflow');
}).call(done);
}, 5000);
});
Now to run this test, you would just run a typical jasmine-node command from your terminal.
It comes down to the naming convention you are using. First, you need to remove the last line: jasmine.getEnv().execute(); then run the jasmine-node command with the --matchall flag:
jasmine-node --matchall path/to/test/script.js
If you named your file script_spec.js, then you could run it without the --matchall flag.
This is also assuming you have jasmine-node installed globally. If you want to use the local node_modules dependency, then you need to run this command:
./node_modules/jasmine-node/bin/jasmine-node --matchall path/to/test/script.js
When you are using jasmine-node module you should run your spec with
node_modules/jasmine-node/bin/jasmine-node $TEST_DIRECTORY
And your test should end with *spec.js, *spec.coffee or *spec.litcoffee as docs said.
And jasmine.getEnv().execute(); and var jasmine = require('foo-bar/node_modules/jasmine-node'); should not be in your script.