protractor FOR loop using expectations - node.js

I made loop and now I want to use protractor expectation for every i.
Loop works ok, but expectations doesn't. If count is 4, there should be 4 expectations. If I run a test, I get pass, without any expectations(which should be false).
I found articles about that but I couldn't make it happen. I tried with Push, but there is only empty value.
Thanks for help.
myelement.count().then(function(count){
console.log("whatever", count);
for (var i=0; i<count; i++){
var o = location.get(i);
expect(o.getText()).toEqual("something");
};
});

Be aware. Almost all commands are promises. If you don't handle them correct it will never work. You will first need to resolve them before you can go to the next one.
Something like this can do the trick
let promise;
const promises = [];
myelement.count()
.then(function(count) {
console.log("whatever", count);
for (var i = 0; i < count; i++) {
var o = location.get(i);
promises.push(expect(o.getText()).toEqual("something"));
};
return Promise.all(promises);
});

Full test-case code would help, but I assume that you've forgot to either return a promise from 'it' or define and call 'done' callback, since what you're doing - is an async operation.

Your problem descrption is not clear. I'm assuming that location is list of elements. So i'm applying each() on set elements called 'location' . It will work perfectly.
//replace location with myelement if it the correct one
location.each(function(ele,index){
expect(ele.getText()).toEqual("something");
});

Related

Nested loop Synchronous or Asynchronous?

I have an array called noNCreatedResources. I want do some operation on each item of array and push item in createdResources array and remove the item from noNCreatedResources array and continue to do that until noNCreatedResources be empty. For this I've written CreateResources function including nested while and for loop. It works fine but i realize that it don't work synchronously. For example: it must iterate twice in while loop but iterates 4 times and I don't know why.
I think I don't understand concept of async/await/non-blocking concept of node.js. can any body help me to realize what the problem is?
CreateResources = async () => {
while (this.noNCreatedResources.length > 0) {
for (let index = 0; index < this.noNCreatedResources.length; index++) {
if (this.resourceHasCreatedDependencies(this.noNCreatedResources[index])) {
const resourceModel = this.someOperation(this.noNCreatedResources[index]);
this.createdResources.push(resourceModel);
this.noNCreatedResources.splice(index, 1);
}
}
}
}
First of all you are not doing anything asynchronous in you function so you can remove the async keyword from your function. Since you are not doing anything asynchronous so, your problem is not related to it. It is more of an implementation problem IMO.
Your while loop is useless for what you are trying to achieve. Also, your logic is broken!
Example: The following code will output 1, 3, and 5.
let x = [1,2,3,4,5];
for(let i = 0; i < x.length; i++) {
console.log(x[i]);
x.splice(i, 1);
}
I do not think you need to remove item from array to achieve your expected result. If you need to reset the array then at the end you can just do this x = [] to reset the array.
The problem you have is not due to async calls. Actually, your code is entirely synchronous. Try to take a look at where the "noNCreatedResources" is been created/updated. Async calls happens when you're sending a http request, reading a file etc, in other words, operations that doesn't happens inside your code. It allows the code to go on, not blocking the next function calls, and when the promise is fulfilled, the callback function is invoked.

Sequelize migration - run an array of queries in order

I have a series of queries that need to run in a specific order. I've been trying this:
var queries = []
queries.push('update blah set foo="bar"')
queries.push('update baz set bar="foo"')
for(var i=0; i< queries.length; i++){
Promise.all([
migration.sequelize.query(queries[i]).then(function(result){
console.log(result)
})
])
}
done();
This does not work as anticipated. Any suggestions?
UPDATE: using recursion in the callback seems to work
var queries = []
queries.push('update blah set foo="bar"')
queries.push('update baz set bar="foo"')
var index = 0
var execute = function(queries){
if(typeof queries[index] == 'undefined'){
return done()
}
console.log(queries[index])
migration.sequelize.query(queries[index]).then(function(result){
console.log(result)
index += 1
return execute(queries)
})
}
execute(queries)
If you're on io.js and can write generators, or transpiling using Babel or TypeScript and can write async functions, this becomes very easy.
async function runSerialQueries(queries) {
var results = [];
for (var i=0; i<queries.length; i++) {
var query = queries[i];
var result = await migration.sequelize.query(query);
results.push(result);
}
return results;
}
runSerialQueries([
'update blah set foo="bar"',
'update baz set bar="foo"'
]).then(function(results) {
// ...
})
NOTE: The async keyword used above is a native feature of JavaScript EcmaScript 2016, not to be confused with the "async" npm module which is a completely different thing.
Anyhow, this solution ensures that one query doesn't start until the previous one ends, and will go in the order of the original array. It basically behaves just like it reads. If you can write generators but not async functions, something nearly identical can be done with generators, but requires a library like co() or Bluebird.coroutine().
Check out this excellent article for background on these techniques. They really are the future of JavaScript:
https://blog.risingstack.com/asynchronous-javascript/ <-- highly recommended!
I don't exactly know what the problem is with your code (if there any).
You should try with the each function of the async lib.
For example:
async.each(queries, function(query, done) {
// do the query here
done(); // this query is done, so runs the next one
});

Chaining nested asynchronous finds with Node.js monk and MongoDB

Using Node.js monk and MongoDB, I want to mimic a table join:
Do a find on collection A
For each result X, do a find in collection B, and update X
Return updated list of results
The asynchronous nature of database commands in monk is giving me trouble.
This is my initial code. It doesn't work because the second call to find returns a promise immediately,
and the results in xs are sent in the response before they can be updated.
var db = require('monk')('localhost/mydb');
db.get('collection').find({}, function(e,xs) {
xs.forEach(function(x){
coll_b.find({a_id:x._id}, function(e,bs) {
a['bs'] = bs;
});
});
res.json({'results':as});
});
I feel like I should use promise chaining here, but I cannot figure out how to do it.
Any help would be greatly appreciated.
I think I solved it in this way, inspired by this answer:
var db = require('monk')('localhost/mydb');
// Initial find
db.get('collection').find({}, function(e,xs) {
// Get inner finds as a list of functions which return promises
var tasks = xs.map(function(x){
return function() {
return coll_b.find({a_id:x._id}, function(e,bs) {
a['bs'] = bs;
});
}
});
// Chain tasks together
var p = tasks[0](); // start the first one
for(var i = 1; i < tasks.length; i++) p = p.then(tasks[i]);
// After all tasks are done, output results
p.then(function(_x){
res.json({'results':xs});
});
});
I still feel like this code could be minimised by using chain(), but at least this works as expected.
Note: I realise that performing a second find for each result is not necessarily efficient, but that's not my concern here.

Get the result at the right time with node

i am new to node.js, i followed some tutorial.
I don't know how to get the array "result" only when the call in the function end.
app.get('/api/email/check/:email',function (request,response){
var email = request.params['email'];
var result = Array();
for (var i = 0; i < 2; i++) {
existence.check(email, function(err,res){
result[i]=res; console.log({"Result":res});
});
};
response.send(result); // Problem is that i get: []
});
I got the log but the result is an empty array because it's called before the functions ends. Is there a nice way to resolve this ? without counting the "i".
You can put
response.send(result);
out of the for loop.
Because response.send() is a async method so before the for loop ends, response has ended before.

Migrating from localStorage to chrome.storage

I'm in the process of migrating my Chrome extension's persistency repository, from localStorage to chrome.storage. An important difference between them is that chrome.storage is asynchronous, therefore a callback function needs to be passed.
How would you modify a loop that writes to localStorage, synchronously, to the async chrome.storage?
for (var i = 0; i < obj.length; i++) {
localStorage.setItem(obj[i].key, obj[i].val);
}
doThisWhenAllElementsAreSaved();
Thanks.
For this example, I'll use chrome.storage.local, but you can replace it with chrome.storage.sync if you prefer.
The goal is to use chrome.storage.local.set. The first step is to convert your obj into an object that contains the list of pair of key / value:
var keyValue = {};
for (var i = 0; i < obj.length; i++)
{
keyValue[obj[i].key] = obj[i].val;
}
Then we call the actual method:
chrome.storage.local.set(keyValue, function()
{
// Notify that we saved.
doThisWhenAllElementsAreSaved();
});
or, simply:
chrome.storage.local(keyValue, doThisWhenAllElementsAreSaved);
Note that the callback will be called on success, as well as on failure. If the storage failed, then chrome.runtime.lastError will be set.
You can save multiple items at once with the chrome.storage API, so I would use the following approach:
Before, using localStorage.setItem
for (var i = 0; i < obj.length; i++) {
localStorage.setItem(obj[i].key, obj[i].val);
}
doThisWhenAllElementsAreSaved();
After, using chrome.storage.local.set
var items = {};
for (var i = 0; i < obj.length; i++) {
items[obj[i].key] = obj[i].val;
}
chrome.storage.local.set(items, function() {
doThisWhenAllElementsAreSaved();
});
If you need to know whether the save operation succeeded, check the value of chrome.runtime.lastError in the callback.
The best practice would be just to change the code to use chrome.storage.local like others said.
But sometimes, it gets really messy and you may want some code to remain untouched.
I tried to use a library that highly incorporates window.localStorage in a packaged app environment(the library was angular-cached-resource) and didn't want to change the original source code. So I managed to make the following shim: https://github.com/stewartpark/chrome-localStorage-shim
Hope it helps! Happy hacking.

Resources