Protractor having problems pressing a hidden radio button - angularjs

I am having issues pressing a hidden radio button on my page using protractor. Below you will find a single test where the flow should work as following.
Page is navigated too, and make sure that the radio button exists. (Two ways to verify existence below, both work)
Attempt to click the button in a variety of different ways. All of the commented out ways, as well as the real one below do not error out the test, but they do also not "Click" the radio button. I am able to confirm this because of the 3 expects at the bottom that look to see if the form that shows up when the button is clicked actually shows up, and those are turning false every single time.
Any help with this would be greatly appreciated, Below I've also put the sample html that this code is looking at. Any help would be great, not sure if it is even possible. Thank you for any help in advance
it('Should press one of the radio buttons and have the form pop up', function() {
// Make sure that the value equals bank is found (This passing its test)
expect(element.all(by.model('bankConnection.bank')).get(0).getAttribute('ng-value')).toEqual('bank');
// Another way to make sure that the element is found (This is passing the test)
// expect(element.all(by.css('[ng-value="bank"]')).get(0).getAttribute('ng-value')).toEqual('bank');
// browser.driver.executeScript("return arguments[0].click();", element.all(by.css('[ng-value="bank"]')).get(0).getAttribute('ng-value').getWebElement());
// browser.driver.executeScript("return arguments[0].click();", element.all(by.model('bankConnection.bank')).get(0).getAttribute('ng-value').getWebElement());
// #1 Way THIS WAY WORKS BUT DOESNT PRESS ANYTHING
// var input = element.all(by.model('bankConnection.bank')).get(0);
// browser.driver.executeScript('angular.element(arguments[0]).triggerHandler("touchstart");', input.getWebElement());
// #2 Way THIS WAY WORKS BUT DOESNT PRESS ANYTHING
var input = element.all(by.model('bankConnection.bank')).get(0).getAttribute('ng-value');
browser.driver.executeScript('angular.element(arguments[0]).triggerHandler("touchstart");', input.getWebElement());
// To verify button was pressed. 2 seconds
browser.driver.sleep(2000);
// Make sure that the form pops up (IT IS CURRENTLY NOT SHOWING UP)
expect(element(by.model('bankConnect.username')).isPresent()).toBe(true);
expect(element(by.model('bankConnect.password')).isPresent()).toBe(true);
// Once click is figured out this should flow through properly BOA CLICK
expect(bank_page.idText).toEqual('Online ID');
});
Radio Button Element
<div class="col" ng-repeat="bank in firstBanks">
<div style="font-size: 2em; ">
<label class="bank_radio">
<input type="radio" ng-model="bankConnection.bank" ng-value="bank" class="ng-valid ng-dirty" value="[object Object]">
<img ng-src="img/banks/bofa.png" src="img/banks/bofa.png">
</label>
</div>
</div>
Form that pops up element
<div class="list card" style="margin-bottom: 0;margin-top:0;" ng-show="bankConnection.bank != null ">
<div class-="list">
<label class="item item-input">
<span class="input-label ng-binding">Online ID</span>
<input type="text" ng-model="bankConnection.username" class="ng-pristine ng-valid">
</label>
<label class="item item-input">
<span class="input-label ng-binding">Password</span>
<input type="password" ng-model="bankConnection.password" class="ng-pristine ng-valid" autocomplete="off" style="cursor: auto; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QsPDhss3LcOZQAAAU5JREFUOMvdkzFLA0EQhd/bO7iIYmklaCUopLAQA6KNaawt9BeIgnUwLHPJRchfEBR7CyGWgiDY2SlIQBT/gDaCoGDudiy8SLwkBiwz1c7y+GZ25i0wnFEqlSZFZKGdi8iiiOR7aU32QkR2c7ncPcljAARAkgckb8IwrGf1fg/oJ8lRAHkR2VDVmOQ8AKjqY1bMHgCGYXhFchnAg6omJGcBXEZRtNoXYK2dMsaMt1qtD9/3p40x5yS9tHICYF1Vn0mOxXH8Uq/Xb389wff9PQDbQRB0t/QNOiPZ1h4B2MoO0fxnYz8dOOcOVbWhqq8kJzzPa3RAXZIkawCenHMjJN/+GiIqlcoFgKKq3pEMAMwAuCa5VK1W3SAfbAIopum+cy5KzwXn3M5AI6XVYlVt1mq1U8/zTlS1CeC9j2+6o1wuz1lrVzpWXLDWTg3pz/0CQnd2Jos49xUAAAAASUVORK5CYII=); background-attachment: scroll; background-position: 100% 50%; background-repeat: no-repeat;">
</label>
</div>
</div>

Here is what was able to fix my problem in the end. Courtesy of: How to click on hidden element in protractor?
I added this block to my code to hover over the area of the image, and then issue a click command.
// Move mouse over the button
browser.driver.actions().mouseMove(element(by.css('[ng-src="img/banks/bofa.png"]'))).perform();
element.all(by.css('[ng-src="img/banks/bofa.png"]')).then(function (elm) {
elm[0].click();
});
Thank you for the help!

Related

How do i click on a particular image during runtime?

I am working with filling up form where fields can be checkbox/radio button/textbox/datepicker/timepicker etc.
I am facing an issue with clicking on 'TimePicker' basically one clock icon is given on right hand side, when i am clicking on it, one popup displays from which i do have to pick the time.
Please refer image. https://i.stack.imgur.com/MUOXz.jpg There is no locator with help of which i can click on 'clock' icon.
Here is html DOM.
<ac-input _ngcontent-brk-c387="" inputtype="time" _nghost-brk-c374="" class="visible ng-untouched ng-pristine ng-invalid ng-star-inserted" xpath="1">
<div _ngcontent-brk-c374="" class="col-sm-12 col-md ng-star-inserted">
<div _ngcontent-brk-c374="" class="form-group">
<ac-label _ngcontent-brk-c374="" _nghost-brk-c371="">
<label _ngcontent-brk-c371="" aria-hidden="true" class="ql-editor required ng-star-inserted" for="<p>
<p>
2. Time:
</p>
</label>
</ac-label>
<div _ngcontent-brk-c374="">
<input _ngcontent-brk-c374="" class="form-control ng-star-inserted" id="<p></p>" type="time">
</div>
<ac-hint _ngcontent-brk-c374="" _nghost-brk-c372="">
</ac-hint>
<ac-validation-messages _ngcontent-brk-c374="" role="alert" aria-atomic="true" _nghost-brk-c348="" style="">
</ac-validation-messages>
</div>
</div>
</ac-input>
I have captured 'Clock' icon with the help of snipping tool from the application and pasted on desktop as well under my application under the 'Screenshot' folder.
But click event is not happening from application at run time but its clicking the 'Clock' icon from desktop. And console output for it is "[log] DOUBLE CLICK on L[410,442]#S(0) (69 msec)".
Here is what i tried...
else if(answerType.equals("Time"))
{
WebElement timeText = answers.get(ans) .findElement(By.tagName("label"));
System.out.println(timeText.getText());
Screen screen = new Screen();
Pattern image1 = new Pattern("C:\\Selenium\\workspace\\C_Care\\Screenshots\\Clock.PNG");
Pattern image2 = new Pattern("C:\\Selenium\\workspace\\C_Care\\Screenshots\\Twelve.png");
screen.wait(image1, 10);
for(int sc=0; sc<6; sc++)
{
screen.mouseMove(image1);
screen.doubleClick(image1);
break;
}
screen.wait(image2,10);
screen.click(image2);
}
I a working with TestNg framework and used maven dependency for Sikuli is 2.0.4.
Any help will be appreciated.

Protractor: How to test an element built with ngTagsInput?

I currently has a simple form that I am trying to test with Protractor. While it seems to work fine with basic input types, it does not seem to work with ngTagsInput the way I have it set up. I was wondering if there was a particular way of setting this up without triggering the error below.
Failed: unknown error: cannot focus element
(Session info: ...)
(Driver info: ...)
...
Currently my form, has 4 elements. A name (standard input), a type (radio buttons), targets (the tag inputs), and a submit button. In HTML, it appears something like this.
<div class="form-group">
<input class="form-control" placeholder="Enter name here..." ng-model="name">
</div>
<div class="form-group">
<div id="t1" class="radio">
<input name="radioType" id="a" value="A" checked="" type="radio" ng-model="type">
</div>
<div id="t2" class="radio">
<input name="radioType" id="b" value="B" type="radio" ng-model="type">
</div>
<div id="t3" class="radio">
<input name="radioType" id="c" value="C" type="radio" ng-model="type">
</div>
</div>
<div class="form-group">
<tags-input class="btags" name="targets" min-length=1 placeholder="Enter your targets here..." min-tags=1 add-on-blur="true" ng-model="targets">
</div>
<div class="form-group">
<button id="submit" type="button" class="btn btn-primary" ng-click="submitThing()"></button>
</div>
Lastly, the one Protractor test I have written looks like this.
it('should submit a valid thing',function(){
//Sets a name for the object
element(by.model('name')).sendKeys('user');
//Sets a type for the object
element(by.id('t1')).click();
/*Inputting tags (the functions below) seem to not work and throw an error*/
//Clicks (or focuses on) the tag input box
element(by.model('targets')).click();
//Types in the elements within it
element(by.model('targets')).sendKeys('target1');
//Presses Enter to submit that particular target
browser.actions().sendKeys(protractor.Key.ENTER).perform();
//Repeat for more
element(by.model('targets')).sendKeys('target2');
browser.actions().sendKeys(protractor.Key.ENTER).perform();
element(by.model('targets')).sendKeys('target3');
browser.actions().sendKeys(protractor.Key.ENTER).perform();
element(by.id('submit')).click();
}
The managed to find a solution thanks to MBielski's comment. It turns out that you need to look at the HTML that is rendered and focus on one of those elements since it is a custom element. Using Google Chrome's developer tools, I managed to find some of the inner code for the make up of the tags. In short, it appears as:
<input class="input" ng-model="newTag.text">
There is much more information in this inner element, but I left what was relevant. So, you add information into the tags inbox I've defined in the question asked, you would simply focus on the model called "newTag.text", like this.
it('should submit a valid thing',function(){
//Sets a name for the object
element(by.model('name')).sendKeys('user');
//Sets a type for the object
element(by.id('t1')).click();
//Clicks (or focuses on) the tag input box // This may not be needed
element(by.model('newTag.text')).click();
//Types in the elements within it
element(by.model('newTag.text')).sendKeys('target1');
//Presses Enter to submit that particular target
browser.actions().sendKeys(protractor.Key.ENTER).perform();
//Repeat for more
element(by.model('newTag.text')).sendKeys('target2');
browser.actions().sendKeys(protractor.Key.ENTER).perform();
element(by.model('newTag.text')).sendKeys('target3');
browser.actions().sendKeys(protractor.Key.ENTER).perform();
element(by.id('submit')).click();
}
This solved the problem for me. Hopefully it also does for others.

Making the Bootstrap navbar searchbox work

I am trying to make a search function which works if I put in the query params into my URL directly but I don't know how to make it work so that it picks it up from the search box and executes it. I have used ng-model to map the text itself to the controller which works but the execution isn't working.
The navbar form:
<form ng-submit="doSearch()" class="navbar-form">
<div class="form-group" style="display:inline;">
<div class="col-md-offset-4 input-group" style="display:table;">
<input ng-model="search.text" class="form-control" name="search" placeholder="Search Here" autocomplete="off" autofocus="autofocus" type="text">
<span class="input-group-addon" style="width:1%;">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
</div>
By the way, my doSearch() function works just fine when I run it manually and so is the search itself. I have also validated that search.text comes through. I guess what I am asking is how do I make the icon (glyphicon-search) execute ng-submit="doSearch()" when the user clicks on it or presses enter.
Sorry if this is very obvious. I was always more on the backend side of things so am sorta new to HTML and Angular.
Thanks
You could place the icon inside a <button> element instead of <span>, tweak a bit of css to integrate it to the form field.
In regards to trigger search on enter, with jQuery something like this could be used:
$('input').keypress(function (e) {
var key = e.which;
if(key == 13) // the enter key code
{
doSearch();
}
});
did you try using <button type="submit"> before your search icon
<span class="glyphicon glyphicon-search"></span>
to specify that clicking on that button is equivalent to a submit event for that form.
So this worked in the end. First, the proper HTML which works:
<form ng-submit="doSearch()" class="navbar-form">
<div class="form-group" style="display:inline;">
<div class="col-md-offset-4 input-group" style="display:table;">
<input ng-model="search.text" class="form-control" name="search" placeholder="Search Here" autocomplete="off" autofocus="autofocus" type="text">
<span ng-click="doSearch()" class="input-group-addon" style="width:1%;">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
</div>
</form>
Furthermore, there was an issue with the view not connecting to the controller. Actually, let me rephrase that - it was connecting to the controller but only when the whole page loaded and for my test, I had a console.log('I have loaded') put in there. So when I saw "I have loaded", I thought my controller was invoked properly.
However, the doSearch() was in the controller which was connecting via angular routing, so the ng-View was not connecting to the right controller.
I am not sure if this means anything to anyone but I am writing this in case someone else comes across an issue like mine.
So just to summarise the issue was not with the HTML as I originally thought. ng-submit (for form submission when pressing enter) and ng-click (for clicking the glyphicon) does the trick.

Ionic ng-click calls same Modal in <input type='button'>

<label class="item item-input">
<span class="input-label" id="depTime">Time</span>
<input type="button" value="{{query.depTime}}" ng-click="openModal(2)" class="button"></input>
<input type="button" value="{{query.depDate}}" ng-click="openModal(1)" class="button"></input>
</label>
openModal function
$scope.openModal = function(index) {
console.log("openModal" + index);
if (index == 1) {
$scope.dateModal.show();
} else {
$scope.timeModal.show();
}
};
http://codepen.io/anon/pen/wGMQJQ
how does the problem cause?
or I should just use /a class='button'/
thanks for replying
This error comes because when you call openModal it always get the value of index=2 it will be better if you use different function for each button then it will work
Short answer:
The problem is that you nest two input controls inside the label.
Just remove or replace label around inputs and everything will start working fine
<body ng-controller="myCtrl">
<span class="input-label" id="depTime">Time</span>
<input type="button" value="{{query.depTime}}" ng-click="openModal(2)" class="button button-outline button-calm"></input>
<input type="button" value="{{query.depDate}}" ng-click="openModal(1)" class="button button-outline button-calm"></input>
See http://codepen.io/ryltsov/pen/aNaxja
Note that i also fixed couple minor bugs (changed modal template dateModal to modal-1 and also updated this modal template to have number 1)
Detailed answer:
http://www.w3.org/TR/html-markup/label.html says:
The label element may contain at most one descendant input element,
button element, select element, or textarea element.
Label elements increase the hit area of the related input. If you have two inputs, when you click on either or on the label text the click is handled by the first input. That's why you always get 2 in the click handler.

ng-repeat radio button 2-way binding issue, only last item set correctly

I am using angularjs to repeat radio button groups with the following code.
<div class="row observation-point"
ng-repeat="observationPoint in question.observationPointList">
<div class="col-md-6 col-sm-6">
<small>{{observationPoint.text}}</small>
</div>
<div class="col-md-4 col-sm-4 col-md-offset-2 col-sm-offset-2">
<label class="radio-inline">
<input type="radio" ng-disabled="observation.status != 'Open'"
name="{{domain.id}}-{{question.id}}-{{observationPoint.id}}"
id="{{domain.id}}-{{question.id}}-{{observationPoint.id}}-1" ng-value="true"
ng-model="observationPoint.observed">{{'observation-domain.html.yes' | translate}} {{observationPoint.observed}}
</label>
<label class="radio-inline">
<input type="radio" ng-disabled="observation.status != 'Open'"
name="{{domain.id}}-{{question.id}}-{{observationPoint.id}}"
id="{{domain.id}}-{{question.id}}-{{observationPoint.id}}-0" ng-value="false"
ng-model="observationPoint.observer">{{'observation-domain.html.no' | translate}}
</label>
</div>
</div>
With angular 1.2.28 this worked fine, however we've recently upgraded to 1.4.2 and now the result is as in the picture below.
The model values are correctly saved and restored (see the true and false values in the image) in the variables, but only the last radio button in the ng-repeat is selected after reloading the page.
Why is this happening, because I really don't understand what the problem is and how to fix this.
nb. observationPoint.observer contains a boolean value not a string
EDIT: i've created a simplified plunker and of course this works as intended :S
http://plnkr.co/edit/tWjizHB8I5FNZVOgdq6J?p=preview
Which would suggest something is wrong with the naming or id's.
However when I check with the developer tools id and name seem fine
I've found a solution, if I change the dynamic names from
name="{{domain.id}}-{{question.id}}-{{observationPoint.id}}"
to
name="observationPoint_{{observationPoint.id}}"
it works without a hitch. I presume there is some sort of loading/timing issue going on. The variables are probably not unique at the moment the UI is rendered and causes only the last item to be set.

Resources