Making a jest test file for mysql database calls - javascript

I'm very new to testing with Jest. I want to make a test to see if the following function returns user data from the database I have:
let dbConnect = require('../config/dbConnect');
let findUserByEmail = (email) => {
return new Promise(async (resolve, reject) => {
try {
dbConnect.query("SELECT * FROM user_login WHERE email = ?", email, function (error, results) {
if (error) reject(error);
let user = results[0];
if(user == undefined){
resolve()
}
resolve(user);
})
} catch (e) {
reject(e);
}
})
}
How would I go about making mock data to use in testing?
EDIT: Here is dbConnect:
let mysql = require('mysql');
let dotenv = require('dotenv');
dotenv.config({path: '../.env'});
let db = mysql.createConnection({
host: process.env.DATABASE_HOST,
database: process.env.DATABASE,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
});
db.connect(function (error) {
if (error) console.log(error);
else console.log("MYSQL Connected...");
});
module.exports = db;

Edit: fixed mistake
const mysql = require('mysql')
const mockQuery = jest.fn()
jest.mock('mysql', () => ({
createConnection: () => ({
connect: () => undefined,
query: mockQuery
}),
}))
describe('findUserByEmail', () => {
it('should resolve with the user when query suceeds', async () => {
mockQuery.mockImplementationOnce((sql, email, callback) => callback(null, ['TEST USER']));
expect(await findUserByEmail()).toBe('TEST USER');
})
});

Related

Lambda inconstant when querying my RDS database

When I go to test my code, the lambda does nothing, and at other times it runs my query and returns the data I have queried for. It's very inconsistent. It doesn't even give me an error. I am also using a proxy and that's not showing any errors. That's also not triggering.
I suspect it's something to do with the await/ async...
Here is my code:
async function RDSToken() {
vr signer = new AWS.RDS.Signer({
region: 'us-east-1',
hostname: 'proxy',
port: 3306,
username: 'username'
});
var host ='proxy'
var user ='username'
var db ='name'
let token = signer.getAuthToken({username: 'admin' });
let connectionConfig = {
host: host,
user: user,
database: db,
ssl: { rejectUnauthorized: false},
password: token,
authSwitchHandler: function ({pluginName, pluginData}, cb) {
console.log("Setting new auth handler.");
}
};
connectionConfig.authSwitchHandler = (data, cb) => {
if (data.pluginName === 'mysql_clear_password') {
let password = token + '\0';
let buffer = Buffer.from(password);
cb(null, password);
}};
try {
connection = await mysql2.createConnection(connectionConfig);
} catch(err) {
console.error('error connecting to the database');
console.error(err);
var response = {
statusCode: 500,
"headers": {
"Content-Type": "application/json"
},
body: 'error connecting to the database' +err
};
return response;
}
return connection
}
async function randomfact() {
var connection = await RDSToken();
let sql = 'SELECT * FROM quote_header;';
return await new Promise((resolve, reject) => {
connection.query(sql, (err, result) => {
if (err) {
reject(err);
}
else {
resolve(result);
}
});
});
}
async function Dashboard() {
const result = await randomfact();
console.log(result)
}
So I was correct there is something to do await/asnyc/promise.
Here is my updated code.
const connection = mysql2.createPool({
host: "host",
user: "admin",
password: "pw",
database : 'name',
waitForConnections: true,
connectionLimit: 3,
})
SelectAllElements = (connection) =>{
return new Promise((resolve, reject)=>{
connection.query('SELECT * FROM quote_header ', (error, elements)=>{
if(error){
return reject(error);
}
return resolve(elements);
});
});
};
async function Dashboard() {
try{
const result1 = await SelectAllElements(connection);
console.log(result1)
// here you can do something with the three results
} catch(error){
console.log(error)
}
}
But this works around 95% of the time. It doesn't like to work the first time I run the lambda but after then it works for a short time, then returns null again, then works again. I still dont understand what's causing it not to connect.

Convert Promise to async

I am trying to convert mySQL connection from promise to asycn await so far I have the following setup:
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
password: "",
user: "root",
database: "usersdb",
host: "localhost",
port: "3306",
});
let usersDB = {};
usersDB.all = () => {
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users", (err, results) => {
if (err) {
return reject(err);
}
return resolve(results);
});
});
};
usersDB.one = (id) => {
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users WHERE id = ?", [id], (err, results) => {
if (err) {
return reject(err);
}
return resolve(results[0]);
});
});
};
module.exports = usersDB;
Is there a way to convert this codes:
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users", (err, results) => {
if (err) {
return reject(err);
}
return resolve(results);
});
to async await and make the code more compress or succint?
UPDATE: on my router, I have these codes:
const router = express.Router();
router.get("/", async (req, res) => {
try {
let results = await db.all();
res.json(results);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
router.get("/:id", async (req, res) => {
try {
let results = await db.one(req.params.id);
res.json(results);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
So it just fine calling async await twice?
You can convert any callback function to promise by using util.promisify
const util = require('util')
// ....
const query = util.promisify(pool.query)
// ... inside some async function
const users = await query("SELECT * FROM users;")
// or promise style
query("SELECT * FROM users;")
.then((users) => {
console.log(users)
})
.catch(console.error)
usersDB.one = (id) => {
try {
const users = pool.query("SELECT * FROM users WHERE id = ?", [id]);
return users;
} catch (e) {
throw e;
}
};
Or more simply,
usersDB.one = (id) => pool.query("SELECT * FROM users WHERE id = ?", [id]);
What you want to do is to promisify the DB call. You can acheive this by factorisation :
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
password: "",
user: "root",
database: "usersdb",
host: "localhost",
port: "3306",
});
function promisify(...args){
return new Promise((resolve, reject) => {
pool.query(...args, (err, result) => {
if(err) reject(err);
resolve(result);
});
});
}
let usersDB = {};
//Then you can call it this way :
usersDB.all = async () => {
return await promisify("SELECT * FROM users");
//Note that you can avoid to await there.
};
usersDB.one = async (id) => {
return await promisify("SELECT * FROM users WHERE id = ?", [id]);
};
module.exports = usersDB;

learning and implementing async await

I've been reading about async and await in JS and tried to implement them in my code (which I totally messed up).
Here is my JS.
var express = require('express');
var router = express.Router();
var jsforce = require('jsforce');
const SEC_TOKEN = 'SEC_TOKEN';
const USER_ID = 'USER_ID';
const PASSWORD = 'PWD';
const { default: axios } = require('axios');
router.get("/", async (req, res, next) => {
await initConnect;
await soqlData;
await slackPostTest;
});
initConnect = async () => {
var conn = new jsforce.Connection({
loginUrl: 'https://login.salesforce.com'
});
await conn.login(USER_ID, PASSWORD + SEC_TOKEN, (err, userInfo) => {
if (err)
console.log(err);
else {
console.log(userInfo.Id);
}
});
}
soqlData = async () => {
await conn.query('Select Id, Name from Account LIMIT 1', (err, data) => {
if (err)
console.log(err);
else
return data.records[0];
})
}
slackPostTest = async () => {
await axios.post('SLACK_WEBHOOK', {
"text": "soqlRes"
})
}
module.exports = router;
What I am trying to achieve?
Initialize my connection by passing in SEC_TOKEN, USER_ID, PASSWORD to my initConnect function this will give me a connection (conn).
Use this conn and query my salesforce instance and get some other data.
post some message(currently irrelevant, but will hook up with the above response later) to my slack endpoint.
Also can someone please give me a little detailed explanation of the solution (in terms of async/await)?
Thanks
Assuming everything else about your JsForce API usage was correct (I have no experience with it, so I can't say), here's how to promisify those callback-based APIs and call them.
var express = require("express");
var router = express.Router();
var jsforce = require("jsforce");
const SEC_TOKEN = "SEC_TOKEN";
const USER_ID = "USER_ID";
const PASSWORD = "PWD";
const { default: axios } = require("axios");
router.get("/", async (req, res, next) => {
const { conn, userInfo } = await initConnect();
const data = await soqlData(
conn,
"Select Id, Name from Account LIMIT 1",
);
await slackPostTest(data.records[0]);
});
function initConnect() {
const conn = new jsforce.Connection({
loginUrl: "https://login.salesforce.com",
});
return new Promise((resolve, reject) => {
conn.login(USER_ID, PASSWORD + SEC_TOKEN, (err, userInfo) => {
if (err) return reject(err);
resolve({ conn, userInfo });
});
});
}
function soqlData(conn, query) {
return new Promise((resolve, reject) => {
conn.query(query, (err, data) => {
if (err) return reject(err);
resolve(data);
});
});
}
function slackPostTest(soqlRes) {
return axios.post("SLACK_WEBHOOK", {
text: soqlRes,
});
}
module.exports = router;

Can't to get connection to PostgreSQL from Node.js

During the launch my website i can't connection to my database. It doesn't get errors and the page is loading infinitely. Who know answer on this question give me some advise.
I work in (Node.js,PostgreSQL,Express)
from file config_db
const client_admin1 = {
user:'a_role',
database:'road_db',
password: '12345',
host:'localhost',
port:5432,
max:10,
idleTimeoutMillis: 30000
}
const pg = require("pg")
const client_login = require("../config/config_db");
searchUser(req, res) {
const db = new pg.Pool(client_login.client_admin1)
db.connect(function(err, client, done){
if(err){
return console.error('connection problems')
}
client.query('SELECT * FROM login_phone WHERE phone = $1 AND password1 = $2',[req.body.login, req.body.password], function(err, result){
done()
if (err || result.rowCount <= 0){
res.render('error_login_choice')
return console.error("")
}
if(result.rows[0].role_name === "client")
{
cln.getClients(req,res)
}
})
}
try this executeQuery method
const pg = require('pg');
const pgconfig = {
user: process.env.DATA_BASE_USER,
database: process.env.DATA_BASE_NAME,
password: process.env.DATA_BASE_PASSWORD,
host: process.env.DATA_BASE_HOST,
port: process.env.DATA_BASE_PORT,
};
console.log(`DB | Settings: ${JSON.stringify(pgconfig)}`);
const pool = new pg.Pool(pgconfig);
pool.on('connect', () => {
console.log('DB | new client connection establish.');
});
pool.on('error', err => {
console.error(`idle client error, ${err.message} | ${err.stack}`);
});
pool.connect(err => {
if (err) {
console.error(`PostgreSQL input: ${err}`);
} else console.log('DB | connection establish.');
});
const executeQuery = async(sql, data) => {
logger.debug(`sqlToDB() sql: ${sql} | data: ${data}`);
try {
const result = await pool.query(sql, data);
return result;
} catch (error) {
console.error(error.message);
}
};
module.exports = {
executeQuery,
};
usage:
const dbHandler = require('./db');
const getLogedInUser = login,password => {
const selectFieldsQuery = `'SELECT * FROM login_phone WHERE phone = $1 AND password1 = $2'`;
return dbHandler.executeQuery(selectFieldsQuery, [login,password]).then(e => e.rows);
};

How to properly use async await on a database query

This is the very basic route I am using:
router.get('/:date', async (req, res) => {
let tracks = []
let query = 'SELECT * from `tracks` where `playlistDate` = \''+req.params.date+'\''
let result = await pool.query(query)
console.log(result)
})
I know this by itself won't work, but what do I need to do to be able to use await on the query function like this?
This is the pool, with the credentials and addr changed.
var pool = mysql.createPool({
poolLimit : 10,
host : 'HOST',
user : 'USER',
password : 'PASS',
database : 'DB'
});
Maybe this logic would help. It depends on how you structured it.
var pool = mysql.createPool({
poolLimit : 10,
host : 'HOST',
user : 'USER',
password : 'PASS',
database : 'DB'
});
const getTracks = (date) => {
return new Promise((resolve, reject) => {
let query = 'SELECT * FROM tracks WHERE playlistDate = ?'
pool.query(query, [date], (err, res) => {
if (err) {
reject(err);
return;
}
resolve(res);
})
})
};
router.get('/:date', async (req, res) => {
try {
let tracks = await getTracks(req.params.date);
return res.status(200).json(tracks);
} catch (err) {
return res.status(400).json(err);
}
})

Categories