Unable to fetch the value of an element in protractor - angularjs

For one of my protractor script. I want to fetch the value of an element.
Here is the DOM setup:
<h5 class="ng-binding ng-scope" ng-if="editor.special.stock_number !== ''">
<b>Stock Number:</b>
72850
</h5>
I want to fetch the value of Stock Number:
I tried using getText, but it just printed out the Stock Number:
this.get_stock_number = () => {
let stockNumber = stock_number.getText();
stockNumber.then((text) => {
console.log("Stock Number is: " + text);
});
};
I also tried using getAttribute but it is returning null:
this.get_stock_number = () => {
let stockNumber = stock_number.getAttribute('Stock Number:');
stockNumber.then((text) => {
console.log("Stock Number is: " + text);
});
};
I really need this thing to be sorted out. I am kind of stuck here.
Any help will be much appreciated, Thanks.

You can try:
Locate the h5 element with the whole text and extract it
h5element.getText()
so it can return Ex:
<b>Stock Number:</b> 72850
After that just extract the number from the string with regex
let text = `<b>dsadsad</b> 320301`;
let numberPattern = /\d+/g;
let results = text.match(numberPattern);
if (results != null) {
let number = results[0];
console.log(number);
}

Related

Iterating through a JSON array and returning a subset of elements

I'm new to JS and trying to figure out how to iterate through a json array and return only a subset of elements. Specifically I would like to know how to return only the 'first_name' and 'last_name' from the Mock data in the attached code snippet. It seems like it should be straightforward but I'm scratching my head.
let people = [{"id":1,"first_name":"Talbert","last_name":"Kohnert","email":"tkohnert0#wisc.edu","country":"Indonesia"},
{"id":2,"first_name":"Ruthie","last_name":"McKleod","email":"rmckleod1#gizmodo.com","country":"Sweden"},
{"id":3,"first_name":"Lenore","last_name":"Foister","email":"lfoister2#epa.gov","country":"Nicaragua"}]
people.forEach(person => {
for (let key in person) {
console.log(`${key} => ${person[key]}`);
}
Use the element names
people.forEach(person => {
console.log(JSON.stringify(person) + "\n");
console.log(person["first_name"], person["last_name"], "\n");
});
Produces this output:
{"id":1,"first_name":"Talbert","last_name":"Kohnert","email":"tkohnert0#wisc.edu","country":"Indonesia"}
Talbert Kohnert
{"id":2,"first_name":"Ruthie","last_name":"McKleod","email":"rmckleod1#gizmodo.com","country":"Sweden"}
Ruthie McKleod
{"id":3,"first_name":"Lenore","last_name":"Foister","email":"lfoister2#epa.gov","country":"Nicaragua"}
Lenore Foister
You can try Object destructuring assignment of ES6 to achieve the requirement.
Working Demo :
let people = [{"id":1,"first_name":"Talbert","last_name":"Kohnert","email":"tkohnert0#wisc.edu","country":"Indonesia"},
{"id":2,"first_name":"Ruthie","last_name":"McKleod","email":"rmckleod1#gizmodo.com","country":"Sweden"},
{"id":3,"first_name":"Lenore","last_name":"Foister","email":"lfoister2#epa.gov","country":"Nicaragua"}];
let res = people.map(({first_name, last_name}) => first_name + ' ' + last_name);
console.log(res);
There are numerous way of achieving this output. One of most frequently used method is using map() of es6.
let people = [{"id":1,"first_name":"Talbert","last_name":"Kohnert","email":"tkohnert0#wisc.edu","country":"Indonesia"},
{"id":2,"first_name":"Ruthie","last_name":"McKleod","email":"rmckleod1#gizmodo.com","country":"Sweden"},
{"id":3,"first_name":"Lenore","last_name":"Foister","email":"lfoister2#epa.gov","country":"Nicaragua"}]
//by map method
people.map((person,index)=>{
console.log(`${person.first_name} ${person.last_name}`)
})
// by forEach
people.forEach(person => {
console.log(`${person.first_name} ${person.last_name}`)
}
you can achieve this by using the map function.
map lets you iterate over each item in the array and return a new value for each iteration while returning a new array, so for your case:
let people = [
{"id":1,"first_name":"Talbert","last_name":"Kohnert","email":"tkohnert0#wisc.edu","country":"Indonesia"},
{"id":2,"first_name":"Ruthie","last_name":"McKleod","email":"rmckleod1#gizmodo.com","country":"Sweden"},
{"id":3,"first_name":"Lenore","last_name":"Foister","email":"lfoister2#epa.gov","country":"Nicaragua"}
]
const newArray = people.map((person) => {
return {
first_name: person.first_name,
last_name: person.last_name
}
})
console.log(newArray)
here you get a new array with just the properties you need.

Replace index in array

I'm trying to understand how array works in typescript and I'm struggling to find any solutions on how to replace the index inside an array by a variable, for example with the datas as show below I would like to replace all index numbers by the part_id variable that is inside each index :
As an example, for the first index, instead of [0] I want to have 26 which is the part_id etc...
Here's a code samplet ( datas come from an API, I take a copy of the array returned by the API and modify it so that I can do a forEach on them and PatchValue is to set the values onInit)
Component.ts
initQuot(){
this.service.checkExistQuot().subscribe(res => {
this.quotArray = res;
this.quotDetails = res.quotation.quotationdetail;
let group = {};
this.copy.forEach((val, index)=>
{
group[`longueur_${index}`] = '';
group[`quantity_${index}`] = '';
group['diameter1'] = '';
group['diameter2'] = '';
});
this.dropForm = this.formBuilder.group(
group
);
this.quotDetails.forEach( (myArray, index) => {
this.copy.forEach( array1Ttem => {
this.quotDetails.forEach( array2Item => {
if(array1Ttem.part_id == array2Item.part_id){
for (var i = 0; i < this.copy.length; i++) {
this.copy[myArray.part_id] = this.copy[index];
console.log(this.copy);
let patchValue = {};
this.copy[i].longueur = myArray.longueur;
this.copy[i].quantity = myArray.quantity;
patchValue[`longueur_${index}`] = this.copy[index].longueur;
patchValue[`quantity_${index}`] = this.copy[index].quantity;
this.dropForm.patchValue(patchValue);
}
}
else{
console.log("No values matched");
}
})
});
})
})
}
If anyone knows a solution/what should I look at the help my issue I would really appreciate it, thank you
It's not really feasible to alter the array indices, but you could achieve essentially any desired behaviors using array functions. For instance, if you want to order the array by the part_id, you could do list.sort((a, b) => (a.part_id > b.part_id) ? 1 : -1)
It could be asking if the index value of an array, once declared to start at 0, could be changed to 1. The answer to that is no.
Sorting the actual array is the best solution in your case:-
list.sort((a,b) => a.part_id - b.part_id);

Firestore - Simple full text search solution

I know that firestore doesn't support full text search and it giving us solution to use third party services. However I found a simple solution to simple "full text search" and I think this might help others who doesn't want to use third party services as me for such a simple task.
I'm trying to search for company name which is saved in firestore collection under my companyName which can be in any format for example "My Awesome Company". When adding new company with companyName or updating a value in companyName I'm also saving searchName with it which is the same value as company name but in lower case without spaces
searchName: removeSpace(companyName).toLowerCase()
removeSpace is my simple custom function which remove all spaces from a text
export const removeSpace = (string) => {
return string.replace(/\s/g, '');
}
That turns our company name to myawesomecompany which is saved in searchName
Now I've got a firestore function to search for company which indexing through searchName and returning companyName. Minumum search value is a searched value without last character and maximum search value is a searched value with added "zzzzzzzzzzzzzzzzzzzzzzzz" transformed to lower case. That means if you search for My Aw then min value will be mya and max value will be myawzzzzzzzzzzzzzzzzzzzzzzz
exports.handler = ((data) => {
const searchValue = data.value.replace(/\s/g, '').toLowerCase()
const minName = searchValue.substr(0, searchName.length-1)
const maxName = searchValue + "zzzzzzzzzzzzzzzzzzzzzzzz"
let list = []
const newRef = db.collection("user").where("profile.searchName", ">=", minName).where("profile.searchName", "<=", maxName)
return newRef.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
list.push({ name: doc.data().profile.companyName})
})
return list
})
})
I didn't have time to fully test it but so far it works without any problems. Please let me know if you spot anything wrong with it. Now the question is
Is "z" character the highest value character in firestore or is there any other more decent way to add into the search value maximum amount without adding "zzzzzzzzzzzzz"?
I like your decision to preprocess the text so that it can be queried, but you could provide for a more flexible search by storing lowercase keywords with the users and searching those. In other words, transform:
"My Awesome Company"
to...
{ my: true, awesome: true, company: true }
...and test against that.
When adding/updating the property:
// save keywords on the user
let keywords = {}
companyName.split(' ').forEach(word => keywords[word.toLowerCase()] = true)
When querying:
let searchKeywords = userInputString.split(' ').map(word => word.toLowerCase())
let collection = db.collection("user")
searchKeywords.forEach(keyword => {
collection = collection.where(`keywords.${keyword}` , '==' , true);
});
With a little modification of previous answer I have made another simple text search. I'm saving keyword to an array instead of saving it in object like this
nameIndex: textIndexToArray(companyName)
where textIndexToArray is my custom function
export const textIndexToArray = (str) => {
const string = str.trim().replace(/ +(?= )/g,'')
let arr = []
for (let i = 0; i < string.trim().length; i++) {
arr.push(string.substr(0,i+1).toLowerCase());
}
return arr
}
which transfer a text into array. For example
"My Company"
will return
[m, my, my , my c, my co, my com, my comp, my compa, my compan, my company]
with nameIndex saved in firestore we can simply query the data thorough nameIndex and return companyName
exports.handler = ((data) => {
const searchValue = data.value.toLowerCase()
let list = []
const newRef = db.collection("user").where("nameIndex", "array-contains", searchValue)
return newRef.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
list.push({ name: doc.data().companyName, })
})
return list
})
})

How to add items returned from map function

getTotalUserVotes = (userid) => {
let posts = this.state.posts.slice();
let current = posts.filter((item) => {
return item.userid === userid;
})
console.log(current);
const tot = current.map((item) => {
return item.votes;
})
console.log("tot is " + tot)
// this logs 50, 0 ,0
//so each of the three posts that belong to that user have those amount
//of votes respectively.How can I add these?
return <div>votes: {tot}</div>;
}
When I have tried adding these using a for loop the strings concatenate so ill get 5000, I have searched how to stop that on stack overflow but none of the answers had little to any relation to my circumstance.
somewhat related question.
an example of the data in posts is
here
You can use the reduce method instead of map to add each item's votes.
const tot = current.reduce((total, item) => total + Number(item.votes), 0);
However, you can actually filter, map and reduce all at once.
const getTotalUserVotes = (userid) => {
const tot = this.state.posts.reduce((total, post) => {
return post.userid === userid ? total + Number(post.votes) : total
}, 0)
return <div>votes: {tot}</div>;
}
You can cast item.votes to a Number (since it sounds like it's stored as a String) and then use your for loop or reduce() to sum the values:
const tot = current.map((item) => {
return Number(item.votes);
})
tot = tot.reduce((a,b)=>a+b,0)

react , using <br> inside .map inside for (object)

I know in react you can't use <html> like strings, i'm looking for a solution but i don't see clear, how in this complex logic you can to insert a <br/> object and not like string, because variable 'newvalue' need to store and conditionally add br to separate elements in rows.
let values = JSON.parse(value);
let newvalue = '';
values.map((item) => {
for (const key in listViewField.subfields) {
let nameField = key;
if (typeof item[nameField] !=='undefined') {
newvalue += item[nameField]+ ' ';
}
}
// if (newvalue.trim() !=='') newvalue += '<br/>'; // doesn't work
});
value = newvalue;
return <div key={keyIndex}>{value}</div>;
Rather than using map, you can just iterate over your values and push them into an array.
let values = JSON.parse(value);
let contents = [];
for (let value of values) {
contents.push(<span key={value.key}>{value.name}</span>);
if (value.condition) {
contents.push(<br key={`${value.key}-br`} />);
}
});
return <div>{contents}</div>;
Don't forget to add a unique key to each item.
To add different option, if you want to use it with map and your item is simple string, then you can do something like this.
items.map((item, key) => {
<span style={{whiteSpace: 'pre'}} key={key}>{item + '\n'}</span>
});
Note that I have added style={{whiteSpace: 'pre'}} and + \n

Resources