I wish to make call different column if user using different language, example in one collection I have description_en for English and description_ind for Indonesia.
The problem if I concat it is not working.
This is example code
let lang = req.params.lang;
order_status_description:element.orderstatus.description + lang,
this is my complete code
const MyOrderResource = (req,res,next)=>{
let lang = req.params.lang;
let arrayResult = [];
req.order.forEach(element => {
let arrayItem =[];
element.orderitem.forEach(item=>{
arrayItem.push({
_id:item._id,
product_id:item.product_id,
product_name:item.product_name,
description:item.description,
unit:item.unit,
price:item.price,
fprice:'Rp ' + new Intl.NumberFormat().format(item.price),
quantity:item.quantity,
amount:item.amount,
fprice:'Rp ' + new Intl.NumberFormat().format(item.amount),
});
});
arrayResult.push({
_id:element._id,
user_id:element.user_id,
date:element.date,
store_id:element.store_id,
store_name:element.profile[0].name,
store_address:element.profile[0].address,
total:element.total,
ftotal:'Rp ' + new Intl.NumberFormat().format(element.total),
order_status_code:element.orderstatus.code,
order_status_description:element.orderstatus.description + lang,
order_item:arrayItem,
});
});
res.status(201).json({
data:arrayResult,
status : 200,
})
}
module.exports = MyOrderResource;
For this code, I wish to call, column description_en, but the result is undefined
Thanks for helping
You can use something like
order_status_description : element.orderstatus["description" + lang]
In the posted snipet, it instructs to concat the value of key- 'element.orderstatus.description' to the value of key - 'lang'
Related
My scenario is to add a section in a page and perform an action on it.But as there are elements with the same xpath already, webdriver is clicking on first element and the script is failing.So, I want to fetch the existing number of elements having the same xpath and then increase the count by 1 so as to click on the newly added section. Please find the below code and correct me where it is going wrong.(Or) Suggest me any other approach.
Also, please let me know will line no. 9 works if getting the number of elements issue is resolved. Thanks!
Method :
this.getElementCount=async function(locator) {
try {
console.info('Verifying count for element ' + locator);
let noOfElements = await element.all(locator).count();
await console.info('There are ' + noOfElements + 'elements in UI');
return noOfElements;
} catch(err) {
throw err;
}
}
Calling method :
var compLocator = element(by.xpath("//div[#title='Test']"));
this.clickOnComp=async function(){
var elementsCount=getElementCount(compLocator);
console.info("No. of elements : "+elementsCount);
if(elementsCount>1){
var currentEle=elementsCount+1;
var currentCompLocator=compLocator[currentEle]; // line no.9
console.info("comp locator :" +currentCompLocator);
await clickElement(currentCompLocator);
console.info("Clicked : "+currentCompLocator);
}
else{
await clickElement(compLocator);
}
}
Output :
Verifying count for element [object Object]
No. of elements : [object Promise]
(node:13915) UnhandledPromiseRejectionWarning: TypeError: Invalid locator
Start with resolving promise with await
var compLocator = element(by.xpath("//div[#title='Test']"));
this.clickOnComp=async function(){
var elementsCount=await getElementCount(compLocator); // <-----------------
console.info("No. of elements : "+elementsCount);
if(elementsCount>1){
var currentEle=elementsCount+1;
var currentCompLocator=compLocator[currentEle]; // line no.9
console.info("comp locator :" +currentCompLocator);
await clickElement(currentCompLocator);
console.info("Clicked : "+currentCompLocator);
}
else{
await clickElement(compLocator);
}
}
There are two issues in your code:
getElementCount() expects a locator argument by you give a element
(Line 9) compLocator is an element not an xpath or an element array, you can't use compLocator[currentEle]
var compXPath = "//div[#title='Test']"
var compLocator = by.xpath(compXPath);
this.clickOnComp=async function(){
var elementsCount = await getElementCount(compLocator);
console.info("No. of elements : "+elementsCount);
if(elementsCount > 1){
var currentEle = elementsCount+1;
var currentCompXPath = compXPath + "/["+ currentEle +"]" // line no.9
console.info("current Comp xpath :" +currentCompXPath);
var currentCompLocator = by.xpath(currentCompXPath)
await clickElement(currentCompLocator);
console.info("Clicked : "+currentCompLocator);
}
else{
await clickElement(compLocator);
}
}
I want to update a taable from a JSON object. The WHERE clause of the update has more than one columns. I tried this :
connexion.query("update my_table set ? where ?", [{ "param_valeur": emails }, { "param_key": "paramKey", "flotte_id": 1 }], function (err, rows) {
console.log("=================== sql =", this.sql);
if (err)
throw err;
res.send("");
});
but at runtime the WHERE clause does not have the AND keyword ! So how to fix that ?
OK, you want to use dynamic data by sending a json to MySQL WHERE query, from what I found out until now this is not a trivial operation... So, my first answer is not a good solution for your requirements so I write a new and dynamic code. (a little bit more complicated than the first answer...)
Please try the solution and let my know if this is what you want.
my answer is based on https://www.npmjs.com/package/mysql#preparing-queries, you can read this docs section for better understanding of the double question marks syntax.
let paramsSETObj = { "param_valeur": emails };
let paramsWHEREObj = { "param_key": "paramKey", "flotte_id": 1 };
// separate the question marks with comma ', '
let questionMarksForSET = this.getQuestionMarksStr(Object.keys(paramsSETObj).length, ', ');
let valuesForSETArray = this.convertObjectToArray(paramsSETObj);
// separate the question marks with 'AND'
let questionMarksForWHERE = this.getQuestionMarksStr(Object.keys(paramsWHEREObj).length, ' AND ');
let valuesForWHEREArray = this.convertObjectToArray(paramsWHEREObj);
let sql = `UPDATE my_table SET ${questionMarksForSET} WHERE ${questionMarksForWHERE}`;
let inserts = [...valuesForSETArray, ...valuesForWHEREArray];
sql = mysql.format(sql, inserts);
connexion.query(sql, function (err, rows) {
if (err)
throw err;
res.send("");
});
// Convert an object to array, where each key is before the value
module.exports.convertObjectToArray = function (obj) {
let arr = [];
for (let key in obj) {
arr.push(key);
arr.push(obj[key]);
}
return arr;
}
/**
* Get a question marks string separate each pair with the equal sign '='
* the amount of the questions marks pairs is the same as the keys of the object from the request.
* The separator in this case is comma ',' or 'AND' - this is a must for your requirement in the question.
* example:
* questionMarksForSET: ?? = ? , ?? = ?
* questionMarksForWHERE: ?? = ? AND ?? = ?
*/
module.exports.getQuestionMarksStr = function (objKeysLength, separator) {
let questionsMarks = '';
for (let i = 0; i < objKeysLength; i++) {
// if the index is not in the last object key - add the separator else add empty string
let commaOrAndSeparator = (i !== objKeysLength - 1) ? separator : '';
questionsMarks += ' ?? = ? ' + commaOrAndSeparator;
}
return questionsMarks;
}
Try this:
connexion.query('UPDATE my_table SET param_valeur = ? WHERE param_key = ? AND flotte_id = ?', [emails, "paramKey", 1], function (err, rows) {
if (err)
throw err;
res.send("");
});
When I generate the CSV file each "item" output comes out with a  symbol. How would I go about removing this with my code. I tried to change it to utf-8 because I read that might be what's causing it. Any ideas? Example:
const products = await page.$$('.item-row');
Promise.all(products.map(async product => {
// Inside of each product find product SKU, it's human-readable name, and it's price
let productId = await product.$eval(".custom-body-copy", el => el.innerText.trim().replace(/,/g,' -').replace('Item ', ''));
let productName = await product.$eval(".body-copy-link", el => el.innerText.trim().replace(/,/g,' -'));
let productPrice = await product.$eval(".product_desc_txt div span", el => el.innerText.trim().replace(/,/g,' -'));
// Format them as a csv line
return productId + ',' + productName + ',' + productPrice + ',';
})).then(lines => {
// Write the lines to a file
fs.writeFileSync("products.csv", lines.join('\n'), 'utf-8');
browser.close();
});
});
There are probably better solutions, but the first thing that comes to mind to to change the string to an array with split() and then .map through and test for the à ascii code and change back to a string with join() like this:
const strToChange = 'My string with an à char';
const charWeDoNotWant = 'Ã'.charCodeAt();
const toFixArr = strToChange.split('');
fixedArr = toFixArr.map(char =>
char.charCodeAt() === charWeDoNotWant ? '' : char
);
const fixedStr = fixedArr.join('');
console.log(`String without Ã: ${fixedStr}`);
I'd like to store initial device title, which is accessible via GUI in browser as page title, and reuse it later in the code. E.g. I want to change name of device if it is set to some particular name only, and to store an old device name in browser console log. Code might look like this:
var some_name = 'Some Name';
var title = browser.getTitle();
console.log(title);
if (title.equals('Some Name')){
some_name = 'Some Other Name';
}
setDeviceName(some_name);
unfortunately, to that protractor responds with
TypeError: title.equals is not a function
How is it possible to extract browser title as string?
Thanks.
UPDATE:
Thanks everyone, the solution due to igniteram1 is
var some_name = 'Some Name';
some_name = browser.getTitle().then(function(webpagetitle){
if (webpagetitle === 'Some Name'){
return 'Some Other Name';
}else{
return 'Some Name'
}
});
expect(some_name).toEqual('Some Other Name');
In addition to #Sudharshan Selvraj's answer,its good practice to use strict equality === instead of == and to return the value.
var some_name = 'Some Name';
some_name = browser.getTitle().then(function(webpagetitle){
if (webpagetitle === 'Some Name'){
return 'Some Other Name';
}else{
return 'Some Name';
}
});
expect(some_name).toEqual('Some Other Name');
If you aware of the new asyc/await you may use:
expect(await browser.getTitle()).toEqual("myCustomTitle");
In protractor whatever information you need from browser will be a promise and not a string. in order to fetch the value you need to resolve the promise. look at the below example.
var title = browser.getTitle();
title.then(function(webpagetitle){
if (webpagetitle == 'Some Name'){
some_name = 'Some Other Name';
}
})
.equals() is not a function in JavaScript, but it's a valid function in Java. In Java Script, we have '==', '===' as an alternative for performing equal operations.
var x=10
== compare only values of operands, not type of operands
example:
x==10 => true
x=="10" => true
=== compare both values and type of operands
example:
x===10 => true
x==="10" => false(type of x in int and "10" is string)
var someName;
browser.getTitle().then(function (webPageTitle) {
if (webPageTitle == 'Some Name'){
someName= 'Some Other Name';
}
});
I've got a simple function in protractor to get the title when in the promise it shows the title properly, but when I do console.log it gives :
Title Got is ManagedPromise::123 {[[PromiseStatus]]: "pending"}
describe('Protractor Demo App', function() {
it('should have a title', function(one) {
browser.waitForAngularEnabled(false);
browser.get('https://tasyah.com');
titleGot = browser.getTitle().then(function(promisedResult){
console.log("Title is : " + promisedResult);
return promisedResult;
})
console.log("Title Got is " + titleGot);
expect(titleGot).toEqual('Tasyah: Online Shopping For Fashion And Costume Jewellery');
console.log("Title Got is " + titleGot);
});
});
Any explanation on this is appreciated...
Thanks
Naveen
Page Object .po file
getTableRows() {
return element.all(by.css('[data-qa="qa-table"] tr'));
}
.e2e.spec file
<PROMISE-APPROCH>
obj.getTableRows().then((list)=> {
list.count().then((totalRows)=>{
expect(totalRows).toBe(10); // example
})
});
<ASYNC-AWAIT-APPROCH>
const rowsCount = await obj.getTableRows().count();
expect(rowsCount).toBe(10); // example
I want to be able to pass multiple data sets to my view. Here is how I am currently doing it in my controller:
transactions: function (req, res) {
var queryexpenses = 'select * from expense order by name';
Expense.query(queryexpenses, function (err, expense) {
this.expenses = expense;
});
if (req.param('filter')) {
var where = 'where fk_expense = ' + req.param('expensefilter');
where += ' and datePosted > "' + req.param('yearfilter') + '-01-01" ';
where += ' and datePosted < "' + req.param('yearfilter') + '-12-31" ';
} else {
var where = 'where fk_expense IS NULL';
}
var query = 'select * from accounting ' + where + ' order by description';
Accounting.query(query, function (err, trans) {
this.transactions = trans;
});
var total = 0;
_.each(this.transactions, function (element, index, list) {
// format dates
element.datePosted = dateFormat(element.datePosted, 'dd/mm/yyyy');
var tmp0 = element.amount
var tmp1 = tmp0.replace(/ /g, '');
var tmp2 = parseFloat(tmp1);
total += tmp2;
});
this.total = total.toFixed(2);
return res.view();
}
This is the only way I am able to accomplish what Im trying to do but there are problems which I believe are caused by me putting the query objects in the "this" scope. The first problem is the page will crash after server restart on first reload. The second problem is everything seems to happen one step behind. What I mean is if I issue commands on the UI (eg submit a form) nothing will happen unless I take the same action twice.
So how do I pass multiple sets of data to my views without scoping them in "this"?
res.view({
corndogs: [{name: 'Hank the Corndog'}, {name: 'Lenny the Corndog'}]
});
Here is the relevant docs page: http://sailsjs.org/#!documentation/views
Also, it looks like you're not taking full advantage of Waterline for making SQL queries.