nightwatch.js return value from function outside a test - function

I have trouble moving certain code outside a test into a function that needs to return a value.
Here is part of my code for the test file
function getCountOfTopics(browser){
var count;
browser.getText('#sumTopics',
function(result){
count = result.value;
console.log(result.value);
}
);
return count;
};
module.exports = {
'Create article' : function(browser){
var noOfThreadsByInlineCode, noOfThreadsByFunction;
browser.getText('#sumTopics',
function(result){
noOfThreadsByInlineCode = result.value;
}
);
noOfThreadsByFunction = getCountOfTopics(browser);
browser.end();
}
}
Now, the variable noOfThreadsByInlineCode indeed gets the value in the DOM, but the variable noOfThreadsByFunction is undefined. The console does indeed print the correct value, so the function does get the correct value out of the DOM.
I would appreciate help in updating the function so that I do get the value returned.

One word answer is Asynchronisity. The code doesn't wait for your callback to get complete, thats what the feature of Node JS is.
If you are in desperately in need for the content inside of the callback you can write this variable into a file and then access it anywhere you want inside your code. Here's a bit of a workaround:
Save something in a file:
var fs = require('fs');
iThrowACallBack(function(response){
fs.writeFile('youCanSaveData.txt', this.response, function(err) {
if (err) throw err;
console.log('Saved!');
browser.pause(5000);
});
});
Access it somewhere else:
iAccessThefile(){
response = fs.readFileSync('youCanSaveData.txt').toString('utf-8');
}
Hope it helps.

You return variable 'count' outside the callback,that is why.You can take a look this topic How to return value from an asynchronous callback function?
function getCountOfTopics(browser){
var count;
browser.getText('#sumTopics',
function(result){
count = result.value;
console.log(result.value);
/// result.value is available in this callback.
}
);
What do you want to do with the 'value'?
ps:do not remember custom_command.I think it is very helpful for this issue.

Related

Save result to variable?

So I have been developing a note taking app, and I am having some trouble with displaying the username! Normally you would get a result like this:
con.query('SELECT someVariable FROM someColumn', function (result) {
console.log(result)
})
But I would like to save the result to a variable like this:
var variable = '';
con.query('SELECT someVariable FROM someColumn', function (result) {
variable = result
})
console.log("Here is some data: " + variable)
But that obviously wouldn't work. So how can I do this???
The point
How would I save a mySQL result to a variable, so it can be used later in my code? Also Im not an experienced developer so you might have to do a bit more explaining that usual, thanks.
If you're new to Node and/or JavaScript then you've just stumbled on one of the major problems of asynchronous programming. Here's your code as the JavaScript runtime sees it:
// Declare variable
var variable = '';
var callback = function(result) {
variable = result;
};
// This code runs right away
con.query('SELECT someVariable FROM someColumn', callback);
// Then this code runs
console.log("Here is some data: " + variable);
// Then, a thousand years later (from a CPU's perspective) this callback executes
callback(result);
You can see you're jumping the gun here. You can't depend on any behaviour until the callback has run, or in other words, you need to put any dependent behaviour inside the callback.
Since it's 2020 you can also do this with async and await if you're using a Promise-capable library. Your code could look like:
// Assign variable to the result of the query call, waiting as long as necessary
let variable = await con.query('SELECT someVariable FROM someColumn');
console.log("Here is some data: " + variable);
This will be properly sequenced.

Google Script call another function to return a value

I'm getting to grips with beginner methods of GScript now but so far have only used one function. Could someone show me how to 'call' another function to check for something and then return a TRUE or FALSE. Here is my attempt (it will eventually check a lot of things but I'm just checking one thing to start..)
Function callAnotherFunctionAndGetResult () {
MyResult = call(CheckTrueFalse)
if(MyResult = True then.. do something)
};
function CheckTrueFalse() {
if(3 > 2) {
CheckTrueFalse = TRUE
Else
CheckTrueFalse = FALSE
};
So basically I just want to get the other function to check something (in this case is 3 bigger than 2?) if it is then return TRUE. From this I should have the knowledge to modify for the real purpose. I'm used to Visual Basic so I've written it more how that would look - I know that won't work. Could someone help me convert so will work with Google Script please?
A function with a return statement is what you're looking for. Assuming you need the called function to take some input from the main function:
function mainFunction() {
//...
var that = "some variable found above";
//call other function with input and store result
var result = otherFunction(that);
if (result) {
//if result is true, do stuff
}
else {
//if result is false, do other stuff
}
}
function otherFunction(that) {
var this = "Something"; //check variable
return (this == that);
//(this == that) can be any conditional that evaluates to either true or false,
//The result then gets returned to the first function
}
You could also skip assigning the result variable and just check the returned condition directly, i.e.:
if (otherFunction(that)) {
//do stuff
}
else {do other stuff}
Let me know if you need me to clarify any of the syntax or if you have any more questions.
Here's a basic sample that might help you:
function petType(myPet){
return myPet;
}
function mainFunctoin(){
var newPet = petType("dog");
if(newPet === "dog"){
Logger.log("true");
}else{
Logger.log("false");
}
}
Execute mainFunction().
If you set petType to "cat", it will return false; but, if you set it to "dog", it will return true.
Let me know if it helped.

JSON array undefined & empty in promise Bluebird

I am using Promise bluebird to process a json array objects from file. The problem arises if I want to store data in a json array (called list) and return this in the final process.
The list is empty/undefined after the return of list or even in the final process. Running the code, I always have 1 value that is not false which trigger the adding/push of the json in the list.
Can you help me with this issue? Below you will find my code.
Thanks in advance !!!
var Promise = require('bluebird');
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));
fs.readdirAsync(dir).map(function (filename) {
return fs.readFileAsync(dir + "/" + filename, "utf8");
}).then(function(result){
var list=[];
result.map(function(row, index){
Promise.coroutine(function*() {
update(row, index).then(function(value){
if (value!=false){
var trade_update = new updated_Item(row.ID, row.Quantity, row.Price, row.Remark);
list.push(trade_update);
console.log(JSON.stringify(list)); <-- This works. It gives me data
}
return list;
})
})();
});
console.log('list: ' + JSON.stringify(list)); <-- output: list:[]
return list;
}).finally(function(result){
console.log('Final outcome: '+ ' ' + JSON.stringify(result)); <-- output: Final outcome: undefined
})
With the help of Samuel my code is now:
var Promise = require('bluebird');
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));
function updateOrder(done){
fs.readdirAsync(dir).map(function (filename) {
return fs.readFileAsync(dir + "/" + filename, "utf8");
}).then(function(result){
var list=[];
result.map(function(row, index){
Promise.coroutine(function*() {
update(row, index).then(function(value){
if (value!=false){
var trade_update = new updated_Item(row.ID, row.Quantity, row.Price, row.Remark);
list.push(trade_update);
done(list);
}
})
})();
});
//done(list); <--if I put the done callback here, it will give me an empty list. I though once the result.map finished processing all the values give me the end result.
}
}
updateOrder(function(resultList){
console.log('List' + JSON.stringify(resultList));
})
This code give me whole resultList everytime the list has been updated (pushed) now.
I would to receive the resultList at the end once the function updateOrder is finished.
As noted in the comment. Promise.coroutine is asynchronous so this means that a result is not going to get return straight after your code reaches it. And this pretty much explains the phenomenon you are seeing where the latter print statements you got in the code is suggesting that list is undefined.
What you could do is wrap the entire code you got there in a function, then add a callback function as a parameter for the async functions to invoke when it has finished its duty, together returning the populated list back for later processing.
I have written a pseudo code for your case, unfortunately I couldn't test it on my IDE but the concept is there and it should work.
Consider my pseudo code:
var Promise = require('bluebird');
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));
// Wrap everything you got into a function with a `done` parameter (callback fn)
function doStuff(done) {
fs.readdirAsync(dir).map(function (filename) {
return fs.readFileAsync(dir + "/" + filename, "utf8");
}).then(function(result){
var list=[];
result.map(function(row, index){
Promise.coroutine(function*() {
update(row, index).then(function(value){
if (value!=false){
var trade_update = new updated_Item(row.ID, row.Quantity, row.Price, row.Remark);
list.push(trade_update);
}
done(list);
})
})();
});
}).finally(function(result){
console.log('File read finish, but this doesnt mean I have finished doing everything!');
})
}
// call your function and provide a callback function for the async method to call
doStuff(function(resultList) {
console.log('list: ' + JSON.stringify(resultList));
// Continue processing the list data.
});

Trying to interpret the Node-Neo4j API

I'm pretty new to coding so forgive me if my code is unreadable or my question simplistic.
I am trying to create a little server application that (amongst other things) displays the properties of a neo4j node. I am using node.js, Express and Aseem Kishore's Node-Neo4j REST API client, the documentation for which can be found here.
My question stems from my inability to fetch the properties of nodes and paths. I can return a node or path, but they seem to be full of objects with which I cannot interact. I poured through the API documents looking for some examples of how particular methods are called but I found nothing.
Ive been trying to call the #toJSON method like, "db.toJSON(neoNode);" but it tells me that db does not contain that method. I've also tried, "var x = neoNode.data" but it returns undefined.
Could someone please help me figure this out?
//This file accepts POST data to the "queryanode" module
//and sends it to "talkToNeo" which queries the neo4j database.
//The results are sent to "resultants" where they are posted to
//a Jade view. Unfortuantly, the data comes out looking like
// [object Object] or a huge long string, or simply undefined.
var neo4j = require('neo4j');
var db = new neo4j.GraphDatabase('http://localhost:7474');
function resultants(neoNode, res){
// if I console.log(neoNode) here, I now get the 4 digit integer
// that Neo4j uses as handles for nodes.
console.log("second call of neoNode" + neoNode);
var alpha = neoNode.data; //this just doesn't work
console.log("alpha is: " +alpha); //returns undefined
var beta = JSON.stringify(alpha);
console.log("logging the node: ");
console.log(beta);// still undefined
res.render("results",{path: beta});
res.end('end');
}
function talkToNeo (reqnode, res) {
var params = {
};
var query = [
'MATCH (a {xml_id:"'+ reqnode +'"})',
'RETURN (a)'
].join('\n');
console.log(query);
db.query(query, params, function (err, results) {
if (err) throw err;
var neoNode = results.map(function (result){
return result['a']; //this returns a long string, looks like an array,
//but the values cannot be fetched out
});
console.log("this is the value of neoNode");
console.log(neoNode);
resultants(neoNode, res);
});
};
exports.queryanode = function (req, res) {
console.log('queryanode called');
if (req.method =='POST'){
var reqnode = req.body.node; //this works as it should, the neo4j query passes in
talkToNeo(reqnode, res) //the right value.
}
}
EDIT
Hey, I just wanted to answer my own question for anybody googling node, neo4j, data, or "How do I get neo4j properties?"
The gigantic object from neo4j, that when you stringified it you got all the "http://localhost:7474/db/data/node/7056/whatever" urls everywhere, that's JSON. You can query it with its own notation. You can set a variable to the value of a property like this:
var alpha = unfilteredResult[0]["nodes(p)"][i]._data.data;
Dealing with this JSON can be difficult. If you're anything like me, the object is way more complex than any internet example can prepare you for. You can see the structure by putting it through a JSON Viewer, but the important thing is that sometimes there's an extra, unnamed top layer to the object. That's why we call the zeroth layer with square bracket notation as such: unfilteredResult[0] The rest of the line mixes square and dot notation but it works. This is the final code for a function that calculates the shortest path between two nodes and loops through it. The final variables are passed into a Jade view.
function talkToNeo (nodeone, nodetwo, res) {
var params = {
};
var query = [
'MATCH (a {xml_id:"'+ nodeone +'"}),(b {xml_id:"' + nodetwo + '"}),',
'p = shortestPath((a)-[*..15]-(b))',
'RETURN nodes(p), p'
].join('\n');
console.log("logging the query" +query);
db.query(query, params, function (err, results) {
if (err) throw err;
var unfilteredResult = results;
var neoPath = "Here are all the nodes that make up this path: ";
for( i=0; i<unfilteredResult[0]["nodes(p)"].length; i++) {
neoPath += JSON.stringify(unfilteredResult[0]['nodes(p)'][i]._data.data);
}
var pathLength = unfilteredResult[0].p._length;
console.log("final result" + (neoPath));
res.render("results",{path: neoPath, pathLength: pathLength});
res.end('end');
});
};
I would recommend that you look at the sample application, which we updated for Neo4j 2.0
Which uses Cypher to load the data and Node-labels to model the Javascript types.
You can find it here: https://github.com/neo4j-contrib/node-neo4j-template
Please ask more questions after looking at this.

Custom binding to return the last Json record

I'm using the following code to load all Json data.
$.getJSON("/Home/GetSortedLists", function (allData) {
var mappedSortedLists = $.map(allData, function (item) { return new SortedLists(item) });
viewModel.sortedlists(mappedSortedLists);
});
I also need to load a single record from the same Json data; the record with the highest SortedListsID value (i.e. the last record entered).
Can anybody suggest the best way to do this? I've considered adding viewModel.lastsortedlist and amending the above code somehow. I've also considered creating a last custom binding to do something like:
<tbody data-bind="last: sortedlists.SortedListID">
All advice welcome.
Unless you want to do more ui-related stuff with the record, I don't think you need the custom binding.
It should be enough to compute it in the getJSON callback and save it in the viewModel:
$.getJSON("/Home/GetSortedLists", function (allData) {
var mappedSortedLists = $.map(allData, function (item) { return new SortedLists(item) });
viewModel.sortedlists(mappedSortedLists);
//correct the sort function if it's bad, or drop it if allData is already sorted
var sortedData = allData.sort(function(a,b){ return a.SortedListID - b.SortedListID})
viewModel.lastSortedList(sortedData[sortedData.length - 1])
});
Or, if it can change outside the getJSON callback, you could also make it a computed observable:
viewModel.lastSortedList = ko.computed(function(){
//correct the sort function if it's bad, or drop it
var sortedData = mappedSortedLists().sort(function(a,b){ return a.SortedListID - b.SortedListID})
return sortedData[sortedData.length - 1]
}, this)