Is there a way how to check whether an element has any text in it? I already found textToBePresentInElement but this function checks for specified value and does not return a proper error if it fails.
I'm population the element via API and it's loaded bit later, so I want the browser to wait till any information appears in the element and then check for correct value.
Alternatively it would be also very helpful to manage to get a specific error message when EC fails:
browser.wait(EC.textToBePresentInElement(element(by.binding('myvar')), "expected"), 5000);
The third argument to browser.wait() is a custom error message:
browser.wait(EC.textToBePresentInElement(element(by.binding('myvar')), "expected"), 5000, "Text is not something I've expected");
See also:
Custom message on wait timeout error
To wait for an element to contain any text, you can write a custom expected condition:
var EC = protractor.ExpectedConditions;
var anyTextToBePresentInElement = function(elementFinder) {
var hasText = function() {
return elementFinder.getText().then(function(actualText) {
return actualText;
});
};
return EC.and(EC.presenceOf(elementFinder), hasText);
};
And here is the usage:
browser.wait(anyTextToBePresentInElement(element(by.binding('myvar'))), 5000);
The previous code snippet works form but with a small update: return actualText; should be boolean. So the whole code will be:
var anyTextToBePresentInElement = function(elementFinder) {
var EC = protractor.ExpectedConditions;
var hasText = function() {
return elementFinder.getText().then(function(actualText) {
return !!actualText;
});
};
return EC.and(EC.presenceOf(elementFinder), hasText);
};
Usage example:
var el = element(by.binding('myvar'));
browser.wait(anyTextToBePresentInElement(el, 5000, 'Element still has no text');
You can check this one
export function titleType(textReference, expectedText)
{
textReference.then(function(name)
{
if (name == expectedText)
{
expect(textReference).toContain(expectedText);
expect(name).toEqual(expectedText);
}
else
{
throw new TypeError("Wrong " + expectedText + " name " + name);
}
});
}
Related
I have imorted a module that performs a function on an array of data. When I run the function I get the results in my server but they seem not to be stored in my variable, which comes back undefined. Can someone tell me why my array comes back undefined when I can see the array in my server?
var net = require('net');
var foo = require('./employeeModule');
var _ = require('underscore');
var colors = require('colors/safe');
var server = net.createServer(
function(socket){
console.log("Client connection...");
socket.on('end', function(){
console.log("Client disconnected...");
});
// process data from client
socket.on('data', function(data){
var command = data.toString();
var results={};
console.log("Received Command: " +command);
if (command == "lookupByLastName Smith")
{
function lastName(results)
{
var results = foo.lookupByLastName('Smith');
console.log('These are the results: '+ results)
}
lastName();
}
else if (command == "addEmployee William Smith")
{
function addEmp(results)
{
var results = foo.addEmployee('William', 'Smith');
console.log('These are the results: '+ results)
}
addEmp();
}
else if (command == "lookupById 4")
{
function lookId(results)
{
var results = foo.lookupById(4);
console.log('These are the results: '+ Name)
}
lookId();
}
else if (command == "bye")
client.end();
else console.log(colors.green("**"+command+" Command not recognized!**"));
});
});
//listent for client connections
server.listen(1000, function(){
console.log("Listening for client connections");
});
First, what is wrong with your code:
var results={}: the var results is not used.
you have 3 functions lastName, addEmp and lookId. All are called and nothing is passed, therefore the results var is always undefined.
inside every of those functions you are defining another var results, so, nothing is done with the results parameter (like overwriting it).
in lookId the var Name it is undefined.
I suppose that you have the parameters hardcoded (commands, like William Smith, 4 or Smith) because it is some type of "test"/learning exercise. I would not recommend you to define the 3 functions inside the callback function (because they are defined every time it is called the callback).
If you want to keep the results do this (following your type of coding):
function addEmp(){
var res = foo.addEmployee('William', 'Smith');
console.log("There asre the results: " + res);
return res;
}
results = addEmp(); // now you set the value to results
Following more or less what would you do, I would do something like (be careful, I change a bit the type of coding and boundaries/inputs are not controlled):
function lastName(surname){
return foo.lookupByLastName(surname);
}
function addEmp(name, surname){
return foo.addEmployee(name, surname);
}
// ...
function socketData(data){
var args = data.toString().split(' '); // assuming space as splitter
var results;
var command = args[0];
switch(command){
case 'lookupByLastName':
results = lastName(args[1]);
break;
case 'addEmp':
results = addEmp(args[1], args[2]);
break;
default:
// ...
}
// do something with results
}
var server = net.createServer(function(socket){
// ...
socket.on('data', socketData);
// ...
});
I write Protractor automation tests and faced an issue. Wait command doesn't actually wait for one of the array elements. See the example below: I try to wait for the first element after navigating to webpage.
var category = element.all(by.repeater('category in listCtrl.categories'));
var category2 = $$('.category-name.custom-tooltip-link.ng-binding');
var EC = protractor.ExpectedConditions;
describe('wait for the first category', function() {
it('wait', function() {
browser.get('http://www.deep.mg/');
browser.wait(EC.visibilityOf(category.get(0)), 20000);
browser.wait(EC.visibilityOf(category2.get(0)), 20000);
});
});
But test fails with the following error: Failed: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator by.repeater("category in listCtrl.categories").
Error doesn't depend on locator type, because appears for both: "by.repeater" and "by.css".
The selectors are ok, test passes after adding 'sleep' command:
var category = element.all(by.repeater('category in listCtrl.categories'));
var category2 = $$('.category-name.custom-tooltip-link.ng-binding');
var EC = protractor.ExpectedConditions;
describe('wait for the first category', function() {
it('wait', function() {
browser.get('http://www.deep.mg/');
browser.sleep(15000);
browser.wait(EC.visibilityOf(category.get(0)), 20000);
browser.wait(EC.visibilityOf(category2.get(0)), 20000);
category.count().then(function(count1) {
console.log(count1); //count returns 5, which means there are actually elements in array
});
category2.count().then(function(count2) {
console.log(count2);
});
});
});
Also timeout parameter doesn't help, it just ignores it and fails immediately.
So the question is how to wait for a certain element of an array? Am I missing something? Thanks.
Make a custom Expected Condition to wait for count of elements in an array to be more than 0:
function presenceOfAll(elementArrayFinder) {
return function () {
return elementArrayFinder.count(function (count) {
return count > 0;
});
};
}
Usage:
browser.wait(presenceOfAll(category), 10000);
browser.wait(presenceOfAll(category2), 10000);
Works for me.
element.all(by.repeater('category in listCtrl.categories')).get(0) will ALWAYS throw an error if there are no elements to 'get' (source: element.js ElementArrayFinder.prototype.get)
You can do:
browser.wait(function() {
return category.count().then(function(catCount) {
if (catCount > 0) {
return EC.visibilityOf(category.get(0));
}
}
}, 20000);
Or you could probably just wait until all the elements are visible, and it would do what you are asking it to do (because it will wait for the 'all' promise to resolve completely anyway, not just break out when it gets the first one):
browser.wait(EC.visibilityOf(category), 20000);
I have an array from my API that prints like this:
Array [Object, Object, Object, Object, Object]
// if stringified
[{"id":"0","name":"user1","type":"mf","message":"bonjour user1"},
{"id":"1","name":"user2","type":"ff","message":"hello user2"},
{"id":"2","name":"user3","type":"mm","message":"konnichiwa user3"},
{"id":"3","name":"user4","type":"mf","message":"ni hao user4"},
{"id":"4","name":"user5","type":"ff","message":"high 5! user5"}]}
I have an input named content and I would like to see if it matches any of the name in the array; if it does, which id is it; if it's not, the id would be 0.
Eg. if user enters user3, the id would be 2; and if user enters user9, the id would be 0.
I have been struggling to get the value of name from this nested array and below is what I have tried... and the whole code is here. It would be very nice if someone could tell me where have I done wrong:
var data = {};
$.ajax({
url: googleApi,
headers: {
"Authorization": "Basic " + btoa(googleKey + ":" + googleSecret)
},
data: data,
dataType: 'json',
type: 'GET',
success: function(data) {
console.log(data);
console.log(JSON.stringify(data));
function getID(name){
if (name.name == content){
console.log ("matching name" + name.name);
return getID(name.name);
} else {
return name;
}
}
alert(getID(data).id);
return false;
},
error: function(data) {
console.log("ERROR: " + data);
}
});
Updated Answer:
Dont alert the function, just alert the answer inside the loop when it matched.
I typed alexis in the textbox and the output was 1
I have edited my answer.Check it, this is what you have to do in your case:
function getID(name) {
$.each(data,function(key,value){
$.each(value,function(key1,value1){
console.log(value);
if(value1 == content){
alert(value.id);
return;
}
});
});
}
getID(data);
return false;
Take a look at the updated fiddle Fiddle Example
Second Update:
You do not have to use else if condition, simply use a variable to check whether there has been any matches.
You create a empty variable and while looping through the array check whether there is a match and if there is a match, you just feed the variable with that id value and later you will check whether the variable is empty or not and based on that alert(0);
Checkout the Latest Updated Fiddle
As you are using jQuery, you can use the grep function which is intended for searching an array:
var contentArray = [{"id":"0","name":"user1","type":"mf","message":"bonjour user1"},
{"id":"1","name":"user2","type":"ff","message":"hello user2"},
{"id":"2","name":"user3","type":"mm","message":"konnichiwa user3"},
{"id":"3","name":"user4","type":"mf","message":"ni hao user4"},
{"id":"4","name":"user5","type":"ff","message":"high 5! user5"}];
var input = 'user5';
var result = $.grep(contentArray, function(e){ return e.name == input; });
The result is an array with the items found. If you know that the object is always there and that it only occurs once, you can just use result[0].id to get the value. Otherwise you should check the length of the resulting array. Example:
if (result.length === 0) {
// not found
} else if (result.length === 1) {
// access the name property using result[0].id
} else {
// multiple items found
}
So you can design a function for above as per your requirement, something like below:
function getID(myArr, inputName) {
var result = $.grep(myArr, function(e){ return e.name == inputName; });
if (result.length === 0) {
return 0;
} else if (result.length === 1) {
return result[0].id
} else {
// multiple items found
// May be it's not true in your case
return result[0].id
}
}
I'm trying to create a nightwatchJS custom assertion that will check if a file exists. The assertion appears to fire, but nightwatch exits as soon as the assertion command finishes.
I guess I'm not returning control to the nightwatch api, but if thats the case then how can I achieve that?
// filename = doesFileExist.js
exports.assertion = function(fname, msg) {
var fs = require('fs');
this.message = msg + 'FileExists: ' + fname ;
this.expected = true;
this.pass = function(value) {
return value == this.expected;
} ;
this.value = function(result) {
return result;
};
this.command = function(callback) {
return fs.exists(fname, callback);
};
};
and the test case (using nightwatch.json as an example) is ;
this.checkForFile = function() {
browser
.verify.doesFileExist('nightwatch.json', 'test1')
return browser;
};
I know this is an old question, but I found in writing my own custom assertions that you need to return 'this' in your command function. The callback is what sends your value to this.value which is used in the pass function.
So it would look like this
this.command = function(callback) {
fs.exists(fname, callback);
return this;
};
I needed to add an api.execute around my call to make the function halt.
this.command = function (callback) {
var someValue = evaluateSomeValueHere;
return this.api.execute(
function (someValue) {
return someValue;
}, [someValue],
function (result) {
callback(result.value);
}
)
};
I'm having trouble decorate the objects in my list returned by $asArray in angularfire with a new method (not decorating the array itself).
The angularfire documentation seems to suggest that the right way to do this is to override the $$added method in the factory for $FirebaseArray, returning a new object that either encapsulates or extends the snapshot that gets passed in to that method. From the documentation:
// an object to return in our JokeFactory
app.factory("Joke", function($firebaseUtils) {
function Joke(snapshot) {
this.$id = snapshot.name();
this.update(snapshot);
}
Joke.prototype = {
update: function(snapshot) {
// apply changes to this.data instead of directly on `this`
this.data = snapshot.val();
},
makeJoke: function() {
alert("Why did the " + this.animal + " cross the " + this.obstacle + "?");
},
toJSON: function() {
// since we didn't store our data directly on `this`, we need to return
// it in parsed format. We can use the util function to remove $ variables
// and get it ready to ship
return $firebaseUtils.toJSON(this.data);
}
};
return Joke;
});
app.factory("JokeFactory", function($FirebaseArray, Joke) {
return $FirebaseArray.$extendFactory({
// change the added behavior to return Joke objects
$$added: function(snap) {
return new Joke(snap);
},
// override the update behavior to call Joke.update()
$$updated: function(snap) {
this.$getRecord(snap.name()).update(snap);
}
});
});
However, when I do this in my code, nothing ever gets added to the array, although I can see from outputting to the console that it is getting called.
var printMessageObjConstructor = function(snap) {
this.$id = snap.name();
this.snapshot = snap;
this.$update = function(snap) {
this.snapshot = snap;
};
this.printMessage = function() {
return this.author + "'s question is: " + this.body;
};
};
var ref = new Firebase("https://danculley-test.firebaseio.com/questions");
//What Am I Doing Wrong Here?
var arrayFactory = $FirebaseArray.$extendFactory({
$$added: function(snap, prevChild) {
var x = new printMessageObjConstructor(snap);
console.log("I am being called from FirebaseDecoratedCtlOverloadAddedinNewObj.");
return x;
},
$createObject: function(snap) {
return new printMessageObjConstructor(snap);
},
$$updated: function(snap) {
var i = this.$indexFor(snap.name());
var q = this.$list[i];
q.$update(snap);
}
});
var sync = $firebase(ref, {arrayFactory:arrayFactory});
var list = sync.$asArray();
list.$loaded(function(list) {
$scope.questions = list;
});
I've set up a new plunk stripped down to show the issue with a couple other use cases that I've tried. (The actual method I'm adding is more complex and isn't related to the view, but I wanted to do something simple to reproduce the issue.)
I think the issue is that I don't quite understand what exactly $$added is supposed to return, or what additional behavior beside returning the value to be stored $$added is supposed to have. There also doesn't really seem to be an $$added on the prototype or on $FirebaseArray to call as a super to get the default behavior. Can someone point me in the right direction?
UPDATE
For the benefit of others, after reviewing the like that Kato posted, I was able to solve the issue by adding the following, almost all copied directly from the source except for the commented line below.
$$added: function(snap, prevChild) {
var i = this.$indexFor(snap.name());
if( i === -1 ) {
var rec = snap.val();
if( !angular.isObject(rec) ) {
rec = { $value: rec };
}
rec.$id = snap.name();
rec.$priority = snap.getPriority();
$firebaseUtils.applyDefaults(rec, this.$$defaults);
//This is the line that I added to what I copied from the source
angular.extend(rec, printMessageObj);
this._process('child_added', rec, prevChild);
}
}
For the benefit of others, after reviewing the link that Kato posted, I was able to solve the issue by adding the following, almost all copied directly from the source except for the commented line below.
$$added: function(snap, prevChild) {
var i = this.$indexFor(snap.name());
if( i === -1 ) {
var rec = snap.val();
if( !angular.isObject(rec) ) {
rec = { $value: rec };
}
rec.$id = snap.name();
rec.$priority = snap.getPriority();
$firebaseUtils.applyDefaults(rec, this.$$defaults);
//This is the line that I added to what I copied from the source
angular.extend(rec, printMessageObj);
this._process('child_added', rec, prevChild);
}
}