How to resolve the promise in protractor - selenium

I have created a simple script on protractor but for me the script is not running correctly. Please find the code and output
it('Test#5.5 - Select top 5 Email Dumps', async () => {
let testId = 5.5;
let timeKey = 'Select top 5 Email Dumps';
console.time(timeKey);
log.info('\n', 'Selecting top 5 Email Dumps one after one')
// let email_dumps_list = await element.all(by.xpath('//*[contains(#data-selenium,"email_dump_item")]')).count();
// log.info('list of email dumps are ' + email_dumps_list);
for (let i = 0; i < 5; i++) {
let email_dump_item = await element.all(by.xpath('//*[contains(#data-selenium,"email_dump_item")]/div/span')).get(i);
selectElementAndCheckText(email_dump_item, testId + '_' + i)
}
});
async function selectElementAndCheckText(obj, testId) {
// const email_dump_0 = await element.all(by.xpath('//*[contains(#data-selenium,"email_dump_item")]/div/span')).get(element);
let email_dump_name = await obj.getText()
log.info('Clicking on ' + email_dump_name + ' email dump')
obj.click().then(async function(){
const email_header_name = element(by.css('div[data-testid="data-dump-page"] > * .MuiToolbar-gutters'));
if (browser.wait(EC.visibilityOf(email_header_name), 5000)) {
checkText(email_dump_name, await email_header_name.getText(), 'Email details shown doesn\'t match with the selected Dump', testId)
log.info("Pass")
return true;
}
else {
log.error('Email dump details not loaded')
return false;
}
});
}
async function checkText(actualText, expectedText, errorMessage, testId) {
try {
assert.equal(actualText, expectedText, errorMessage, '\n')
} catch (error) {
console.log(error);
}
}
Output
Selecting top 5 Email Dumps one after one
[1028/234735.013:INFO:CONSOLE(1)] "true SORT", source: https://webapp-dev-raven.ocp-nonprod.com/static/js/main.88ddd1a0.chunk.js (1)
Clicking on Selenium email dump email dump
Clicking on 10k email upload test email dump
Clicking on 191 emails test email dump
Clicking on another 100 emails email dump
Clicking on simulated 100 emails email dump
AssertionError [ERR_ASSERTION] [ERR_ASSERTION]: Email details shown doesn't match with the selected Dump
at checkText (C:\Users\webapp\test\e2e\email-dumps-test.js:270:14)
at C:\Users\webapp\test\e2e\email-dumps-test.js:114:7
at processTicksAndRejections (internal/process/task_queues.js:95:5) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: 'Selenium email dump',
expected: 'simulated 100 emails',
operator: '=='
}
Pass
AssertionError [ERR_ASSERTION] [ERR_ASSERTION]: Email details shown doesn't match with the selected Dump
at checkText (C:\Users\webapp\test\e2e\email-dumps-test.js:270:14)
at C:\Users\webapp\test\e2e\email-dumps-test.js:114:7
at processTicksAndRejections (internal/process/task_queues.js:95:5) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: '10k email upload test',
expected: 'simulated 100 emails',
operator: '=='
}
Pass
AssertionError [ERR_ASSERTION] [ERR_ASSERTION]: Email details shown doesn't match with the selected Dump
at checkText (C:\Users\webapp\test\e2e\email-dumps-test.js:270:14)
at C:\Users\webapp\test\e2e\email-dumps-test.js:114:7
at processTicksAndRejections (internal/process/task_queues.js:95:5) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: '191 emails test',
expected: 'simulated 100 emails',
operator: '=='
}
Pass
If you notice the output, the for loop is executing first before going in to obj.click().then function and so its printing the log and then doing the actual test. Can you please let me know if I am doing anything wrong here.

Because your function selectElementAndCheckText() and selectElementAndCheckText () are Async, so you need to prefix await when call them.
await should be added into following place:
for (let i = 0; i < 5; i++) {
let email_dump_item = await element.all(by.xpath('//*[contains(#data-selenium,"email_dump_item")]/div/span')).get(i);
await selectElementAndCheckText(email_dump_item, testId + '_' + i)
....
if (browser.wait(EC.visibilityOf(email_header_name), 5000)) {
await checkText(email_dump_name, await email_header_name.getText(), 'Email details shown doesn\'t match with the selected Dump', testId)

Related

How to add variable into JSON path

This is the query I am using:
app.get("/items/:data", async (req, res) => {
const { data } = req.params;
query = `
SELECT items.discount
FROM items
WHERE items.discount #? '$[*] ? (#.discount[*].shift == $1)'
`
try {
const obj = await pool.query(query, [data]);
res.json(obj.rows[0])
} catch(err) {
console.error(err.message);
}
});
I get this error:
error: bind message supplies 1 parameters, but prepared statement "" requires 0
I am using node-postgres package in node.js.
How can I solve this issue?
Use bracket notation instead of dot notation. So instead of obj.key use obj[key]
Updated
all them driver connectors come with their own method to do what you're looking for. node-postgres also have there own
Pool
import { Pool } from 'pg';
const pool = new Pool({
  host: 'localhost',
user: 'database-user',
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
/**
* execs the given sql statement.
*
* #param {string} sql - query to run.
* #param {Array} params - an array with the parameter.
* #example
* runQuery("SELECT * FROM users WHERE id = $1", [1]).then(result=> console.log(result))
*/
export async function runQuery (sql, params) {
const connection = await pool.connect()
try {
await connection.query('BEGIN')
const queryText = 'INSERT INTO users(name) VALUES($1) RETURNING id'
const result = await connection.query(sql,params);
// check what result has
console.log(result);
return connection.query('COMMIT').then(result)
} catch (e) {
await connection.query('ROLLBACK')
throw e;
throw e
} finally {
connection.release()
}
}
Pool Config
config = {
// all valid client config options are also valid here
// in addition here are the pool specific configuration parameters:
// number of milliseconds to wait before timing out when connecting a new client
// by default this is 0 which means no timeout
connectionTimeoutMillis?: int,
// number of milliseconds a client must sit idle in the pool and not be checked out
// before it is disconnected from the backend and discarded
// default is 10000 (10 seconds) - set to 0 to disable auto-disconnection of idle clients
idleTimeoutMillis?: int,
// maximum number of clients the pool should contain
// by default this is set to 10.
max?: int,
}
conclution
so basically the structure of a query should be like or less this
const text = 'INSERT INTO users(name, email) VALUES($1, $2) RETURNING *'
const values = ['brianc', 'brian.m.carlson#gmail.com']
connection
.query(text, values)
.then(res => {
console.log(res.rows[0])
// { name: 'brianc', email: 'brian.m.carlson#gmail.com' }
})
.catch(e => console.error(e.stack))

Postman. How can I use assertion / expect and console log together?

pm.test('Check if employee filled their skills', function() {
jsonData.forEach(function(item) {
expect(item.MainEmployeeSkills).to.be.not.empty;
if (item.MainEmployeeSkills.length < 1) {
console.log(item.fullName + " doesn't have skills");
}
})
})
After expect code is unreachable. But I want to know that test failed and log results.
Please, help
var jsonData = [2, 2, 3, 2, 2]
jsonData.forEach(function (a) {
pm.test("Your test name", function () {
if (item.MainEmployeeSkills.length < 1) {
console.log(item.fullName + " doesn't have skills");
}
pm.expect(a).to.eql(2);
});
})
you should print it before the pm.expect as it throws an exception and nexyt line won't be executed.
Also there is no point of having for loop inside pm.text as the loop exists for the first except itself ( unless this is what you want )
If you are looking way to print descriptive assertion message yu don't havr to do this. Instead use:
pm.test('Check if employee filled their skills', function() {
jsonData.forEach(function(item) {
pm.expect(item.MainEmployeeSkills,item.fullName + " doesn't have skills").to.be.not.empty;
})
})

Discord.JS Purge.js command issue

Ok so my bot got rebuilt with a somewhat different code.
I'm using a somewhat more simplified fs command and events handler. My command works as intended.
But I'm wanting to add the amount pruned into the fields for the richEmbed and it keeps erroring out.
Here is my purge.js file
const Discord = require('discord.js')
module.exports = {
name: 'purge',
description: 'Purge up to 99 messages.',
execute(message, args) {
console.log("purging messages")
const embed = new Discord.RichEmbed()
.setTitle("Success")
.setColor(0x00AE86)
.setFooter("Guardian", "https://raw.githubusercontent.com/phantomdev-github/Resources/master/Discord%20Bots/Guardian/src/avatar.png")
.setThumbnail("https://raw.githubusercontent.com/phantomdev-github/Resources/master/Discord%20Bots/Guardian/src/avatar.png")
.setTimestamp()
.setURL("https://github.com/phantomdev-github/Resources/tree/master/Discord%20Bots/Guardian")
.addField("Bot Messages Purged", "missing code here", false)
.addField("User Pins Purged", "missing code here", false)
.addField("User Messages Purged", "missing code here", false)
.addField("Total Messages Purged", "missing code here", false)
message.channel.send({ embed });
const amount = parseInt(args[0]) + 1;
if (isNaN(amount)) {
return message.reply('that doesn\'t seem to be a valid number.');
} else if (amount <= 1 || amount > 100) {
return message.reply('you need to input a number between 1 and 99.');
}
message.channel.bulkDelete(amount, true).catch(err => {
console.error(err);
message.channel.send('there was an error trying to prune messages in this channel!');
});
},
};
If it helps this i my index.js
const fs = require('fs');
const Discord = require('discord.js');
const client = new Discord.Client();
const { token } = require('./token.json');
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
console.log(file,command)
}
fs.readdir('./events/', (err, files) => {
if (err) return console.error(err);
files.forEach(file => {
if(!file.endsWith('.js')) return;
const eventFunction = require(`./events/${file}`);
console.log(eventFunction)
eventFunction.execute(client)
});
});
client.login(token);
and this is my message.js
const { prefix } = require('./prefix.json');
module.exports = {
name: 'message',
description: '',
execute:function(client) {
client.on('message',message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if (!client.commands.has(command)) return;
try {
client.commands.get(command).execute(message, args);
} catch (error) {
console.error(error);
message.reply('there was an error trying to execute that command!');
}
})
}};
Basically I'm trying to figure out what to place into the "missing code here" sections. Also any way to lock it to people with Administrator permissions only would be useful as well. I attempted that but it failed to work with the embed.
If I understand you right you want to know how to get the amount of the purged pins, bot msgs and user msgs. For this you need to put your embed after you deleted the messages.
purge.js
const Discord = require('discord.js')
module.exports = {
name: 'purge',
description: 'Purge up to 99 messages.',
execute(message, args) {
console.log("purging messages")
const amount = parseInt(args[0]) + 1;
if (isNaN(amount)) {
return message.reply('that doesn\'t seem to be a valid number.');
} else if (amount <= 1 || amount > 100) {
return message.reply('you need to input a number between 1 and 99.');
}
message.channel.bulkDelete(amount, true).then(deletedMessages => {
// Filter the deleted messages with .filter()
var botMessages = deletedMessages.filter(m => m.author.bot);
var userPins = deletedMessages.filter(m => m.pinned);
var userMessages = deletedMessages.filter(m => !m.author.bot);
const embed = new Discord.RichEmbed()
.setTitle("Success")
.setColor(0x00AE86)
.setFooter("Guardian", "https://raw.githubusercontent.com/phantomdev-github/Resources/master/Discord%20Bots/Guardian/src/avatar.png")
.setThumbnail("https://raw.githubusercontent.com/phantomdev-github/Resources/master/Discord%20Bots/Guardian/src/avatar.png")
.setTimestamp()
.setURL("https://github.com/phantomdev-github/Resources/tree/master/Discord%20Bots/Guardian")
.addField("Bot Messages Purged", botMessages.size, false)
.addField("User Pins Purged", userPins.size, false)
.addField("User Messages Purged", userMessages.size, false)
.addField("Total Messages Purged", deletedMessages.size, false);
message.channel.send(embed);
}).catch(err => {
console.error(err);
message.channel.send('there was an error trying to prune messages in this channel!');
});
},
};

Is there a way to wait until a function is finished in React Native?

I'm trying to get information (true/false) from AsyncStorage in a function and create a string which is importent to fetch data in the next step. My problem is, the function is not finished until the string is required.
I tried many solutions from the internet like async function and await getItem or .done() or .then(), but none worked out for me.
//_getFetchData()
AsyncStorage.getAllKeys().then((result) => { //get all stored Keys
valuelength = result.length;
if (valuelength !== 0) {
for (let i = 0; i < valuelength; i++) {
if (result[i].includes("not") == false) { //get Keys without not
AsyncStorage.getItem(result[i]).then((resultvalue) => {
if (resultvalue === 'true') {
if (this.state.firstValue) {
this.state.channels = this.state.channels + "channel_id" + result[i];
console.log("channel: " + this.state.channels);
}
else {
this.state.channels = this.state.channels + "channel" + result[i];
}
}
});
}
return this.state.channels;
_fetchData() {
var channel = this._getFetchData();
console.log("channel required: " + channel);
}
The current behaviour is that the console displays first "channel required: " than "channel: channel_id0".
Aspects in your question are unclear:
You don't say when this.state.firstValue is set, and how that relates to what you are trying to accomplish.
You have a for-loop where you could be setting the same value multiple times.
You mutate the state rather than set it. This is not good, see this SO question for more on that.
There are somethings we can do to make your code easier to understand. Below I will show a possible refactor. Explaining what I am doing at each step. I am using async/await because it can lead to much tidier and easier to read code, rather than using promises where you can get lost in callbacks.
Get all the keys from AsyncStorage
Make sure that there is a value for all the keys.
Filter the keys so that we only include the ones that do not contain the string 'not'.
Use a Promise.all, this part is important as it basically gets all the values for each of the keys that we just found and puts them into an array called items
Each object in the items array has a key and a value property.
We then filter the items so that only the ones with a item.value === 'true' remain.
We then filter the items so that only the ones with a item.value !== 'true' remain. (this may be optional it is really dependent on what you want to do)
What do we return? You need to add that part.
Here is the refactor:
_getFetchData = async () => {
let allKeys = await AsyncStorage.getAllKeys(); // 1
if (allKeys.length) { // 2
let filteredKeys = allKeys.filter(key => !key.includes('not')); // 3
let items = await Promise.all(filteredKeys.map(async key => { // 4
let value = await AsyncStorage.getItem(key);
return { key, value }; // 5
}))
let filteredTrueItems = items.filter(item => items.value === 'true'); // 6
let filteredFalseItems = items.filter(item => items.value !== 'true'); // 7
// now you have two arrays one with the items that have the true values
// and one with the items that have the false values
// at this points you can decide what to return as it is not
// that clear from your question
// return the value that your want // 8
} else {
// return your default value if there are no keys // 8
}
}
You would call this function as follows:
_fetchData = async () => {
let channel = await this._getFetchData();
console.log("channel required: " + channel);
}
Although the above will work, it will not currently return a value as you haven't made it clear which value you wish to return. I would suggest you build upon the code that I have written here and update it so that it returns the values that you want.
Further reading
For further reading I would suggest these awesome articles by Michael Chan that discuss state
https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0
https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296
https://medium.learnreact.com/setstate-takes-a-function-56eb940f84b6
I would also suggest taking some time to read up about async/await and promises
https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8
And finally this article and SO question on Promise.all are quite good
https://www.taniarascia.com/promise-all-with-async-await/
Using async/await with a forEach loop
Try this instead. Async functions and Promises can be tricky to get right and can be difficult to debug but you're on the right track.
async _getFetchData() {
let channels = "";
let results = await AsyncStorage.getAllKeys();
results.forEach((result) => {
if (result.includes("not") === false) {
let item = await AsyncStorage.getItem(result);
if (item === 'true') {
console.log(`channel: ${result}`)
channels = `channel_id ${result}`;
}
}
});
return channels;
}
_fetchData() {
this._getFetchData().then((channels) => {
console.log(`channel required: ${channel}`);
});
}
what if you wrap the _getFetchData() in a Promise? This would enable you to use
var channel = this._getFetchData().then(console.log("channel required: " + channel));
Otherwise the console.log won't wait for the execution of the _getFetchData().
This is what the console.log is telling you. it just logs the string. the variable is added after the async operation is done.
UPDATE
I would try this:
//_getFetchData()
AsyncStorage.getAllKeys().then((result) => { //get all stored Keys
valuelength = result.length;
if (valuelength !== 0) {
for (let i = 0; i < valuelength; i++) {
if (result[i].includes("not") == false) { //get Keys without not
AsyncStorage.getItem(result[i]).then((resultvalue) => {
if (resultvalue === 'true') {
if (this.state.firstValue) {
this.state.channels = this.state.channels + "channel_id" + result[i];
console.log("channel: " + this.state.channels);
}
else {
this.state.channels = this.state.channels + "channel" + result[i];
}
}
});
}
return new Promise((resolve, reject) => {
this.state.channels !=== undefined ? resolve(this.state.channels) : reject(Error('error '));
}
_fetchData() {
var channel = this._getFetchData().then(console.log("channel required: " + channel));
}
maybe you must change the this.state.channels !=== undefined to an expression that's matches the default value of this.state.channels.

JSON store hangs while retrieving data

We have observed that at certain times accessing the JSONStore API's hangs for long time, to make it work we have to call the function again or app has to be taken to background & bring to foreground again.
NOTE : when application faces this issue, behaviour is same until we reinstall the app or reboot the device.
There doesn't appear to be any proper scenarios for this, we have searched many articles but did not find any solution, any solutions are welcome.
We observed this issue on Android devices like S5 and S4.
Here is my code Snippet:
function getWidgets(w_id, getWidgetsSuccessCallback, getWidgetsFailureCallback) {
var query = { user_id : w_id };
var options = {};
WL.JSONStore.get(StorageCollections.widgets).find(query, options)
.then(function(arrayResults) {
var count = arrayResults.length;
Logger.debug("getWidgets: success, count: " + count);
...
getWidgetsSuccessCallback(widgets);
})
.fail(function(errorObject) {
Logger.error("getWidgets: failed, error: " + JSON.stringify(errorObject));
getWidgetsFailureCallback(errorObject);
});}
Logs when everything works fine http://pastebin.com/NVP8ycTG
Logs when accessing JSON store hangs, it will work only when app taken to background & bring back to foreground again http://pastebin.com/eYzx57qC
JSON store is initialised as below
var collections = {
// User
user: {
searchFields: {
user_id : 'string',
user_name : 'string',
first_name : 'string',
last_name : 'string',
}
}
}};
// Storage encryption
var options = {};
if (key) {
options.password = key;
options.localKeyGen = true;
}
// Open the collection
var promise = WL.JSONStore.init(collections, options)
.then(function() {
Logger.debug("initializeAppStorage: " + JSON.stringify(collections) + " completed");
initAppStorageSuccessCallback(true);
return true;
})
// Handle failure
.fail(function(errorObject) {
Logger.error("initializeAppStorage: failed, error: " + errorObject.toString());
initAppStorageFailureCallback(errorObject.toString());
return false;
});
return promise;
Thanks.
Try this one :
function getWidgets(w_id, getWidgetsSuccessCallback, getWidgetsFailureCallback) {
var query = { key : w_id };
var options = {};
WL.JSONStore.get(StorageCollections.widgets).find(query, options)
.then(function(arrayResults) {
var count = arrayResults.length;
Logger.debug("getWidgets: success, count: " + count);
...
getWidgetsSuccessCallback(widgets);
})
.fail(function(errorObject) {
Logger.error("getWidgets: failed, error: " + JSON.stringify(errorObject));
getWidgetsFailureCallback(errorObject);
});}