Protractor e2e test won't click on button in bootstrap popover - javascript

I have a problem with e2e testing a web application in Internet Explorer 9 with protractor (1.0.0-rc4). The top bar has a dropdown menu that is implemented
with a bootstrap popover and looks like this:
<div ng-class="{ in: isOpen(), fade: animation() }" class="popover bottom popover--default in" is-open="tt_isOpen" animation="tt_animation" placement="bottom" content="r6-operator-toolbar-popover" title="" r6-directive-popover-popup="" style="display: block; top: 29px; left: 1395.7px;">
<div class="arrow-cover"><div class="arrow"></div></div>
<h3 ng-show="title" ng-bind="title" class="popover-title ng-binding ng-hide"></h3>
<div r6-popover-content="" class="popover-content"><ul class="r6nav r6nav--popover" r6-operator-toolbar-popover="">
<li>
<ul r6-localization-languageselector="">
<!-- ngRepeat: language in languages --><li ng-class="language.key == languages[selected].key ? 'is-selected' : null" ng-repeat="language in languages" class="ng-scope">
<a ng-click="language.key == languages[selected].key ? null : loadLanguage(language.key)" href="" class="ng-binding">DE</a>
</li><!-- end ngRepeat: language in languages --><li ng-class="language.key == languages[selected].key ? 'is-selected' : null" ng-repeat="language in languages" class="ng-scope is-selected">
<a ng-click="language.key == languages[selected].key ? null : loadLanguage(language.key)" href="" class="ng-binding">EN</a>
</li><!-- end ngRepeat: language in languages -->
</ul>
</li>
<li>
<a ng-click="changePassword()" href=""><span class="r6icon-size1color3 r6icon-configure"></span>Change password</a>
</li>
<li>
<a ng-click="logout()" href=""><span class="r6icon-size1color3 r6icon-logout"></span>Logout</a>
</li>
</ul></div>
</div>
The code is the template that is loaded once the popover is shown. The idea is to click on the logout-link in order to log out the user. The way I have it in my test is as follows:
it('should logout user', function() {
userToolBarPage.btnToolbar.click();
var elementToFind = '//a[contains(text(), "Logout")]';
browser.wait(function() {
var isThere = ptor.isElementPresent(elementToFind);
expect(ptor.isElementPresent(elementToFind)).toBeTruthy();
ptor.findElement(protractor.By.xpath(elementToFind)).click();
return isThere;
}, 15000);
});
The userToolBarPage.btnToolbar just clicks on the menu to open the popover and display the HTML above. Afterwards it looks for the link and clicks it. This works in Firefox and Chrome, but I can not
get IE9 to click on the button. It opens the popover, but it never seems to find the button, no matter what I try.
I know the code is not very clean right now, but this is still a trial and error process for me and I can't get any results, no matter what I try. If anyone has a suggestion how I could do this, please feel free to share it.

Related

displaying alert message in angular when move to other tab

I'm fairly new to Angular and need to solve what seems to be a simple problem: show an alert or confirmation message on navigating between tabs in angular bootstrap. the issue is when moving to another tab, the tab will open first and then show an alert message if clicked on cancel it will back to the previous tab, what I want simply is to not leave the current tab until click on confirmation to leave.
<ul ngbNav #navWithIcons="ngbNav" [(activeId)]="activeTab" class="nav-tabs">
<li ngbNavItem="docs">
<a ngbNavLink (click)="navigateTab('docs')">
<span [data-feather]="'file-text'"></span>Documents</a>
<ng-template ngbNavContent>
<p>
any content
</p>
</ng-template>
</li>
<li ngbNavItem="external">
<a ngbNavLink (click)="navigateTab('external')">
<span [data-feather]="'chrome'"></span> External
Resource</a>
<ng-template ngbNavContent>
<p>
any external link
</p>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="navWithIcons" class="mt-2"></div>
TS:
navigateTab(navTab: string) {
if (navTab != this.currentTab) {
if (this.isInputUpdated) {//if there is an update on the current tab inputs then
this.confirmationMessage(true, this.currentTab);
this.isInputUpdated = false;
}
this.currentTab = navTab;
}
}
You can listen to navChange event on the ngbNav element and stop the event from propagating
<ul ngbNav #navWithIcons="ngbNav" [(activeId)]="activeTab" class="nav-tabs" (navChange)="navChanged($event)">
...
</ul>
navChanged(event) {
event.preventDefault()
}
Inside the confirmationMessage method, if clicked on confirm set active tab with the value of currentTab

Odd Angular/Bootstrap Dropdown Behavior

I've got an application requiring a series of dropdowns. The functionality requires me to be able to switch between normal dropdown behavior and multi-select behavior.
I have made slight modifications to the ui.boostrap.dropdown from the Angular Directives for Bootstrap (see Dropdown). Everything works well, except for a gray bar after clicking (looks like the :hover css stays active after clicking) when in Multiselect mode.
When I toggle off then back on, the highlight goes away, as if the hover event has somehow completed.
Process:
Open the dropdown
Click Multiselect
Move the mouse and Multiselect stays highlighted, as if the ":focus" tag is not removed.
Visually:
The mouse is over 345 in this image, Multiselect should not be highlighted.
Angular HTML for dropdown:
<div ng-controller="DropdownCompanyController as vm">
<div class="btn-group u-front_dropdown-wide" dropdown is-open="vm.isopen">
<button type="button" class="btn btn-default dropdown-toggle" dropdown-toggle>
{{ vm.selected }} <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" ng-click="vm.checkMultiSelect($event)">
<li ng-repeat="company in vm.companies"
ng-class="{ selected : company.selected }">
{{ company.name }}
</li>
<li class="divider"></li>
<li class="ng-scope" ng-class="{selected : vm.multi.select }">
<a href="#"
ng-click="vm.event.multiselect()"
ng-class="{ multi: vm.multi.select }">Multiselect</a>
<button
ng-hide="!vm.multi.select"
ng-class="{ multi_button: vm.multi.select }"
ng-click="vm.event.close_dropdown($event)">Close</button>
</li>
</ul>
</div>
</div>
Here's the event where the click on an element is handled:
vm.event = {};
vm.event.select = function(company) {
if (!vm.multi.select) {
clearCompanies(false);
company.selected = true;
vm.selected = company.name;
vm.isopen = false;
} else {
if (company.name !== vm.defaultCompany) {
company.selected = !company.selected;
vm.selected = vm.multi.title + countCompanies();
}
}
};
Link to Plunker.
I have had no luck tracking this down and my instinct is that the issue is in the CSS, but it's standard bootstrap CSS. Any assistance would be appreciated.
If you just dont want any item to have the highlight then in your own custom app.css file override the focus state with white:
.dropdown-menu > li > a:focus {
background-color: white;
}
Without doing a custom bootstrap build just add the hover following the focus to to keep the grey highlight:
.dropdown-menu > li > a:hover {
background-color: lightgray;
}

angular looping with scope variables in same controller

I have 2 scope variables like the following:
$scope.degrees =[{DegreeCategoryID:"1",DegreeCategory:"Accounting",DegreeCategoryType:"Applied Sciences"},
{DegreeCategoryID:"2",DegreeCategory:"Advanced Manufacturing/Mechatronics Technology",DegreeCategoryType:"Applied Sciences"},
{DegreeCategoryID:"3",DegreeCategory:"Air Conditioning and Refrigeration Technology",DegreeCategoryType:"Applied Sciences"},
{DegreeCategoryID:"4",DegreeCategory:"Auto Body Technology",DegreeCategoryType:"Applied Sciences"},
{DegreeCategoryID:"78",DegreeCategory:"Associate in Sciences",DegreeCategoryType:"Academic"},
{DegreeCategoryID:"79",DegreeCategory:"Associate of Arts in Teaching",DegreeCategoryType:"Academic"},
{DegreeCategoryID:"80",DegreeCategory:"Emphasis",DegreeCategoryType:"Academic"},
{DegreeCategoryID:"81",DegreeCategory:"Field of Study",DegreeCategoryType:"Academic"}];
$scope.degreecategories=[{DegreeID:"1",DegreeCategoryID:"1",Degree:"Accounting AAS ",DegreeTypeID:"2",BHC:"1",CVC:"1",EFC:"1",ECC:"1",MVC:"1",NLC:"1",RLC:"1",Description:""},
{DegreeID:"2",DegreeCategoryID:"1",Degree:"Accounting Assistant Certificate ",DegreeTypeID:"1",BHC:"1",CVC:"1",EFC:"1",ECC:"1",MVC:"1",NLC:"1",RLC:"1",Description:""},
{DegreeID:"3",DegreeCategoryID:"1",Degree:"Accounting Clerk Certificate ",DegreeTypeID:"1",BHC:"1",CVC:"1",EFC:"1",ECC:"1",MVC:"1",NLC:"1",RLC:"1",Description:""},
{DegreeID:"4",DegreeCategoryID:"1",Degree:"Advanced Technical Certificate in Professional Accountancy",DegreeTypeID:"1",BHC:"",CVC:"",EFC:"",ECC:"",MVC:"1",NLC:"",RLC:"",Description:""},
{DegreeID:"5",DegreeCategoryID:"2",Degree:"Advanced Manufacturing/Mechatronics Technology AAS ",DegreeTypeID:"2",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"6",DegreeCategoryID:"2",Degree:"Advanced Manufacturing/Mechatronics Technology Certificate ",DegreeTypeID:"1",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"1",NLC:"",RLC:"",Description:""},
{DegreeID:"7",DegreeCategoryID:"3",Degree:"Air Conditioning and Refrigeration Technology AAS ",DegreeTypeID:"2",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"8",DegreeCategoryID:"3",Degree:"Profit Center Manager Enhanced Skills Certificate ",DegreeTypeID:"1",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"9",DegreeCategoryID:"3",Degree:"Residential - Technician I Certificate ",DegreeTypeID:"1",BHC:"",CVC:"1",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"10",DegreeCategoryID:"3",Degree:"Residential - Technician III Level II Certificate ",DegreeTypeID:"1",BHC:"",CVC:"1",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"11",DegreeCategoryID:"3",Degree:"Residential AAS ",DegreeTypeID:"2",BHC:"",CVC:"1",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"12",DegreeCategoryID:"4",Degree:"Auto Body Metal Technician Certificate ",DegreeTypeID:"1",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""}];
Both my above variables are present in the same controller. I am trying to display data in such a way that, when i click a button named 'Academic', it displays all the DegreeCategoryType:"Academic" variables from $scope.degrees using a filter.(until here it works fine)
Now i wanted to display another list following the previous list based on the selection i make from within the list ie. when i click one selection from the above made list, i wanted to to display the details from my $scope.degreecategories such that the it matches and filters based on the DegreeCategoryID. How do i approach this issue? i already posted this question but the message i tried to convey was not proper.
MARKUP Masterlist
<div ng-show="display.academic" class="col-lg-4 col-md-4 col-sm-4">
<div class="panel panel-info list-group list-unstyled" data-spy="scroll" data-target="#panelcategory" data-offset="0" style="max-height:300px;overflow:auto;position:relative;">
<div class="panel-heading">
<h3 class="panel-title">Academic</h3>
</div>
<a href='#' ng-repeat="degree in degrees | filter:{DegreeCategoryType:'Academic'}" class="list-group-item">
<li ng-click="showAcademic(degree)" >{{degree.DegreeCategory}}</li>
</a>
</div>
</div>
Markup sublist
<div ng-show="display.academiccourse" class="col-lg-9 col-md-9 col-sm-9">
<div class="panel panel-info list-group list-unstyled" data-spy="scroll" data-target="#panelcategory" data-offset="0" style="max-height:300px;overflow:auto;position:relative;">
<div class="panel-heading">
<h3 class="panel-title">{{DegreeCategory}}</h3>
</div>
<a href='#' ng-repeat="degree in degreecategories | filter:{DegreeCategoryID:filterSub}" class="list-group-item">
<li ng-click="display.appliedsciencescourse" >{{degree.Degree}}</li>
</a>
</div>
</div>
JS
$scope.showAcademic = function(degree){
$scope.DegreeCategory = degree.DegreeCategory;
$scope.filterSub = degree.DegreeCategoryID;
$scope.display.academiccourse = true;
};
<a href='#' ng-repeat="degree in degrees | filter:{DegreeCategoryType:'Applied Sciences'}" class="list-group-item">
<li ng-click="display.appliedsciencescourse" >{{degree.DegreeCategory}}</li>
</a>
I cant see that your ng-click actually does anything. If your ng-click calls a function, applying the element clicked on as a parameter, then you can set $scope.selectedCategory = yourcategory, on your second list, you can filter by selectedCategory, that will exist in the scope.

Running click functions on every instance of listing instead of current

I have a listing of articles here, and I can't figure out how to execute the ng-click function calls on every new article inside the ng-repeat. Right now it works for existing articles, but when new articles are added dynamically (via AJAX), I need those to have the same functionality too.
For example: the ng-click function calls on the "+" sign to reveal social buttons seem to not work once new articles are inserted via AJAX (ie: delete articles, and let list be populated again with new elements)
Does AngularJS provide any tools to do that?
<div>
<div>
<input type="text" ng-model="search">
<span>{{filtered.length}} article(s)</span>
</div>
<div article-listing ng-repeat="article in filtered = (wikiArticles | filter:search)">
<!--Individual article begin-->
<span>
{{article.title}}
</span>
<div>
<a ng-click="articles.removeArticle($index)" title="Delete">
<span>✖</span>
</a>
<a ng-click="articles.toggleShare(article)">
<span class="plus-sign" title="Share">✖</span>
<div social-share ng-show="article.socialShare">
<div ng-click="socialShare = !socialShare" class="addthis_toolbox addthis_default_style addthis_32x32_style"
addthis:title="{{article.title}}" addthis:description="{{article.extract}}" addthis:url="{{article.url}}">
<a class="addthis_button_facebook"></a>
<a class="addthis_button_twitter"></a>
<a class="addthis_button_google_plusone_share"></a>
<a class="addthis_button_reddit"></a>
<a class="addthis_button_hackernews"></a>
</div>
</div>
</a>
</div>
<div>{{article.extract}}</div>
<!--Individual article end-->
</div>
</div>
Code for ng-click calls that don't seem to work for new article insertions
$scope.articles = (function() {
return {
shuffleArticles : function() {
$scope.wikiArticles.reverse();
},
removeArticle : function(index) {
$scope.wikiArticles.splice(index, 1);
$scope.fireAPICalls();
},
toggleShare : function(currArticle) {
var previousState = currArticle.socialShare;
angular.forEach($scope.wikiArticles, function(article) {
article.socialShare = false;
});
currArticle.socialShare = previousState ? false : true;
}
}
})();
Your ng-click calls are actually working- you can watch the ng-show toggle in the debugger.
The problem is that there is nothing to display on the new items you add.
The articles you initially add all have their icons populated with the .addthis classes, for instance here's your Facebook icon element:
<a class="addthis_button_facebook at300b" title="Facebook" href="#">
<span class=" at300bs at15nc at15t_facebook">
<span class="at_a11y">Share on facebook</span>
</span>
</a>
at300bs includes the following css which displays the image:
background: url(widget058_32x32.gif) no-repeat left!important;
However as you add new items, you aren't including the needed .addthis classes to them. Their elements look like this:
<a class="addthis_button_facebook"></a>
So ng-show has nothing to display (it shows a 0x0 div).
Add the .addthis classes to your new elements as you add them and you'll be all set.

Isolate specific HTML elements with jQuery

OK, what I need may sounds rather complex, but here it is...
Let's say we have the HTML code below (it's still just an example, but it's still quite accurate) :
<div data-role="content" comp-id="jqm-content-6207" id="jqm-content-6207" class="" data-theme="" >
<!-- New Navigation Bar #1 -->
<div data-role="navbar" data-position="fixed" comp-id="jqm-navbar-4603" id="jqm-navbar-4603" class="" data-iconpos="top" >
<ul>
<!-- New Navigation Bar Item #1 -->
<li>
<a href="#" comp-id="jqm-navbar-item-6671" id="jqm-navbar-item-6671" class="" data-icon="home" data-theme="" >
One
</a>
</li>
<!-- / New Navigation Bar Item #1 -->
<!-- New Navigation Bar Item #2 -->
<li>
<a href="#" comp-id="jqm-navbar-item-4404" id="jqm-navbar-item-4404" class="" data-icon="gear" data-theme="" >
Two
</a>
</li>
<!-- / New Navigation Bar Item #2 -->
</ul>
</div>
<!-- / New Navigation Bar #1 -->
<!-- New Navigation Bar #2 -->
<div data-role="navbar" data-position="fixed" comp-id="jqm-navbar-4658" id="jqm-navbar-4658" class="" data-iconpos="top" >
<ul>
<!-- New Navigation Bar Item #2.1 -->
<li>
<a href="#" comp-id="jqm-navbar-item-5321" id="jqm-navbar-item-5321" class="" data-icon="home" data-theme="" >
One
</a>
</li>
<!-- / New Navigation Bar Item #2.1 -->
<!-- New Navigation Bar Item #2.2 -->
<li>
<a href="#" comp-id="jqm-navbar-item-2843" id="jqm-navbar-item-2843" class="" data-icon="gear" data-theme="" >
Two
</a>
</li>
<!-- / New Navigation Bar Item #2.2 -->
</ul>
</div>
</div>
First-off, the core idea is : when the user clicks an item with the comp-id attribute set, then add class msp-selected just to this specific element (and remove it from all other elements).
This is how I'm handling this specific part :
function removeAll()
{
$("*").each(function() {
if ($(this)!==undefined) {
$(this).removeClass("msp-selected");
}
});
}
$(document).ready( function() {
$('[comp-id]').bind('click', function(event) {
removeAll();
$(event.target).addClass('msp-selected');
});
});
So, as you may already have guessed it's like a way of "selecting" item (by clicking on them) from the HTML document.
Now, here's the catch :
How could I make it so that the "selection" is progressive?
What I mean...
When the user first clicks on the Navigation Bar :
Check if the first div with comp-id is selected (has the class msp-selected). If not, select it.
If the first div is already selected, then go one level deeper looking for comp-id, and select that one.
So, any ideas?
How would you do it?
P.S. When one clicks on the <a> of a navigation item, what specific item receives the event?
Is it the <div data-role=\"navbar\"> or the navigation bar item? No matter what, from all these items, I want to select the outermost - not being currently selected. Next time, when the user clicks again and e.g. the navigation bar is selected, then unselect it and select it's child (go deeper).
EDIT :
When trying :
$(document).ready( function() {
$('[comp-id]:not(.msp-selected)').on('click', function(e) {
removeAll();
$(this).addClass('msp-selected');
});
});
What I'm getting when clicking on navbar-item is :
Selected Div : jqm-navbar-item-8421
Selected Div : jqm-navbar-8598
Selected Div : jqm-content-2860
Selected Div : jqm-page-3363
So, basically it just "selects" the outermost container. Which is wrong... Next time the user clicks, the content should selected - then the navbar and then the navbar-item....
You may write a function like that (i am not sure if the syntax is correct)
function onclick(sender)
{
if(type of sender == null )
{
return;
}
if(sender.className=="selected")
{
onclick(sender.childElement[0]);
// OR If you need all children to be selected,
// for( var i =0; i<sender.childElement.count; i++)
// onclick(sender.childElement[i]);
}
else
{
sender.className="selected";
}
}

Categories

Resources