Error when trying to get single item from element.all in Protractor - protractor

I have the following test code (a simplified example):
e = element(by.id('element-id'));
it('description', function(){
e.all(by.tagName('my-directive')).then(function(items){
expect(items.count()).toEqual(3); //error
expect(items.length).toEqual(3); //ok
expect(items.get(0).getAttribute('my-attr')).toEqual('1'); //error
});
});
This is the HTML:
<div id="element-id">
<my-directive my-attr="1"></my-directive>
<my-directive my-attr="0"></my-directive>
<my-directive my-attr="0"></my-directive>
</div>
When I run this test I get the following error:
TypeError: undefined is not a function
I stripped it down and found out that the error is from the get() function and the count() function. I have read about the functions in the Protractor API and used them the same way as the example on the site, so I don't understand why it does not work for me.
Does anyone know what I'm doing wrong?
I have also tried this (included 'element'):
e.element.all(by.tagName('my-directive')).then(function(items){...})
But that gave an error event without the get() function.

items in this case is just an ordinary array. You get
TypeError: undefined is not a function
because there isn't any function on the Array.prototype called count.
count() and get() can only be called on ElementFinderArrays, which is a Protractor specific object: http://angular.github.io/protractor/#/api?view=ElementArrayFinder
If you want to get the length and one of the elements' attribute, this will work:
e.all(by.tagName('my-directive')).then(function(items){
expect(items.length).toEqual(3);
expect(items[0].getAttribute('my-attr')).toEqual('1');
});
or like this:
expect(e.all(by.tagName('my-directive')).count()).toEqual(3);
expect(e.all(by.tagName('my-directive')).get(0).getAttribute('my-attr')).toEqual(1);

Related

Are getter functions necessary for Protractor element locators

When using PageObjects for Protractor e2e tests, should you use getter functions for the element locator variables instead of having variables?
example:
public loginButton: ElementFinder = $('#login-submit');
public loginUsername: ElementFinder = $('#login-username');
Or should you use a getter function in the Page Object like this:
public get loginButton(): ElementFinder {
return $('#login-submit');
}
public get loginUsername(): ElementFinder {
return $('#login-username');
}
Is one approach better than another?
No getters needed, since protractor ElementFinder and ElementArrayFinder objects are lazy - no any searching for this element will be done until you will try to call some methods on them. Actually thats also a reason why you don't need to use await for protractor element search methods:
const button = $('button') // no await needed, no getter needed
console.log('Element is not yet tried to be searched on the page')
await button.click() // now we are sending 2 commands one by one - find element and second - do a click on found element.
http://www.protractortest.org/#/api?view=ElementFinder
ElementFinder can be used to build a chain of locators that is used to find an element. An ElementFinder does not actually attempt to find the element until an action is called, which means they can be set up in helper files before the page is available.
It's fine to use either but if you're going to transform or do something else to your element, then the getter function would be better in my opinion since that's the reason why we utilize mutators in the first place.
I'm not really sure which method is more convenient, if there is one.
I've been using protractor for a bit longer than 1 year now, and I always stored locators in variables.
What I'd normally do is:
const button = element(by.buttonText('Button'));
Then I'd create a function for interacting with the element:
const EC = protractor.ExpectedConditions;
const clickElement = async (element) => {
await browser.wait(EC.elementToBeClickable(element));
await element.click();
};
Finally, use it:
await clickElement(button);
Of course I store the locators and functions in a page object, and invoking/calling them in the spec file. It's been working great so far.

undefine is not a function jquery auto complete

When trying to handle the data returned from autocomplete result set this always happens.
Any clue on this issue?
$("#search").autocomplete(suggest_url,{
max:100,
delay:10,
selectFirst: false
}).result(function(event, data, formatted)
{
do_search(true);
});
Thanks
Such error happens only if you are trying to call a function, but it is not a function.
x = 123;
x(); // produces «number is not a function
y = undefined;
y(); // produces exactly «TypeError: undefined is not a function»
«Uncaught type error» indicates that exception caused inside the lambla-style function. Thus, I hope, it is something wrong with do_searh identifier. Try to alert(do_searh) before calling it.
>>> UPDATE
This questions refers to another:
jQuery UI Autocomplete .result is not a function woes

Reset angular form with $setPristine

Using $scope.form.$setPristine() returns undefined.
<html>
<form name="my_form">
...
</form></html>
Defining the controller on my $routeProvider
.when('page_name', {
templateUrl: '...',
controller: function($scope) {
console.log(my_form); // returns the form object
my_form.$setPristine(); returns Object #<HTMLFormElement> has no method '$setPristine'
console.log($scope.my_form); // returns undefined
$scope.my_form.$setPristine(); // returns Cannot call method '$setPristine' of undefined
}
}
I've also tried passing the form to the $scope via jQuery $scope.my_form = $('form'); which, as expected, just sent the form object and resulted in the first error. What does it take to get this method to work?
I tried putting a Plunker together to demonstrate but I can't seem to get routing to work on there properly.
Everything else about the form works btw. I would just like to know how to get $setPristine to work.
Put the form and the ng-controller at the same level...
<form name="my_form" ng-controller="my_controller">
That's working for me.
(sorry about my english) ;-)

AttributeError: 'Bottle' object has no attribute 'template'

Example One
Consider the following:
import bottle
import pymongo
application = bottle.Bottle()
#application.route('/')
def index():
cursor = [ mongodb query here ]
return application.template('page1',{'dbresult':cursor['content']})
Assume that the MongoDB query is correct, and the application is calling the content value of cursor correctly and passing it to the template which is formatted correctly.
The errors I am getting in the logs are to do with being able to use the template() method eg:
AttributeError: 'Bottle' object has no attribute 'template'
Example Two
If I change the corresponding assignment and call to:
application = bottle
application.template
The error is:
TypeError: 'module' object is not callable
Example Three
If I change the corresponding assignment and call to:
application = bottle
#application.route('/')
#application.view('page1.tpl')
return {'dbresult':cursor['content']}
The error is:
TypeError: 'module' object is not callable
Question
What is the correct call to the template() method to use to get Example One working?
To get "Example One" working:
return bottle.template('page1',{'dbresult':cursor['content']})
template() is in the bottle module; just reference it as bottle.template(...).
bottle.template() isn't a method of the bottle.Bottle() application object. It's a function in the bottle module.

Cannot access the parameter of a Menu.param from a Lift Snippet

I'm trying to extract the parameter from a Lift Menu.param within a snippet so that I can use it to create a named Comet. However, I get a NullPointerException when I try to pass the parameter to the snippet using SnippetDisptach in my Boot.scala, as suggested here:
http://comments.gmane.org/gmane.comp.web.lift/44299
I've created the Menu item as follows:
object AnItemPage {
// create a parameterized page
def menu = Menu.param[Item]("Item", "Item",
s => fetchItem(s), item => item._id.toString) / "item"
private def fetchItem(s:String) : Box[Item] = synchronized {
ItemDAO.findById(ObjectId.massageToObjectId(s))
}
}
I've added the menu to SiteMap. I've also created a Snippet which I would like to pick up the Item parameter. (I'm using fmpwizard's InsertNamedComet library here):
class AddCometItemPage(boxedItem: Box[Item]) extends InsertNamedComet with DispatchSnippet{
val item : Item = boxedItem.openOr(null)
override lazy val name= "comet_item_" + item._id.toString
override lazy val cometClass= "UserItemCometActor"
def dispatch = null
}
My next step is to crate an instance of this class as demonstrated by David Pollak here:
http://comments.gmane.org/gmane.comp.web.lift/44299
This is what I have added to my Boot.scala:
LiftRules.snippetDispatch.append {
case "item_page" => new AddCometItemPage(AnItemPage.menu.currentValue)
}
My item.html references this snippet:
<div class="lift:item_page">
I get the following null pointer exception when I compile and run this:
Exception occurred while processing /item/5114eb4044ae953cf863b786
Message: java.lang.NullPointerException
net.liftweb.sitemap.Loc$class.siteMap(Loc.scala:147)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.siteMap(Menu.scala:170)
net.liftweb.sitemap.Loc$class.allParams(Loc.scala:123)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.allParams(Menu.scala:170)
net.liftweb.sitemap.Loc$class.net$liftweb$sitemap$Loc$$staticValue(Loc.scala:87)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.net$liftweb$sitemap$Loc$$staticValue(Menu.scala:170)
net.liftweb.sitemap.Loc$$anonfun$paramValue$2.apply(Loc.scala:85)
net.liftweb.sitemap.Loc$$anonfun$paramValue$2.apply(Loc.scala:85)
net.liftweb.common.EmptyBox.or(Box.scala:646)
net.liftweb.sitemap.Loc$class.paramValue(Loc.scala:85)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.paramValue(Menu.scala:170)
net.liftweb.sitemap.Loc$$anonfun$currentValue$3.apply(Loc.scala:114)
net.liftweb.sitemap.Loc$$anonfun$currentValue$3.apply(Loc.scala:114)
net.liftweb.common.EmptyBox.or(Box.scala:646)
net.liftweb.sitemap.Loc$class.currentValue(Loc.scala:114)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.currentValue(Menu.scala:170)
bootstrap.liftweb.Boot$$anonfun$lift$8.apply(Boot.scala:107)
bootstrap.liftweb.Boot$$anonfun$lift$8.apply(Boot.scala:106)
net.liftweb.util.NamedPF$$anonfun$applyBox$1.apply(NamedPartialFunction.scala:97)
net.liftweb.util.NamedPF$$anonfun$applyBox$1.apply(NamedPartialFunction.scala:97)
net.liftweb.common.Full.map(Box.scala:553)
net.liftweb.util.NamedPF$.applyBox(NamedPartialFunction.scala:97)
net.liftweb.http.LiftRules.snippet(LiftRules.scala:711)
net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:1506)
net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:1506)
net.liftweb.common.EmptyBox.or(Box.scala:646)
net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$findSnippetInstance(LiftSession.scala:1505)
net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$88.apply(LiftSession.scala:1670)
net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$88.apply(LiftSession.scala:1669)
Has anybody any idea where I'm going wrong? I've not been able to find a lot of information on Menu.param.
Thank you very much for your help.
f
I have never tried what you are doing, so I am not sure the best way to accomplish it. The way you are using the Loc Param, you are extracting a variable from a URL pattern. In your case, http://server/item/ITEMID where ITEMID is the string representation of an Item, and which is the value that gets passed to the fetchItem function. The function call will not have a value if you just arbitrarily call it, and from what I can see you are requesting a value that is not initialized.
I would think there are two possible solutions. The first would be to use S.location instead of AnItemPage.menu.currentValue. It will return a Box[Loc[Any]] representing the Loc that is currently being accessed (with the parameters set). You can use that Loc to retrive currentValue and set your parameter.
The other option would be to instantiate the actor in your snippet. Something like this:
item.html
<div data-lift="AnItemPage">
<div id="mycomet"></div>
</div>
And then in your AnItemPage snippet, something like this:
class AnItemPage(item: Item) {
def render = "#mycomet" #> new AddCometItemPage(item).render
}
I haven't tested either of those, so they'll probably need some tweaking. Hopefully it will give you a general idea.