I want to write a module similar to the one below.
It should be callable via "Server.doBackup" and use the fat arrow notation together with an async-await function
Any ideas?
Can you provide a corrected version of my snippet below?
const Server = {
config: {
documents: ['DEFAULT', 'KEYS'],
exportpath: 'data/exportFromCosmos/',
uploadpath: 'data/uploadToAzureBlob/',
crosscheckFile: 'data/crosscheckFile.txt'
},
doBackup: () => async {
let prepareFolders = await Folders.prepare(Server.config, resolve)
let downloadDB_DEFAULT = await Database.downloadDocumentsOfType_DEFAULT()
let downloadDB_KEYS = await Database.downloadDocumentsOfType_KEYS()
let zipDocuments = await Documents.zip(Server.config)
}
}
module.exports = Server
const Server = {
config: {
documents: ['DEFAULT', 'KEYS'],
exportpath: 'data/exportFromCosmos/',
uploadpath: 'data/uploadToAzureBlob/',
crosscheckFile: 'data/crosscheckFile.txt'
},
doBackup: async () => {
let prepareFolders = await Folders.prepare(Server.config, resolve)
let downloadDB_DEFAULT = await Database.downloadDocumentsOfType_DEFAULT()
let downloadDB_KEYS = await Database.downloadDocumentsOfType_KEYS()
let zipDocuments = await Documents.zip(Server.config)
}
}
module.exports = Server
// Sample Code
async function findName(){
return {name: "Stack"}
}
let user = {
getName: async()=>{
let {name} = await findName()
return name
}
}
user.getName()
.then((userDetail)=> console.log(userDetail))
.catch((error) => console.log(error))
Related
I'm working with Playwright, cucumber and Javascript. I'm facing the next issues below:
page.type: selector: expected string, got object
page.click: selector: expected string, got function
And many similar error messages.
this is the profile.cjs class, where the data is located:
const wrongEmailFormat = 'eyftqeiuyfqwiyfiwqfywqgfywqguddwqguy'
const existingEmail = 'amalg12#gmail.com'
module.exports = { wrongEmailFormat , existingEmail };
This is my profile-page.cjs:
const { secondaryUrl } = require("../config.cjs");
const { wrongEmailFormat , existingEmail } = require("../data/profile.cjs")
const should = require('chai').should(); //Chai assertion
const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
const profileTitle = async () => await page.$('//h2[contains(text(),\'My Profile\')]')
const communicationTab = async () => await page.$('//button[#id=\'headlessui-tabs-tab-:R5l6:\']')
const currentEmail = async () => await page.$('#current-email')
const updateEmail = async () => await page.$('#cla9ruxam000w3b630t1c9dl4')
class ProfilePage {
async navigateToProfilePage() {
await page.goto(secondaryUrl)
await delay(2000)
}
async profilePageDisplayed() {
should.exist(profileTitle)
}
async communicationTabDisplayed() {
should.exist(communicationTab)
}
async currentEmailFieldDisplayed(){
should.exist(currentEmail)
}
async updateEmailFieldDisplayed(){
should.exist(updateEmail)
}
async updateEmailWrongFormat(){
//await page.keyboard.press(updateEmail().type(wrongEmailFormat))
//await updateEmail().click()
//await page.click(updateEmail, { force: true })
//await page.fill(wrongEmailFormat).toString()
//await page.waitFor(updateEmail())
//await page.click(updateEmail, { force: true }).toString()
//await page.fill(updateEmail(), wrongEmailFormat).toString()
//await page.dispatchEvent(updateEmail()).click
//await updateEmail().keys(wrongEmailFormat)
//await delay(3000)
}
}
module.exports = { ProfilePage };
updateEmailWrongFormat is all with comments, because I have tried in many ways, but without success.
Could anybody help me with this, please?
The error was the next:
All the selectors included in the profile-page were using the "WebdriverIO" format, so I did the next:
1.- Take all the selectors and move them to a new folder(selectors) inside a new class: profile-selectors with the next format:
module.exports = {
profileTitle: '//h2[contains(text(),\'My Profile\')]',
communicationTab: '//button[#id=\'headlessui-tabs-tab-:R5l6:\']',
currentEmail:'#current-email',
updateEmail:'//html[1]/body[1]/div[1]/div[1]/div[2]/main[1]/div[1]/div[2]/' +
'div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]'
};
After this, import in the Page object class and use them:
const { profileTitle, communicationTab, currentEmail, updateEmail} = require('../selectors/profile-selectors')
I know there are many xpaths, but much of the webelements do not have identifiers, or any others are dynamic elements.
I'm doing a little data analysis from chess.com data
I have this code
const getUsernames = async function() {
let response = await chessAPI.getCountryPlayers('RE')
names = [...response.body.players]
//console.log(names)
return names
}
const grabPlayerScores = async function() {
let players = getUsernames()
// let playerStats = [];
for (i = 0; i = players.length; i++) {
let data = await chessAPI.getPlayerStats(i)
console.log(data)
}
}
grabPlayerScores();
I can't get the other function to await the return of the first. I know I should use promises or structure my other function differently but I'm still getting the hang of these types of functions.
As a best practice, you should make sure all of your functions return a value. Use const for variables that will not change, and let for variables that you absolutely will change. Watch out for name = ... where you didn't write const or let, as this makes names into a global -
const getUsernames = async function() {
const response = await chessAPI.getCountryPlayers('RE')
return response.body.players // <- probably no need to copy
}
const grabPlayerScores = async function() {
const players = await getUsernames()
return Promise.all(players.map(p => chessAPI.getPlayerStats(p)))
}
Now grabPlayerScores will be a promise containing an array of all player scores -
grabPlayerScores().then(console.log).catch(console.error)
[ ..., ... ,... ]
Maybe you want the player data combined with the score data in the final output?
const grabPlayerScores = async function() {
const players = await getUsernames()
return Promise.all(players.map(async p => ({
player: p,
scores: await chessAPI.getPlayerStats(p)
})))
}
grabPlayerScores().then(console.log).catch(console.error)
[ { player: "alice", scores: ... },
{ player: "brenda", scores: ... },
{ player: "catherine", scores: ... } ]
Another good practice is to make your functions take parameters. This makes them more reusable in other areas of your program -
const getUsernames = async function(countryCode) {
const response = await chessAPI.getCountryPlayers(countryCode)
return response.body.players
}
const grabPlayerScores = async function(countryCode) {
const players = await getUsernames(countryCode)
return Promise.all(players.map(async p => ({
player: p,
scores: await chessAPI.getPlayerStats(p)
})))
}
Now you pass "RE" as an argument to your function, allowing you to easily reuse this function for other countries -
grabPlayerScores("RE").then(console.log).catch(console.error)
You need to add another await in your grabPlayerScores function to wait for getUsernames to finish.
const grabPlayerScores = async function() {
// Add an 'await' here
let players = await getUsernames();
for(let i = 0; i = players.length; i++) {
let data = await chessAPI.getPlayerStats(i)
console.log(data)
}
}
I changed bit in your code,
const grabPlayerScores = async function () {
let players = await getUsernames();
for (i = 0; i = players.length; i++) {
let data = await chessAPI.getPlayerStats(players[i]);
console.log(data)
}
}
I have the following method:
import { ObjectDal } from "./ObjectDal";
export class ObjectBL {
async getObject(id) {
try {
let dal = new ObjectDal();
let result = await dal.get(id);
return result;
} catch (err) {
// log the error
}
}
where the ObjectDal class is:
export class ObjectDal {
async get(id) {
// open connection to db
// make a query based on id
// put the result in a `result` variable
return result;
}
}
I have to write an unit test for the getObject() method using only Mocha...
This is the begining of the UT:
const assert = require('assert');
const ObjectBL = require("../ObjectBL");
describe('Something', () => {
describe('...', () => {
it('getObject_GetsObjectUsingID_True', async () => {
// arange
let id = "123456789101";
let expected = {
"name": "ana",
"hasApples": true
};
let test = new ObjectBL.ObjectBL();
let result = await test.getObject(id);
assert.deepStrictEqual(result, expected);
});
});
});
But in this case I would have to call the method from the ObjectDal class...
How can I mock the call to the get() method using only Mocha?
I found answers with Sinon, or Mocha with Sinon and/or Chai... but nothing with only Mocha...
Proxies might be the way to go for you.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
You could mok methods by using a Proxy like so:
const assert = require('assert');
const ObjectBL = require("../ObjectBL");
describe('Something', () => {
describe('...', () => {
it('getObject_GetsObjectUsingID_True', async () => {
// arange
let id = "123456789101";
let expected = {
"name": "ana",
"hasApples": true
};
let test = new ObjectBL.ObjectBL();
const handler = {
get: function(obj, prop) {
// mok the getObject method
if(prop === 'getObject'){
return () => {
return Promise.resolve({
"name": "ana",
"hasApples": true
});
}
} else {
return obj[prop];
}
}
};
const p = new Proxy(test, handler);
let result = await p.getObject(id);
assert.deepStrictEqual(result, expected);
});
});
});
If you ONLY want to mok the ObjectDal.get method, you might want to override the prototype and recover it afterwards:
const assert = require('assert');
const ObjectBL = require("../ObjectBL");
const ObjectDal = require("../ObjectDal");
describe('Something', () => {
describe('...', () => {
it('getObject_GetsObjectUsingID_True', async () => {
// arange
let id = "123456789101";
let expected = {
"name": "ana",
"hasApples": true,
};
const proto = Object.getOwnPropertyDescriptor(ObjectDal, 'prototype').value;
const backup = proto.get;
proto.get = () => {
return Promise.resolve({
"name": "ana",
"hasApples": true,
});
}
let test = new ObjectBL.ObjectBL();
let result = await test.getObject(id);
ObjectDal.prototype.get = backup;
assert.deepStrictEqual(result, expected);
});
});
});
You could also override the ObjectDal with a Proxy and implement the construct handler to return a dummy ObjectDal, but this might be more tricky, since you are working with modules.
Testing is feedback, not just on whether or not your code works as advertised but even more crucially on the quality of your design.
The fact that you are having trouble writing the tests is your first sign you did something sub-optimal in the implementation. What you want is this:
export class ObjectBL {
constructor (dal) {
this.dal = dal;
}
async getObject(id) {
try {
let result = await this.dal.get(id);
return result;
} catch (err) {
// log the error
}
}
...and now the dependency is clear rather than implicit and will show up in editor tooltips, is more amenable to static analysis, etc. And it solves your problem: now you can mock it easily for testing, no further libraries needed.
I am beginner at javascript so please bear with me. I wonder how to put async() event in the right way.
I have 2 code snippets that I want to execute asynchronously and not synchronously. The code snippets use a library that do HTTP requests so that is out of my control.
So I like the 2 code snippets to execute in parallell somehow. What I have are those 2 code snippets and I also think I understand that I only want to declare the first 2 lines once as those lines takes time:
'use strict';
const ccxt = require ('ccxt');
The 2 code snippets are the below
Code snippet1:
'use strict';
const ccxt = require ('ccxt');
(async () => {
try{
const exchange = new ccxt.one({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
fs.writeFile("/myproject/file1.txt", JSON.stringify(obj), function(err) { });
}catch{}
}) ()
Code snippet2:
'use strict';
const ccxt = require ('ccxt');
(async () => {
try{
const exchange = new ccxt.two({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
fs.writeFile("/myproject/file2.txt", JSON.stringify(obj), function(err) { });
}catch{}
}) ()
I tried this code and it actually did it in parallell. It executed very fast.
If you have any idéas of code to add to make it even more efficient I would be very happy to hear how to do that. (For example open up more ports or any other bottlenecks?)
'use strict';
const ccxt = require ('ccxt');
(async () => {
try{
const exchange = new ccxt.one({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
fs.writeFile("/myproject/file1.txt", JSON.stringify(obj), function(err) { });
}catch{}
}) ();
(async () => {
try{
const exchange = new ccxt.two({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
fs.writeFile("/myproject/file2.txt", JSON.stringify(obj), function(err) { });
}catch{}
}) ();
Use Promise.all:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
'use strict';
const ccxt = require ('ccxt')
const fs = require('fs')
async function work (exchangeId) {
try {
const exchange = new ccxt[exchangeId] ({ enableRateLimit: true })
const tickers = await exchange.fetchTickers ()
const obj = { tickers }
const filename = exchangeId + '.txt'
fs.writeFileSync (filename, JSON.stringify (obj))
console.log ('saved', filename)
} catch {
}
}
(async () => {
const exchangeIds = [ 'bittrex', 'bitfinex' ]
await Promise.all (exchangeIds.map (exchangeId => work (exchangeId)))
}) ()
It's not clear to me what you want to happen but your code will not catch all errors as written. I know you seemed to be ignoring all errors but just in case, ...
If you're going to use async/await then you should go all in. That means you should use fs.promises.readFile not fs.readFile. Either that or you should wrap fs.readFile in a promise either manually or using util.promisify.
So the code becomes
'use strict';
const ccxt = require ('ccxt');
const thing1 = (async () => {
try{
const exchange = new ccxt.one({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
await fs.promises.writeFile("/myproject/file1.txt", JSON.stringify(obj));
} catch {
// catch error here
}
}) ();
const thing2 = (async () => {
try{
const exchange = new ccxt.two({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
await fs.promises.writeFile("/myproject/file2.txt", JSON.stringify(obj));
} catch {
// catch error here
}
}) ();
If wanted to do both to wait for both things then you could use Promise.all by passing in an array that contain each of the promises returned by both async functions.
'use strict';
const ccxt = require ('ccxt');
const thing1 = (async () => {
try{
const exchange = new ccxt.one({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
await fs.promises.writeFile("/myproject/file1.txt", JSON.stringify(obj));
} catch {
// catch error here
}
}) ();
const thing2 = (async () => {
try{
const exchange = new ccxt.two({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
await fs.promises.writeFile("/myproject/file2.txt", JSON.stringify(obj));
} catch {
// catch error here
}
}) ();
(async() => {
await Promise.all([thing1, thing2]);
// do something after thing1 and thing2
}) ();
And of course at given the 2 functions are the same except for the filename then
'use strict';
const ccxt = require ('ccxt');
async function fetchTickersAndWrite({method, filename}) {
try{
const exchange = new ccxt[method]({ enableRateLimit: true })
const tickers = await exchange.fetchTickers()
const obj = { tickers }
const fs = require('fs');
await fs.promises.writeFile(filename, JSON.stringify(obj));
} catch {
// catch error here
}
}
(async() => {
await Promise.all([
{ method: 'one', filename: `/myproject/file1.txt` },
{ method: 'two', filename: `/myproject/file2.txt` },
].map(fetchTickersAndWrite));
// do something
}) ();
So, I'm using selenium webdriver with javascript, the browser is firefox.
The base_page looks like this:
function Page() {
this.driver = new Builder().forBrowser('firefox').build();
const driver = this.driver;
this.visit = async(url) => {
try {
return await driver.get(url);
} finally {
console.log("visit: OK");
}
};
...
The home_page looks like this:
const Page = require('./base_page');
Page.prototype.requestBtn = async() => {
try {
await this.write('input', 'user#fakemail.com');
return {
opacity: await this.find('.btn-lg').getCssValue('opacity'),
state: await this.find('.btn-lg').isEnabled()
};
} catch(err) {
console.log(err);
}
};
...
In the mocha.test.js I import the home_page. I can use the functions created in base_page, but can't access functions in home_page.
For example, page.visit() and page.quit() are qorking, but page.requestBtn() not.
const assert = require('assert');
const {Builder, By, Key, until} = require('selenium-webdriver');
const Page = require('../lib/home_page');
let page;
describe('Test', () => {
beforeEach(async() => {
page = new Page();
await page.visit('https://library-app.firebaseapp.com');
});
afterEach(async() => {
await page.quit();
});
it("Example", async() => {
await page.requestBtn();
});
...