I have a simple supertest test using mocha like this.
describe("test", () =>{
it("Test 1", (done) =>{
let app = (new App()).express;
supertest(app).get("/").expect(200, done);
})
})
The test runs and passes but never shuts down mocha. I tried this.
describe("test", () =>{
it("Test 1", (done) =>{
let app = (new App()).express;
supertest(app).get("/").expect(200, ()=>{
app.close();
done();
});
})
})
But app.close is not declared and I am not rolling up a whole server. How do I get mocha to stop after the test?
Here is an minimal working example:
app.js:
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.sendStatus(200);
});
const port = 3000;
const server = app.listen(port, () => {
console.info(`HTTP server is listening on http://localhost:${port}`);
});
module.exports = server;
app.test.js:
const app = require("./app");
const supertest = require("supertest");
describe("test", () => {
after((done) => {
app.close(done);
});
it("Test 1", (done) => {
supertest(app)
.get("/")
.expect(200, done);
});
});
Integration test result with coverage report:
HTTP server is listening on http://localhost:3000
test
✓ Test 1
1 passing (23ms)
-------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
app.js | 100 | 100 | 100 | 100 | |
app.test.js | 100 | 100 | 100 | 100 | |
-------------|----------|----------|----------|----------|-------------------|
Start the HTTP server:
☁ mocha-chai-sinon-codelab [master] ⚡ node /Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/src/stackoverflow/53048031/app.js
HTTP server is listening on http://localhost:3000
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/53048031
use
$ mocha --exit
or add
"exit": true
in .mocharc
source: github link
Related
I'm trying to test my API and I'm having the following error:
Uncaught Error: listen EADDRINUSE: address already in use :::5000
this is my code:
test.ts
chai.use(chaiHttp)
describe('Persons', () => {
describe('GET /person/', () => {
it('check error path', (done) => {
chai
.request(startServer)
.get("/persons/")
.end((err, res) => {
res.should.have.status(422);
})
done();
});
});
// describe('GET /person/:firstName', () => {
it('It should person by first name', (done) => {
chai
.request(startServer)
.get("/persons/Ross")
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('string');
// res.header["content-type"].should.contains('application/json');
})
done();
});
// });
});
server.ts
import express, { Application } from "express";
import personRouter from "./route/person.route";
import groupRouter from "./route/group.route";
import bodyParser from "body-parser";
const app: Application = express();
const PORT: Number | string = process.env.NODE_ENV || 5000;
app.use(bodyParser.json());
app.use('/person', personRouter)
app.use('/group', groupRouter)
export function startServer() {
app.listen(PORT, () => {
console.log(`Server started on http://localhost:${PORT}`);
});
}
what am I doing wrong?
I ran the server from a diffrent place and then I did this:
describe('Persons', () => {
const host = "http://localhost:5000/person/";
describe('GET /person/', () => {
it('check error path', (done) => {
chai
.request(host)
.get("/persons/")
.end((err, res) => {
res.should.have.status(200);
})
done();
});
});
This way the server is not trying to start evry test.
I have built a simple koa framework application.After adding routes am trying to hit the /health GET route. It throws the below error:
TypeError: next is not a function
at cookieParser (c:\Userxxs\x\gimt\dp-my-app\node_modules\cookie-parser\index.js:46:14)
at dispatch (c:\Users\B748806a\gimt\dp-my-app\node_modules\koa-compose\index.js:42:32)
at bodyParser (c:\Users\B748806a\gimt\dp-my-app\node_modules\koa-bodyparser\index.js:95:11)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Below are the files and their order of execution:
server.js
const app = require("./app.js");
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`));
app.js
"use strict";
const koa = require('koa');
const koaRouter = require('koa-router');
const app = new koa();
const router = new koaRouter();
const middleware = require("./src/main/middlewares/middlewares");
const routes = require("./src/main/middlewares/route-path");
const init = async () => {
try {
/**
* Step 2: load endpoint routes for the application
*/
routes(router)
} catch (err) {
logger.error({
err
});
}
};
/**
* Step 1: load middleware setup - cors,helmet from KP Spring cloud service
*/
middleware(app);
init();
module.exports = app
middleware.js
const koa = require("koa");
const koaRouter = require('koa-router');
const router = new koaRouter();
const cors = require("koa-cors");
const compression = require("koa-compress");
const helmet = require("koa-helmet");
const cookieParser = require("cookie-parser");
const bodyParser = require('koa-bodyparser')
const ActuatorRouter = require('pm-js-actuator').koa //internal library
const ACTUATOR_OPTIONS = {
health: {
enabled: true
},
livenessprobe: {
enabled: true
},
env: {
enabled: false
},
info: {
enabled: true,
secure: false
}
}
function middleware(app) {
// Use the CORS for the time being.
app.use(cors())
// Let's don the security helmet
app.use(helmet())
app.use(helmet.frameguard())
app.use(helmet.ieNoOpen())
app.use(helmet.frameguard({
action: 'sameorigin'
}))
app.use(helmet.noSniff())
app.use(helmet.referrerPolicy({
policy: 'same-origin'
}))
app.use(helmet.xssFilter())
//app.disable('x-powered-by')
app.use(ActuatorRouter.getRouter(ACTUATOR_OPTIONS).routes())
app.use(bodyParser())
app.use(cookieParser());
// Set up compression
app.use(compression());
}
module.exports = middleware;
route-path.js
const RootHeathController = require("../controller/root-health-controller")
const routes = (router) => {
router.get("/health", RootHeathController.handler)
};
module.exports = routes
root-health-controller.js
const handler = async (ctx, next) => {
ctx.body="Hi";
}
module.exports = {
handler
};
The application is started successfully on port 3000. But when i hit, /health from postman, it throws the mentioned error. Any solution?
The problem here is, that cookie-parser seems to be an express - thing (see also repo url: https://github.com/expressjs/cookie-parser). So to test this I created a minimal version of your code:
const koa = require('koa');
const koaRouter = require('koa-router');
const bodyParser = require('koa-bodyparser');
const cookieParser = require("cookie-parser");
const app = new koa();
app.use(bodyParser());
app.use(cookieParser()); // <-- comment this line
const router = new koaRouter();
router.get("/health", async (ctx, next) => {
ctx.body = 'hi';
});
app.use(router.routes());
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`));
Calling the localist:3000/health endpoint throws the same error. But if you comment the app.use(cookie-parser()) line all works fine.
The question is, why you would need this library? You should be able to set and get cookies in koa with ctx.cookies.get and ctx.cookies.set
I am getting this error in my heroku logs.
Same Question
All the solutions provided here did not address the issue.
I tried the different variations of the get method:
app.use(express.static('build'));
app.get('*', function (req, res) {
res.sendFile('index.html');
});
What else could I try or am I missing from here?
App.js
const configuration = require('#feathersjs/configuration');
const feathers = require('#feathersjs/feathers');
const express = require('#feathersjs/express');
const socketio = require('#feathersjs/socketio');
const moment = require('moment');
class IdeaService {
constructor() {
this.ideas = [];
}
async find() {
return this.ideas;
}
async create(data) {
const idea = {
id: this.ideas.length,
text: data.text,
tech: data.tech,
viewer: data.viewer
};
idea.time = moment().format('h:mm:ss a');
this.ideas.push(idea);
return idea;
}
}
const app = express(feathers());
app.feathers().configure(configuration());
app.use(express.static('build'));
app.get('*', function (req, res) {
res.sendFile('index.html');
});
// Parse JSON
app.use(express.json());
// Configure SocketIO realtime API
app.configure(socketio());
// Enable REST services
app.configure(express.rest());
// Register services
app.use('/ideas', new IdeaService());
// Connect new streams
app.on('connection', conn => app.channel('stream').join(conn));
// Publish events to stream
app.publish(data => app.channel('stream'));
const PORT = process.env.PORT || 3030;
app.listen(PORT).on('listening', () => console.log(`Server running on port ${PORT}`));
app.service('ideas').create({
text: 'Build a cool app',
tech: 'Node.js',
viewer: 'John Doe'
});
export default IdeaService;
package.json
I have a socket emit function which has acknowledge function as
socket.emit('ferret', 'tobi', (data) => {
const a = 5;
this.sum(a,data);
});
I want to have a test that covers the line const a = 5; and this.sum(a,data);
In order to testing easily, you should make a little refactor about your code like this:
index.ts:
import { socket } from './socket';
export const obj = {
someMethod() {
this.handleFerret = this.handleFerret.bind(this);
socket.emit('ferret', 'tobi', this.handleFerret);
},
handleFerret(data) {
const a = 5;
this.sum(a, data);
},
sum(a, b) {
//
}
};
socket.ts: simulate socket.io module, you can replace it with socket.io
export const socket = {
emit(event, data, callback) {
// real implemetation
}
};
index.spec.ts:
import { obj } from './';
import { socket } from './socket';
describe('obj', () => {
it('should emit event and execute callback correctly', () => {
const emitSpy = jest.spyOn(socket, 'emit');
obj.someMethod();
expect(emitSpy).toBeCalledWith('ferret', 'tobi', obj.handleFerret);
});
it('should handle ferret correctly', () => {
const sumSpy = jest.spyOn(obj, 'sum');
obj.handleFerret(2);
expect(sumSpy).toBeCalledWith(5, 2);
});
});
Unit test result with 100% coverage report:
PASS src/stackoverflow/57461614/index.spec.ts (12.977s)
obj
✓ should emit event and execute callback correctly (13ms)
✓ should handle ferret correctly (1ms)
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
socket.ts | 100 | 100 | 100 | 100 | |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 14.159s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57461614
I am trying to test that redux actions are fired when the finish event on my upload object is fired.
Here's my epic:
const uploadFileEpic = (action$, state$, dependencies$) =>
action$.pipe(
ofType(uploadActions.UPLOAD_FILE),
mergeMap(({ payload }) => {
const { file, masterHandle } = payload;
return new Observable(o => {
const upload = masterHandle.uploadFile("/", file);
const handle = upload.handle;
upload.on("finish", () => {
o.next(
uploadActions.uploadSuccess({
masterHandle
})
);
o.complete();
});
});
})
);
Here is what I have written so far. It doesn't work:
import { of } from "rxjs";
import "rxjs/add/operator/toArray";
import { EventEmitter } from "events";
import uploadActions from "../actions/upload-actions";
import uploadEpic from "./upload-epic";
test("uploadFilesEpic filesActions.UPLOAD_FILE on success", done => {
const file = { name: "f1" };
const upload = new EventEmitter();
upload.handle = "h1";
const masterHandle = {
uploadFile: jest.fn(() => upload)
};
const action$ = of(uploadActions.uploadFile({ file, masterHandle }));
upload.emit("finish");
uploadEpic(action$).subscribe(actions => {
expect(actions).toEqual(uploadActions.uploadSuccess({ masterHandle }));
done();
});
});
It says the async callback was not fired:
FAIL src/redux/epics/upload-epic.test.js (8.531s)
✓ uploadFilesEpic filesActions.UPLOAD_FILES (9ms)
✕ uploadFilesEpic filesActions.UPLOAD_FILE on success (5021ms)
● uploadFilesEpic filesActions.UPLOAD_FILE on success
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Error:
23 | });
24 |
> 25 | test("uploadFilesEpic filesActions.UPLOAD_FILE on success", done => {
| ^
26 | const file = { name: "f1" };
27 | const upload = new EventEmitter();
28 | upload.handle = "h1";
at new Spec (node_modules/jest-config/node_modules/jest-jasmine2/build/jasmine/Spec.js:116:22)
at Object.test (src/redux/epics/upload-epic.test.js:25:1)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 passed, 2 total
Snapshots: 0 total
Time: 9.297s
It makes sense to me that the test is failing but I'm not sure how to subscribe to the epic, fire the finish event, and then inspect the actions returned by the epic.
The event for finishing the upload is emitted too early in the test. The EventEmitter does not keep a buffer of events and if no one is subscribed, then the even is lost.
Move the emit "finish" to the bottom of the test.
upload.emit("finish"); // must emit after subscribing