jest-puppeteer on bitbucket / no exit, stuck on success - jestjs

Running jest-puppeteer with the following express config :
import express from "express";
import path from "path";
import webpack from 'webpack';
import config from '../webpack.config';
const port = 3200;
const app = express();
const compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath
}));
app.listen(port, function (error) {
if(error) console.log(error);
});
with the following simple test :
describe('Google', () => {
beforeAll(async () => {
await page.goto('http://localhost:3200')
})
it('should display "demo" text on page', async (done) => {
await expect(page).toMatch('Your cart');
done();
});
});
The jest-puppeteer config is the following :
module.exports = {
server: {
command: './node_modules/babel-watch/babel-watch.js ./test/server.js',
port: 3200,
},
};
I'm having trouble on my bitbucket pipeline; all tests are passing but the commands never exits
What would be the reason for it being stuck ? Is the webpack conf involved ?
Just ran the very same test scripts on semaphore, everything works smoothly
thx a lot for any advised answers

Related

socket.io not working in after migrating my .js file to .ts file

I built a chat app with node js but when I migrated my code to typescript, the socket.io stopped working.
Below is my index.ts file
import express, { Express, Request, Response } from "express"
import mysql from "mysql"
import { createServer } from "http"
import { Server } from "socket.io"
import dotenv from 'dotenv';
dotenv.config();
const app: Express = express(),
users: any[] = [],
http=createServer(app),
conn = mysql.createConnection({
host : process.env.DATABASE_HOST,
user : process.env.DATABASE_USER,
password : process.env.DATABASE_PASSWORD,
database : process.env.DATABASE_NAME
}),
socketIO= new Server(http, { cors: { origin:"*" } })
app.use(express.static('public'));
conn.connect((error:any)=>console.log(`Database Connected: ${error}`))
app.get('/', (req:Request, res:Response) => res.sendFile(__dirname + '/index.html'));
app.post('/', (req:Request, res:Response) => conn.query(`SELECT * FROM users ORDER BY name ASC`, (error:any, all_users:any)=> res.send({data:all_users})));
socketIO.on("conn", (socket:any)=>{
socket.on("connected", (my_id:any)=>{
users[my_id] = socket.id
console.log("connected")
})
})
http.listen(process.env.PORT, ()=>console.log(`Server listening on port http://localhost:${process.env.PORT}`))
Below is the code for my frontend javascript file
$(document).ready(function(){
let socketIO=io(), my_id=prompt("Enter your user ID")
if (my_id) {
socketIO.emit("connected", my_id)
$.post("http://localhost:3000", resp=>{
})
$("body").on("click", ".send-msg", function(e){
e.preventDefault()
let msg = prompt("Enter Your Message")
console.log(msg)
if(msg) socketIO.emit("send_msg", { my_id, user_id: $(this).data("id"), msg})
})
socketIO.on("msg_receved", resp=>$(".msg").append(`<li class="text-uppercase"> ${resp.user}: <strong>${resp.msg}</strong></li>`))
}
})
I cannot recieve messages or send messages to any user, please what am I doing wrong, I am still new to typescript

Socket.io is not connecting to my Express.js server

I am trying to get Socket.io to connect to my Express.js server but I haven't been able to successfully connect them despite closely following the examples given on the Socket.io website and other code I have been using for reference.
When I try socket.on('connect', console.log(socket.connected)) on the client side it always returns false and when I log the connect_error it returns server error with the following traceback:
Error: server error
at Socket.onPacket (socket.js:317:1)
at XHR.push../node_modules/#socket.io/component-emitter/index.js.Emitter.emit (index.js:143:1)
at XHR.onPacket (transport.js:100:1)
at callback (polling.js:83:1)
at Array.forEach (<anonymous>)
at XHR.onData (polling.js:86:1)
at Request.push../node_modules/#socket.io/component-emitter/index.js.Emitter.emit (index.js:143:1)
at Request.onData (polling-xhr.js:188:1)
at Request.onLoad (polling-xhr.js:229:1)
at XMLHttpRequest.xhr.onreadystatechange (polling-xhr.js:147:1)
These are the relevant parts of my index.js server file on the backend:
const express = require('express');
const cors = require('cors');
const app = express();
// /db/session is express-session related code
const session = require('./db/session');
const { createServer } = require('http');
const { Server } = require('socket.io');
const PORT = process.env.PORT || 5000;
const httpServer = createServer(app);
app.use(cors({
// DEV_ORIGIN is http://localhost:3000
origin: process.env.DEV_ORIGIN,
credentials: true,
}));
const io = new Server(httpServer, {
cors: {
origin: process.env.DEV_ORIGIN,
methods: ["GET", "POST"],
credentials: true
}
});
app.use(session);
io.use((socket, next) => {
session(socket.request, {}, next);
});
httpServer.listen(PORT, () => console.log(`Server running on port ${PORT}`));
// this never seems to do anything
io.on('connection', function() {
console.log('Connected')
});
Here is the main file I have on the client side for the Socket.io connection:
import io from 'socket.io-client';
// API_ORIGIN is http://localhost:5000
export let socket = io(process.env.API_ORIGIN, {
withCredentials: true,
autoConnect: true,
});
I am testing using the socket from this file in a component like so:
import { socket } from '../../services/socket.js';
import React, { useEffect } from 'react';
export default function Lobby() {
useEffect(() => {
socket.on('connect',
console.log(socket.connected)
)
socket.on('connect_error', (err) => {
console.log(err)
});
}, [])
}
But as I mentioned above, socket.connected always returns false. I would really appreciate your help!
I managed to resolve it. The issue was caused by process.env.API_ORIGIN. By changing the code as follows, I was able to get it to work.
The new client side socket.io file:
import { io } from "socket.io-client";
import { serverAddress } from "../settings";
export let socket = io(serverAddress, {
withCredentials: true,
autoConnect: true,
});
and the settings file I created:
const LOCAL_ADDRESS = 'http://localhost:5000';
const PRODUCTION_ADDRESS = [PRODUCTION URL HERE]
export const devEnv = process.env.REACT_APP_ENV === 'development';
export const serverAddress = devEnv? LOCAL_ADDRESS : PRODUCTION_ADDRESS;

Ensure express app is running before starting mocha tests

I built an API for a couchbase database, using express and node.js. My problem is that when I run my tests some of them fail, because the server is not fully running. I found a solution here https://mrvautin.com/ensure-express-app-started-before-tests on how to solve this issue. The article stated that in order to solve this issue, you have to add an event emitter in your server file like this
app.listen(app_port, app_host, function () {
console.log('App has started');
app.emit("appStarted");
});
and then add this, in your test file
before(function (done) {
app.on("appStarted", function(){
done();
});
});
I have tried this, here is my implementation
Server File
app.listen(config['server']['port'], function(){
app.emit("appStarted");
logger.info("Listening")
})
Test File
before(function(done){
app.on("appStarted", function(){
done();
})
});
I keep on getting the following error
1) "before all" hook in "{root}":
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)
The article is from 2016, so I was thinking that maybe the syntax has been deprecated. I was wondering if someone could please help point me in the right direction?
You can add the below condition, more info see "Accessing the main module".
if (require.main === module) {
// this module was run directly from the command line as in node xxx.js
} else {
// this module was not run directly from the command line and probably loaded by something else
}
E.g.
index.ts:
import express from 'express';
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.sendStatus(200);
});
if (require.main === module) {
app.listen(port, () => {
console.log('App has started');
});
}
export { app, port };
index.test.ts:
import { app, port } from './';
import http from 'http';
import request from 'supertest';
describe('63822664', () => {
let server: http.Server;
before((done) => {
server = app.listen(port, () => {
console.log('App has started');
done();
});
});
after((done) => {
server.close(done);
console.log('App has closed');
});
it('should pass', () => {
return request(server)
.get('/')
.expect(200);
});
});
integration test result:
(node:22869) ExperimentalWarning: The fs.promises API is experimental
63822664
App has started
✓ should pass
App has closed
1 passing (26ms)
!Hi World! My little solution here:
Check this: All depends of your testing markup...
For example, I'm using Mocha and Chai Assertion Library.
const express = require('express');
const request = require("request");
const http = require("http");
const expect = require("chai").expect;
require('dotenv').config();
describe('Server', function() {
const { PORT } = process.env;
const app = express();
before((done) => {
http.Server = app.listen(PORT, () => {
console.log(`Listening Node.js server on port: ${PORT}`);
done();
});
});
it('should return 404 response code status', () => {
const url = `http://localhost:${PORT}/api/v1/yourPath`;
return request(url, (err, response, body) => {
/* Note this result 'cause I don't have any get('/')
controller o function to return another code status
*/
expect(response.statusCode).to.equal(404);
});
})
});

Simple node http server unit test

I created a NodeJs http server in TypeScript and I've unit tested everything with Jest, except the base class, the server itself:
import { createServer} from 'http';
export class Server {
public startServer() {
createServer(async (req, res) => {
if(req.url == 'case1') {
// do case1 stuff
}
if(req.url == 'case2') {
// do case2 stuff
}
res.end();
}).listen(8080);
}
}
I'm trying this approach:
import { Server } from '../../../src/app/Server/Server';
import * as http from 'http';
describe('Server test suite', () => {
function fakeCreateServer() {
return {}
}
test('start server', () => {
const serverSpy = jest.spyOn(http, 'createServer').mockImplementation(fakeCreateServer);
const server = new Server().startServer();
expect(serverSpy).toBeCalled();
});
});
Is there a way a can create a valid fake implementation for the 'createServer' method?
And maybe simulate some requests?
Thanks a lot!
What logic do you want to test here?
Such a simple server is declarative enough to keep it without unit tests.
If you want to test that createServer is invoked
just mock http module by jest.mock('http');
Such expressions are lifted up by jest to give them precedence over regular imports.
https://jestjs.io/docs/en/mock-functions#mocking-modules
import { Server } from '../../../src/app/Server/Server';
import * as http from 'http';
jest.mock('http', () => ({
createServer: jest.fn(() => ({ listen: jest.fn() })),
}));
describe('Server', () => {
it('should create server on port 8080', () => {
const server = new Server().startServer();
expect(http.createServer).toBeCalled();
});
});
Maybe you should approach your class and tests a little bit differently.
Nodejs http.createServer returns a server instance. The server instance has a property listening (true if the server is listening for the requests), so you could return the server instance from the startServer method and test server.listening property.
Also, if you want to test for different responses and requests to your server, I would suggest you use supertest
// server.js - it also works with plain HTTP
const app = express();
app.get('/user', function(req, res) {
res.status(200).json({ name: 'john' });
});
module.export = app
// test.js
const request = require('supertest');
const app = require('./server.js')
describe('GET /user', function() {
it('responds with json', function(done) {
request(app)
.get('/user')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200, done);
});
});

Error handling with Typescript and Express in Node.js

I'm starting with Node and Typescript and I have a question.
I have these 2 files.
server.ts
import express = require('express');
import IConfiguration from "../config/config";
export default class Server {
public app: express.Application;
public configuration: IConfiguration;
constructor( configuration: IConfiguration ) {
this.configuration = configuration;
this.app = express();
}
static init(configuration: IConfiguration) {
return new Server(configuration);
}
start(callback: Function) {
this.app.listen(this.configuration.port, callback());
this.app.use(express.static(this.configuration.public_path))
}
}
index.ts
import Server from './server/server';
import Configuration from "./config/config";
import * as dotenv from 'dotenv';
import router from './router/router';
//Loading .env file
dotenv.config();
//Init config
const configuration = Configuration.init();
//Init server
const server = Server.init(configuration);
server.app.use(router);
server.start(() => {
console.log('Server running at port ' + configuration.port);
});
In index.ts I have the app.listen callback on start function, but I dont know how write this error handling for capture the errors.
How I can add this .on("error") on my callback function?
server.start(() => {
console.log('Listening on port: ', port);
}).on('error', (e) => {
console.log('Error happened: ', e.message)
});
I have tried put this in my index.ts but I get this error:
"Property 'on' does not exist on type 'void'"
Your server variable is an instance of your Server class and when you call start it does not return anything, it just implicitly returns undefined (or void in Typescript terms) and undefined surely does not have on method, so you cannot chain it like that. This is what error message says, basically.
What you can do is return this.app from start method, for example.
start(callback: Function) {
this.app.listen(this.configuration.port, callback());
this.app.use(express.static(this.configuration.public_path))
return this.app;
}
Or separate this two line like this:
server.start(() => {
console.log('Listening on port: ', port);
});
server.app.on('error', (e) => {
console.log('Error happened: ', e.message)
});
you cannot pass "err" to app.listen in express. I think you guys are confusing with http server:
const http = require('http');
const server = http.createServer(app);
server.on('error', (err) => {
if (err) {
console.log(err);
}
});
server.listen(PORT, () => {
console.log('Running')
});

Resources