I cannot implement an async function - node.js

I've started working with protractor-cucumber automation testing (https://github.com/mlev/protractor-cucumber-example), previously in one of my other projects I had no issue implementing async await functions, however, in this case I cannot.
This is my current semi-working (protractor outpust completed for all tasks, however it will not wait at browser.sleep) code:
I have tried nodes async await libary and the following code:
this.get = async function someName(){
await browser.get('https://translate.google.com/');
};
this.Given('The Translate is open', async function (callback) {
await this.page.get();
callback();
}
StepsDef:
var chai = require('chai').use(require('chai-as-promised'));
var expect = chai.expect;
var TranslateSteps = function() {
var TranslatePage = require("../pages/translate_page");
this.World = function MyWorld() {
this.page = new TranslatePage();
};
this.Given('The Translate is open', function (callback) {
this.page.get();
callback();
}
)
this.Then('I wait $string seconds', function (string) {
browser.sleep(string * 10000)
}
};
module.exports = TranslateSteps;
Page:
var TranslatePage = function() {
this.get = function (){
browser.get('https://translate.google.com/');
};
this.setInputBox = function (value) {
element(by.className("gt-hl-layer")).sendKeys(value)
console.log("setInput")
};
this.clickLang = function () {
element(by.className("sl-more tlid-open-source-language-list")).click()
console.log("clickLang")
}
};
module.exports = TranslatePage;
most of the time I got error code 1 or 100, at times i got no 199.

Firstly make sure that you disable promise manager by adding this SELENIUM_PROMISE_MANAGER: false line in the protractor.conf.js file.
You don't need to use the callback function.
this.get = async function() {
await browser.get('https://translate.google.com/');
};
this.Given('The Translate is open', async function() {
await this.page.get();
});
As I said above you don't need the callback function. Alson the sleep method expects number type instead of the string.
var TranslateSteps = function() {
var TranslatePage = require("../pages/translate_page");
this.World = function MyWorld() {
this.page = new TranslatePage();
};
this.Given('The Translate is open', async function() {
await this.page.get();
});
this.Then('I wait {num} seconds', async function(num) {
await browser.sleep(num * 10000)
});
};
Add async/await's.
var TranslatePage = function() {
this.get = async function() {
await browser.get('https://translate.google.com/');
};
this.setInputBox = async function(value) {
await element(by.className("gt-hl-layer")).sendKeys(value)
await console.log("setInput")
};
this.clickLang = async function() {
await element(by.className("sl-more tlid-open-source-language-list")).click()
await console.log("clickLang")
}
};
module.exports = TranslatePage;

this.When('I enter $string', async function myF(string) {
await this.page.setFirstValue(string);
return true;
});
and:
this.setFirstValue = async function asd(value) {
await element(by.className('orig tlid-source-text-input goog-textarea')).sendKeys(value);
};
works like a charm

Related

async/await troubles in a recursive Redis function

Ima rookie using async/await but must now to use Redis-om. NN_walkd walks through a Redis database looking for loop-chains and does this by recursion. So the 2 questions I have is:
Am I calling the inner recursive NN_walkd calls correctly via async/await?
At runtime, the compSearchM proc is called first and seems to work (it gets 5 entries so it has to call NN_walkd 5 times). A NN_walkd is then recursively called, and then when it loops the 1st time it then calls compSearchK where the problems are. It seems to sit on the first Redis call in compSearchK (.search). Yet the code for compSearchK and compSearchM look basically identical.
main call
NN_walk = async function(req, db, cnode, pnode, chain, cb) {
var vegas, sneaker;
req.session.walk = [];
await NN_walkd(req, cnode, pnode, [], 1);
req.session.walk = null;
console.log('~~~~~~~~~~~~ Out of Walk ~~~~~~~~~~~~~~~');
cb();
};
redis.mjs
export class RedisDB {
constructor() {
...
this._companyRepo = ...
}
compSearchK(ckey) { // doesn't matter if I have a async or not here
return new Promise(async (resolve) => {
const sckey = await this._companyRepo.search()
.where('COMPANYKEY').equals(ckey)
.return.all();
if (sckey.length) {
const ttrr = await this._companyRepo.fetch(sckey[0].entityId);
resolve(ttrr.toJSON());
} else
resolve(null);
});
}
compSearchM(mkey) {
var tArr=[];
return new Promise(async (resolve) => {
const smkey = await this._companyRepo.search()
.where('MASTERKEY').equals(mkey)
.and('TBLNUM').equals(10)
.return.all();
if (smkey.length) {
for (var spot in smkey) {
const ttrr = await this._companyRepo.fetch(smkey[spot].entityId);
tArr.push(ttrr.toJSON());
}
resolve(tArr);
} else {
resolve(null);
}
});
}
walk.js
NN_walkd = async function(req, cnode, pnode, chain, lvl) {
...
if (cnode[1]) {
const sObj = await req.app.get('redis').compSearchK(cnode[1]);
if (sObj) {
int1 = (sObj.TBLNUM==1) ? null : sObj.CLIENTKEY;
(async () => await NN_walkd(req, [sObj.COMPANYKEY,int1], cnode, Array.from(chain), tlvl))()
}
} else {
const sArr = await req.app.get('redis').compSearchM(cnode[0]);
if (sArr.length) {
for (sneaker in sArr) {
(async () => await NN_walkd(req, [sArr[sneaker].COMPANYKEY,sArr[sneaker].CLIENTKEY], cnode, Array.from(chain), tlvl))()
}
} else {
console.log('no more links on this chain: ',cnode);
}
}
}
"doesn't matter if i have async or not here"
compSearchK(ckey) { // doesn't matter if I have a async or not here
return new Promise(async (resolve) => {
const sckey = await this._companyRepo.search()
.where('COMPANYKEY').equals(ckey)
.return.all();
if (sckey.length) {
const ttrr = await this._companyRepo.fetch(sckey[0].entityId);
resolve(ttrr.toJSON());
} else
resolve(null);
});
}
Of course it doesn't matter, because you're not using await inside of compSearchK!
You are using the explicit promise contructor anti-pattern. You should avoid it as it demonstrates lack of understanding. Here is compSearchK rewritten without the anti-pattern -
async compSearchK(ckey) {
// await key
const sckey =
await this._companyRepo.search()
.where('COMPANYKEY').equals(ckey)
.return.all();
// return null if key is not found
if (sckey.length == 0) return null;
// otherwise get ttrr
const ttrr = await this._companyRepo.fetch(sckey[0].entityId);
// return ttrr as json
return ttrr.toJSON();
}

Return a promise in a node.js module

I want to return the data once it has been processed by convertToHtml, but it just return the data before the converting process is over. Any suggestions on how to implement it?
exports.extractData = async function(path) {
var mammoth = require("mammoth");
return await mammoth.convertToHtml({path: path}, options)
.then(function(result) {
var html = result.value;
var messages = result.messages;
return html;
}
}
Based on the suggestion I changed to:
exports.extractData = async function(path) {
var mammoth = require("mammoth");
const aux = await mammoth.convertToHtml({path: path}, options);
return aux.value;
}
}
Yet, I am getting:
Promise { <pending> }
I call the module like this:
var x = require("./index");
console.log(x.extractWord('docx'));
How can I obtain the result?
Thanks
Any async function returns a promise: you need to await your async function, something like this:
Give your module:
const mammoth = require("mammoth");
exports.extractData = async function(path) {
const aux = await mammoth.convertToHtml({path: path}, options);
return aux.value;
}
You can then say something like this:
const {extractData} = require('whatever-my-module-name-is');
async function main() {
const extractedData = await extractData();
process( extractedData ) ;
}
main()
.then( () => process.exit(0) )
.catch( err => {
console.error(err);
process.exit(1);
});
You don't need .then when you are using async/await. async/await is just a neat replacement for promises, you shouldn't use them together
exports.extractData = async function(path) {
var mammoth = require("mammoth");
return await mammoth.convertToHtml({path: path}, options);
}

Mocha Tests Running Before Docs Defined in Before Block Are Done

I am creating some mocha tests for my Node app. In my test, before retrieving some docs that are created, I need to first create those docs in the database. Then I retrieve them and run some tests on the results.
The problem I'm noticing is that even though I've included the function that needs to run to create the docs in the first before() block, and even though I'm awaiting the result of the doc creation function, my tests run BEFORE the docs are finished being created. It seems the before() block doesn't do quite what I think it does.
How can I rectify this to ensure the doc creation has finished BEFORE the test checks run?
const seedJobs = require('./seeder').seedJobs;
const MongoClient = require('mongodb').MongoClient;
const client = new MongoClient(`${url}${dbName}${auth}`);
describe("Seeding Script", async function () {
const testDate = new Date(2019, 01, 01);
let db;
before(async function () {
await seedJobs(); // This is the function that creates the docs in the db
return new Promise((resolve, reject) => {
client.connect(async function (err) {
assert.equal(null, err);
if (err) return reject(err);
try {
db = await client.db(dbName);
} catch (error) {
return reject(error);
}
return resolve(db);
});
});
});
// Now I retrieve the created doc and run checks on it
describe("Check VBR Code Update", async function () {
let result;
const jobName = 'VBR Code Update';
this.timeout(2000);
before(async function () {
result = await db.collection(collection).findOne({
name: jobName
});
});
it("should have a property 'name'", async function () {
expect(result).to.have.property("name");
});
it("should have a 'name' of 'VBR Code Update'", async function ()
expect(result.name).to.equal(jobName);
});
it("should have a property 'nextRunAt'", function () {
expect(result).to.have.property("nextRunAt");
});
it("should return a date for the 'nextRunAt' property", function () {
assert.typeOf(result.nextRunAt, "date");
});
it("should 'nextRunAt' to be a date after test date", function () {
expect(result.nextRunAt).to.afterDate(testDate);
});
});
// Other tests
});
You are mixing promises and async together which is not needed. The Nodejs driver supports async/await so rather keep it consistent.
I cannot see the seedJobs function but assume it works as expected. I suggest you update the before function as per the example below.
You also have an error initializing the date, the format should be:
const testDate = new Date(2019, 1, 1);
See the below init of mongodb client and use of await:
const mongodb = require('mongodb');
const chai = require('chai');
const expect = chai.expect;
const config = {
db: {
url: 'mongodb://localhost:27017',
database: 'showcase'
}
};
describe("Seeding Script", function () {
const testDate = new Date(2019, 1, 1);
let db;
seedJobs = async () => {
const collections = await db.collections();
if (collections.map(c => c.s.namespace.collection).includes('tests')) {
await db.collection('tests').drop();
}
let bulk = db.collection('tests').initializeUnorderedBulkOp();
const count = 5000000;
for (let i = 0; i < count; i++) {
bulk.insert( { name: `name ${i}`} );
}
let result = await bulk.execute();
expect(result).to.have.property("nInserted").and.to.eq(count);
result = await db.collection('tests').insertOne({
name: 'VBR Code Update'
});
expect(result).to.have.property("insertedCount").and.to.eq(1);
};
before(async function () {
this.timeout(60000);
const connection = await mongodb.MongoClient.connect(config.db.url, {useNewUrlParser: true, useUnifiedTopology: true});
db = connection.db(config.db.database);
await seedJobs();
});
// Now I retrieve the created doc and run checks on it
describe("Check VBR Code Update", async function () {
let result;
const jobName = 'VBR Code Update';
this.timeout(2000);
before(async function () {
result = await db.collection('tests').findOne({
name: jobName
});
});
it("should have a property 'name'", async function () {
expect(result).to.have.property("name");
});
});
});

Can't return data from callback function at NodeJS

When i create new variable and assign callback function, But data cannot return from callback function. Undefined is occurring at new variable.
const nedb = require('nedb');
const user = new nedb({ filename: './builds/database/users.db', autoload: true });
var s = user.find({}, function (err,docs) {
if(docs.length == 0) {
var data = false;
} else {
var data = docs;
}
return data;
});
console.log(s);
var s is undefined! ....
You are mixing up callback and Promise which are two different way to handle asynchronous calls.
I recommend you to use of Promises because they are simpler and the present and future of javascript.
Using async/await which is the next step after Promises
const user = {
find: () => ['jon', 'kalessi', 'jorah'],
};
async function getUsers() {
return (await user.find({})) || [];
}
async function myJob() {
const users = await getUsers();
console.log(users);
// Put your next code here
}
myJob();
Full promise :
const user = {
find: () => new Promise((resolve) => resolve(['jon', 'kalessi', 'jorah'])),
};
user.find({})
.then((docs = []) => {
console.log(docs);
// Put you next code here, you can use of the variable docs
})
.catch((err) => {
console.log(err);
});
Full callback :
const user = {
find: (_, callback) => callback(false, ['jon', 'kalessi', 'jorah']),
};
user.find({}, (err, docs = []) => {
if (err) {
console.log(err);
} else {
console.log(docs);
// Put you next code here, you can use of the variable docs
}
});
I think user.find returning the promise. you can do like this.
const nedb = require('nedb');
const user = new nedb({ filename: './builds/database/users.db', autoload: true });
var s = user.find({}, function (err,docs) {
if(docs.length == 0) {
var data = false;
} else {
var data = docs;
}
return data;
});
Promise.all(s)
.then(result => {
console.log(result);
});
Otherwise you can also use await Like this:
async function abc(){
const nedb = require('nedb');
const user = new nedb({ filename: './builds/database/users.db', autoload: true });
var s = await user.find({}, function (err,docs) {
if(docs.length == 0) {
var data = false;
} else {
var data = docs;
}
return data;
});
}
because await worked with async thats why i put it into async function.

testing events sinon node.js

I want testing my function and I stuck with mocking events. I don't know how mock event with sinon.
This is my code when I stuck:
return pdfGenerator(invoice)
.then(content =>
{
const printer = new PdfMakePrinter(fonts);
let pdfDoc = {};
try {
pdfDoc = printer.createPdfKitDocument(content);
} catch (error) {
throw applicationException.new(applicationException.ERROR, 'Something bad in pdf content: ' + error);
}
let filepath = path.join(__dirname, '../REST/uploads/', filename);
let result = pdfDoc.pipe(fs.createWriteStream(filepath));
pdfDoc.end();
return new Promise(resolve =>
{
result.on('finish', resolve);
})
})
Problem occured when I want test
result.on('finish',resolve);
This is my test:
let pdfGeneratorMock = sinon.stub();
let endMock = sinon.stub().callsFake(function ()
{
return 0;
});
let pipeMock = sinon.spy();
let createPdfKitDocumentMock = sinon.spy(() =>
{
return {
end: endMock,
pipe: pipeMock
}
});
let pdfMakePrinterMock = sinon.spy(function ()
{
return {
createPdfKitDocument: createPdfKitDocumentMock
}
});
let onMock = sinon.spy(function(text,callback){
return callback();
});
let writeStreamMock = sinon.spy(() =>
{
return {
on: onMock
}
});
let fs = {
mkdirSync: sinon.spy(),
createWriteStream: writeStreamMock
};
........
it('should call createPefKitDocument', function ()
{
expect(createPdfKitDocumentMock).callCount(1);
});
it('should call fs.createWriteStream', function ()
{
expect(writeStreamMock).callCount(1);
});
it('should call pipe', function ()
{
expect(pipeMock).callCount(1);
});
it('should call end', function ()
{
expect(endMock).callCount(1);
});
it('should call on', function ()
{
expect(onMock).callCount(1);
});
Test not pass to onMock call and I don't have idea how mock this event and resolves to next then.
I resolved my problem with using yields. Change pipeMock to stub:
let pipeMock = sinon.stub();
In before() pipeMock return yields:
pipeMock.returns({ on: sinon.stub().yields()});
and now test call calback and resolve promise

Resources