I'm trying to do some TDD with my following stack
Jest
Node
Koa2
SuperTest
Knex
Objection
My problem starts with the open handler of the koa server and I could solve that with the instance of the server and close it with server.close()
However, I have the same problem with knex; It leaves the server open and I have to run the knex.close to stop it. With that i can avoid the following error message
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't >stopped in your tests. Consider running Jest with --detectOpenHandles to >troubleshoot this issue.
knex.config
const config = {
development: {
client: 'pg',
connection: process.env.DATABASE_URL,
migrations:{
directory:"./migrations/"
},
pool: { min: 0, max: 7 }
},
test: {
client: 'pg',
connection: process.env.DATABASE_URL,
migrations:{
directory:"./migrations/"
},
pool: { min: 0, max: 7 }
},
//TBD
staging: {
client: 'postgresql',
connection: {
database: 'my_db',
user: 'username',
password: 'password'
},
pool: {
min: 2,
max: 10
},
migrations: {
tableName: 'knex_migrations'
}
},
//TBD
production: {
client: 'postgresql',
connection: {
database: 'my_db',
user: 'username',
password: 'password'
},
pool: {
min: 2,
max: 10
},
migrations: {
tableName: 'knex_migrations'
}
}
}
module.exports = config;
user.model.js
'use strict';
const knex = require('../config/db/knex');
const { Model } = require('objection');
Model.knex(knex);
class User extends Model {
// Table name is the only required property.
static get tableName() {
return 'user';
}
// Custom function to close knex
static close() {
knex.destroy();
}
}
module.exports = User;
user.test.js
const supertest = require('supertest');
const server = require('../../server');
var request = require("supertest").agent(server);
describe("Test users routes", () => {
let Model;
beforeAll(async () => {
// do something before anything else runs
console.log('Jest starting!');
Model = require('../../models/user.model')
});
// close the server after each test
afterAll(() => {
server.close();
Model.close();
console.log('server closed!');
});
test("Get /",async () => {
let res = await request.get('/users/');
expect(res.status).toBe(200);
});
});
I'm pretty sure it could be a better approach solution for what I did, maybe something related with the pool or some callback on the knex.cofing but I'm not sure.
Thank you
Related
I am using the nodemailer-express-handlebars extension to send nodemailer mail using .hbs (handlebars) extension files. I currently have the following folder structure:
-driver-adapter
-adapters
-nodemailer
-handlebars
regiterTemplate.hbs
-nodemailer-adapter.ts
But when I do the typescript build and try to send emails I get the following error
{
"data": {
"errno": -2,
"code": "ENOENT",
"syscall": "open",
"path": "/app/dist/infrastructure/driven-adapters/adapters/nodemailer/handlebars/resetPassword.hbs"
}
}
Going into the dist/ folder I see that I don't have the .hbs files and that's why it can't find them.
I am sharing the code that I am using for the generation and sending of the mail, I would like to understand why it is not taking the .hbs files when doing the build
export class NodeMailerAdapter implements ISendEmail {
private readonly transporter: Mail
constructor () {
const hbsConfig = {
viewEngine: {
extName: '.hbs',
partialsDir: path.join(__dirname, './handlebars/'),
layoutsDir: path.join(__dirname, './handlebars/'),
defaultLayout: ''
},
viewPath: path.join(__dirname, './handlebars/'),
extName: '.hbs'
}
this.transporter = nodemailer.createTransport({
host: CONFIG_NODEMAILER.host,
port: 2525,
auth: {
user: CONFIG_NODEMAILER.user,
pass: CONFIG_NODEMAILER.pass
}
})
this.transporter.use('compile', hbs(hbsConfig))
}
async sendMail (message: IMessage): Promise<string> {
const baseUrl = CONFIG_URL_BASE_TOKEN.baseUrl
const token = 'HERE_IS_TOKEN'
console.log(message)
const email = {
to: {
name: message.to.name,
address: message.to.email
},
from: {
name: CONFIG_EMAIL_SENDER.name,
address: CONFIG_EMAIL_SENDER.email
},
subject: message.subject,
template: 'resetPassword',
context: { baseUrl,token }
}
return await this.transporter.sendMail(email).catch(error => {
return error
})
}
}
I tried to bind MQTT with the react native. When trying to connect to the broker, when I run my code, After a few minutes I get the following error:
here is the error Object { "errorCode": 7, "errorMessage":
"AMQJS0007E Socket error:undefined.", "invocationContext":
undefined, }
import init from 'react_native_mqtt'
import AsyncStorage from '#react-native-async-storage/async-storage'
init({
size: 10000,
storageBackend: AsyncStorage,
defaultExpires: 1000 * 3600 * 24,
enableCache: true,
reconnect: true,
sync : {
}
});
constructor(){
super();
this.onConnect = this.onConnect.bind(this)
const client = new Paho.MQTT.Client('52.11.11.11', 1883, "clientId-" + parseInt(Math.random() * 100, 10));
client.connect({
onSuccess: this.onConnect,
userName: "user",
password: "pass",
onFailure: (e) => {console.log("here is the error" , e); }
});
this.state = {
message: [''],
client,
messageToSend:'',
isConnected: false,
};
}
onConnect = () => {
const { client } = this.state;
console.log("Connected!!!!");
this.setState({isConnected: true, error: ''})
};
We solved this by edit the mosquitto config file to either add a new listener port 8883 and to use the websocket protocol for that port
https://stackoverflow.com/a/32309525/12166187
I'm using Knex to connect to an Azure database, run a query that returns the status of a database (COPYING/ONLINE).
If I run this once, all is fine.
But if I use a setInterval to rerun this (I want to know when the status changes from COPYING to ONLINE) I'm getting a connection error the second, and third, and.. time the function is called.
Here is my code
const knex = require('knex')({
client: 'mssql',
connection: {
host: '***',
user: '***',
password: '***',
options: { requestTimeout: 350000, encrypt: true },
},
pool: {
min: 0,
max: 15,
},
});
async function copyStatus() {
try {
console.log('Running query');
const status = await knex.raw(
"SELECT name, state_desc FROM sys.databases WHERE name = 'Tide_QA_Dev_runtime' "
);
return status[0].state_desc;
// console.log(status[0].state_desc);
} catch (error) {
console.log(error);
} finally {
console.log('Closing connection with database');
await knex.destroy();
}
}
function intervalFunc() {
copyStatus().then(function (result) {
if (result === 'ONLINE') {
console.log('Database copy is done.');
} else if (result === 'Database is still copying') {
console.log('bezig');
}
});
}
setInterval(intervalFunc, 2000);
Here is my output
Closing connection with database
Database copy is done.
Running query
Error: Unable to acquire a connection
at Client_MSSQL.acquireConnection (/Users/davidbouckaert/Documents/Qite/TIDE_repo/node_modules/knex/lib/client.js:286:13)
at Runner.ensureConnection (/Users/davidbouckaert/Documents/Qite/TIDE_repo/node_modules/knex/lib/execution/runner.js:259:46)
at Runner.run (/Users/davidbouckaert/Documents/Qite/TIDE_repo/node_modules/knex/lib/execution/runner.js:30:30)
at Raw.Target.then (/Users/davidbouckaert/Documents/Qite/TIDE_repo/node_modules/knex/lib/builder-interface-augmenter.js:24:43)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
Closing connection with database
Running query
Error: Unable to acquire a connection
at Client_MSSQL.acquireConnection (/Users/davidbouckaert/Documents/Qite/TIDE_repo/node_modules/knex/lib/client.js:286:13)
at Runner.ensureConnection (/Users/davidbouckaert/Documents/Qite/TIDE_repo/node_modules/knex/lib/execution/runner.js:259:46)
at Runner.run (/Users/davidbouckaert/Documents/Qite/TIDE_repo/node_modules/knex/lib/execution/runner.js:30:30)
at Raw.Target.then (/Users/davidbouckaert/Documents/Qite/TIDE_repo/node_modules/knex/lib/builder-interface-augmenter.js:24:43)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
Closing connection with database```
It looks like the connection is made (see console log: Running query).
Any idea what's going on?
You should use code like below, it works for me.
const knex = require('knex')({
client: 'mssql',
connection: {
// no tcp:
server: 'j***2sqlserver.database.windows.net',
user: 'j***2',
password: 'J****0',
database: 'yourdbname',
port: 1433,
options: { requestTimeout: 350000, encrypt: true },
},
pool: {
min: 0,
max: 15,
},
});
My Test Result.
You should not call knex.destroy() if you are going to make more queries to the DB.
Move that knex.destroy() call to somewhere just before application is going to exit.
I'm trying to connect to SQL server using tedious connection pool and windows authentication. But I get an error:
message: 'Login failed for user \'\'.', code: 'ELOGIN'
I'm not sure what I'm doing wrong. I'm using the latest version of tedious.
.env file
SQL_SERVER=localhost
SQL_UNAME=Username
SQL_PSWD=Password
SQL_DB=DatabaseName
SQL_DOMAIN=US
dbController.js
const {Request} = require('tedious');
const TYPES = require('tedious').TYPES;
const ConnectionPool = require('tedious-connection-pool');
const dbConfig = require('./dbconfig');
const poolConfig = {
min: 1,
max: 1,
log: true
};
let _rows = [];
const pool = new ConnectionPool(poolConfig, dbConfig);
pool.on('error', (err) => {
console.log(err);
});
dbConfig.js
const dotenv = require('dotenv');
dotenv.config();
module.exports = {
server: process.env.SQL_SERVER,
options: {
instanceName: 'SQLEXPRESS',
encrypt: false,
database: process.env.SQL_DB,
rowCollectionOnDone: true,
useColumnNames: true
},
authentication: {
type: 'ntlm',
options: {
userName: process.env.SQL_UNAME,
password: process.env.SQL_PSWD,
domain: process.env.SQL_DOMAIN
}
}
};
The problem is tedious-connection-pool is using tedious version 1 instead of tedious version 9.
I'm hoping to solve that with tedious-connection-pool2 based on a PR I found that never got merged upstream.
So, wait a day, and find my tedious-connection-pool2 and use the overrideTedious option that should work.
I have this Sequelize Code for connecting to my database
var sequelize = new Sequelize('db-name', 'user', 'pwd', {
host: 'XXX.XX.XX.XXX',
dialect: 'mysql',
pool: {
max: 50,
min: 0,
idle: 1000000
},
});
I have wrapped this in a module like below
var express = require('express');
var app = module.exports = express();
var Sequelize = require('sequelize');
module.exports = function (Sequelize, DataTypes) {
return new Sequelize('db-name', 'user', 'pwd', {
host: 'XXX.XX.XX.XXX',
dialect: 'mysql',
pool: {
max: 50,
min: 0,
idle: 1000000
},
});
};
However ,when I call this code below:
var sequelize = require('../../Connection.js');
//load model
var City = sequelize.import('../../models/City.js');
It gives me an error saying - undefined is not a function.Basically it is not able to instantiate the sequelize object when I am importing the module
However everything works fine when I am putting these blocks in one page
My core requirement - I want a single connection object across my node app. I have modularized Express Routes in various page.
Your sequelize module exports a function, which returns sequelize. You have to actually call that function
var sequelize = require('../../Connection.js')() <-- ;
Remember to cache the instance in connection.js - otherwise you get a new connection each time. You can also export the instance directly:
module.exports = new Sequelize('db-name', 'user', 'pwd', {
host: 'XXX.XX.XX.XXX',
dialect: 'mysql',
pool: {
max: 50,
min: 0,
idle: 1000000
},
});