Is there any way to use "this.remote" inside then? - intern

Is there any way to use "this.remote" inside then?
return this.remote
.findByCssSelector('.myClass')
.isDisplayed()
.then(function(disp) {
// How to use this.remote here?
})
.end();

You can use this.remote in a callback by saving a reference before hand, like:
var remote = this.remote;
return remote
.findByCssSelector('.myClass')
.isDisplayed()
.then(function (disp) {
return remote
.doLeadfootThings()
})
Another option is to use this.parent, like:
return this.remote
.findByCssSelector('.myClass')
.isDisplayed()
.then(function (disp) {
return this.parent
.doLeadfootThings()
})
this.parent is a pointer to the parent Command chain, so it has the context of the Command chain at the point of the then callback. The difference becomes important for subsequent operations.
return remote
.findById('someTable')
.then(function () {
// context of this.parent is #someTable
return this.parent
.findByTagName('tr')
// found TR is the first row in #someTable
.getVisibleText();
})
vs
return remote
.findById('someTable')
.then(function () {
// context of remote is empty
return remote
.findByTagName('tr')
// found TR is the first TF on the page, not necessarily the first
// in #someTable
.getVisibleText();
})

Another way is using bind()
return this.remote
.findByCssSelector('.myClass')
.isDisplayed()
.then(function(disp) {
// How to use this.remote here?
return this.remote...
}.bind(this))
.end();

Related

Model.findOne() function not working when passed a variable as the value

I am new to node.js.
I am trying to create function, where a randomly generated String is queried to check if it exists or not. If it already exists, the String is randomly generated till it is unique.
let validID = false;
console.log(temp); //temp is the randomly generated String.
while(!validID){
Website.findOne({shortcut: temp},function(err,docs){
if(docs==null){
validID = true;
console.log("The shortcut for the url is" + temp);
}else{
console.log("FOUND");
temp = generateId();
}
});
}
When run, the code is stuck in an infinite while loop.
I tried to see whether the code works with a String value ( not a variable ) passed in as the query inside findOne(). It worked. I am assuming that the fact that temp is a variable is causing the problem. Can variables be passed in as a value in a query? If so, what is the correct way?
Website.findOne operates asynchronously, i.e. the callback-function you passed to it, will be run once the results from the mongodb are fetched. However, node will not be able to actually process this callback, since your callstack never gets emptied due to your while-loop. If you're interested, you can find out more about this here.
One way to solve this is to wrap your Mongo-DB call in a promise, wait for it to resolve, then return if the ID is unique and continue by calling it recursively otherwise (note that this can be highly simplified by using async/await but for understanding how this works using promised are beneficial imo):
function findIdPromise(temp) {
return new Promise((resolve, reject) => {
Website.findOne({
shortcut: temp
}, function (err, docs) {
if (err) {
return reject(err);
}
resolve(docs);
});
});
}
function getNextIsUniqueIdPromise(shortcut) {
return findIdPromise()
.then(docs => {
if (docs == null) {
return shortcut;
}
return getNextIsUniqueIdPromise(generateId());
});
}
// call it initially with
getNextIsUniqueIdPromise(firstShortcutToCheck)
.then(shortcut => {
console.log("The shortcut for the url is" + shortcut):
})
.catch(err => {
console.log("an error occured", err):
});

How to call recursively a function that returns a promise?

I want to extract all child-Folders and child-Docs querying a node-js Service, which every time it is called, returns an array of such items. I do not know the depth fo the folders-tree so I want to recursively call a function that in the end will return an array that will contain all child-folders and child-docs, starting from a list of root-Folders. Each folder is identified by a folder id.
So I have made a "recPromise(fId)" which returns a promise. Inside, this function calls recursively the recFun(folderId).I start invoking the "recPromise(fId)" from a rootFolder so once all root-promises are resolved I can go on.
rootFolders.map( folderOfRootlevel =>{
var folderContentPromise = recPromise(folderOfRootlevel.id);
folderContentPromises.push(folderContentPromise);
})
$q.all(folderContentPromises)
.then(function(folderContent) {
// Do stuff with results.
}
function recPromise(fId){
return new Promise((resolve, reject) => {
var items = [];
function recFun( folderId) { // asynchronous recursive function
function handleFolderContent( asyncResult) { // process async result and decide what to do
items.push(asyncResult);
//Now I am in a leaf-node, no child-Folders exist so I return
if (asyncResult.data.childFolders.length === 0){
return items;
}
else {
//child_folders exist. So call again recFun() for every child-Folder
for(var item of asyncResult.data.childFolders) {
return recFun(item._id);
}
}
}
// This is the service that returns the array of child-Folders and child-Docs
return NodeJSService.ListFolders(folderId).then(handleFolderContent);
}
resolve(recFun(fId));
})
}
It works almost as expected except the loop inside else, where I call again recFun().
The NodeJSService will return an array of sub-Folders so I wish to call recfun() for every sub-Folder.
Now, I only get the result of the 1st sub-Folder of the loop,
which makes sense since I have a return statement there.
If I remove the return statement and call like this "recFun(item._id);"
then it breaks the $q.all().
Finally, I decided to remove the Promise wrapper function and make use of async-await.
var items = [];
(async() => {
for(var item of rootFolders) {
await recFun(item.id)
}
// Do stuff with items
// go on form here..
})()
function listFolders(folderId) {
return new Promise( function( resolve, reject) {
resolve(FolderService.ListFolders(folderId));
})
}
async function recFun(folderId) {
var foldersResponse= await listFolders(folderId);
items.push(foldersResponse);
if (foldersResponse.data.childFolders.length === 0){
return items ;
}
else {
for(var item of foldersResponse.data.childFolders) {
await recFun(item._id);
}
}
}

How to wait for function to complete before returning?

i'm attempting to create a function I can call from any test that'll look at the element being passed (link text, Css Selector, Xpath, ID), click on the element, and then verify the URL that comes up after it loads. The problem i'm having is that it's returning before the function is finished.
I know I need to implement async and a callback, but i'm having a hard time understanding the structure.
clickIDverifyURL: function clickByID (elementVar, elementURL){
var rem = this.remote;
// if statements to look at elementVar and select the right one.. example:
// rem.setFindByTimeout(10000)
// .findByXpath (elementVar)
// .click()
// .end()
return this.remote
// if I code it right, I shouldn't need this sleep right?
.sleep(30000)
.getCurrentUrl()
.then(function(currURL) {
console.log(currURL);
try {
assert.strictEqual(currURL, elementURL, "This test checks to see if the current URL is correct.")
}
catch (e)
{
console.log(e)
}
});
}
Appreciate any help or comments.
You're on the right track. Assuming you want to click the element, wait for a page transition, then check the resulting URL, you could do something like:
clickIDverifyURL: function (elementURL) {
return function (element) {
return this.parent
.then(function () {
return element.click();
})
// Wait for the page transition. This can be a sleep, or you can search for an
// element that should be on the new page (intern will implicitly wait for it
// to appear), or use pollUntil to wait for a more specific condition.
.sleep(1000)
// Get the page URL
.getCurrentUrl()
.then(function (url) {
assert.strictEqual(url, elementURL);
});
}
}
You would use it like:
.findElementByCssSelector('.someselector')
.then(myModule.clickIDverifyURL('expectedURL'))
clickIDVerifyURL takes in some configuration data (the expected URL) and returns a function that can be called in a Command's then callback. Such functions have a parent property in their context that references the parent Command chain (the chain of functions started from this.remote).
Note that methods called on Elements, like element.click() above, return Promises, not Commands. This means that only standard Promise methods can be chained, not Command methods like click, findElementByX, etc. That's why the code above starts the inner chain from this.parent rather than element.
Update
The same basic structure works for other types of helper method. For example, if you wanted to use a helper method to do a find, it might look like:
findBySomething: function (selector) {
return function () {
var setContext = arguments[arguments.length - 1];
return this.parent
.findByCssSelector(selector)
.then(function (element) {
setContext(element);
});
}
}
Then you could do
this.remote
.then(myModule.findBySomething('.selector'))
.then(myModule.clickIDverifyURL('expected URL'))

Meteor method doesn't work

Assume that I have a Collection called Tasks which has few tasks in it.I call a method to return a task array to the user but for some reason it doesn't return anything.
Here is a code for example:
if (Meteor.isClient) {
// This code only runs on the client
Template.body.helpers({
tasks: function () {
// Show newest tasks first
Meteor.call("getTasks", function(error, result) {
return result; // Doesn't do anything..
});
}
});
}
Meteor.methods({
getTasks: function() {
return Tasks.find({}, {sort: {createdAt: -1}});
}
});
Any ideas why when I call the method it doesn't return anything?
Tasks.find() returns a cursor, which makes no sense to transmit to the client via DDP.
You probably mean to return Tasks.find().fetch(), but that defeats the purpose of Meteor's very nice data synchronization mechanism.
Have you read Understanding Meteor's publish/subscribe?

return value from a function with asynchronous commands

I'm writing a NodeJS v0.10 application with MariaSQL.
i want to create a function that returns the id of a row, and if the row doesn't exist, to create it and then return the id.
this is what I have so far:
TuxDb.prototype.createIfNEDrinkCompany = function(drinkCompany) {
this.client.query("insert into drink_company(drink_company_name) values(:drink_company) on duplicate key update drink_company_id=drink_company_id",
{'drink_company' : drinkCompany})
.on('result',function(res) {
res.on('end',function(info){
if (info.insertId > 0) {
return info.insertId;
} else {
this.client.query("select drink_company_id from drink_company where drink_company_name = :drink_company",{'drink_company' : drinkCompany})
.on('result',function(res){
res.on('row',function(row){
return row.drink_company_id;
});
});
}
});
});
}
now the problem is that since it's asynchronous, the function ends before the value is returned.
how can I resolve this issue ?
The standard way in nodejs of dealing with async code is to provide a callback function as a last argument to your method and call it whenever your asynchronous finishes. The callback function standard signature is (err, data) - you can read more about here: Understanding callbacks in Javascript and node.js
Rewriting your code:
TuxDb.prototype.createIfNEDrinkCompany = function(drinkCompany, callback) {
this.client.query("insert into drink_company(drink_company_name) values(:drink_company) on duplicate key update drink_company_id=drink_company_id",
{'drink_company' : drinkCompany})
.on('result',function(res) {
res.on('end',function(info){
if (info.insertId > 0) {
callback(null, row.drink_company_id);
} else {
this.client.query("select drink_company_id from drink_company where drink_company_name = :drink_company",{'drink_company' : drinkCompany})
.on('result',function(res){
res.on('row',function(row){
callback(null, row.drink_company_id);
});
});
}
});
});
}
and then in the code calling your method
db.createIfNEDrinkCompany(drinkCompany, function(err, id){
// do something with id here
})

Resources