We have some textboxes where the value needs to be selected from a popup list. The elements and the popup are like this:
The related html codes are as follows:
<div _ngcontent-c6="" class="col px-0">
<input _ngcontent-c6="" aria-multiline="false" autocapitalize="off"
autocorrect="off" class="form-control ng-dirty ng-valid open ng-touched"
formcontrolname="ESYSITENAME" id="esySiteName" name="" placeholder=""
role="combobox" type="text" autocomplete="off" aria-autocomplete="list"
aria-expanded="true" aria-activedescendant="ngb-typeahead-2-0"
aria-owns="ngb-typeahead-2">
<ngb-typeahead-window class="dropdown-menu show ng-star-inserted"
role="listbox" id="ngb-typeahead-2" style="top: 39px; left: 0px;">
<button class="dropdown-item ng-star-inserted active" role="option"
type="button" id="ngb-typeahead-2-0">
<ngb-highlight _ngcontent-c6="" _nghost-c25="" class="ng-star-inserted">
<span _ngcontent-c25="" class="ngb-highlight ng-star-inserted">
Bull Run Elementary School
</span>
</ngb-highlight>
</button>
</ngb-typeahead-window>
</div>
I have tried to select the Popup element using different strategies like:
let EsyNamePopup = $('#ngb-typeahead-2-0 > ngb-highlight > span');
await helpers.waitForElementVisibility(EsyNamePopup);
await helpers.clickWhenClickable(EsyNamePopup);
// or following way:
let EsyNamePopup = element(by.cssContainingText('span', 'Bull Run Elementary School,));
await EsyNamePopup.click();
None of them worked but got following error messages:
NoSuchElementError: No element found using locator: By(css selector, #ngb-typeahead-2-0 > ngb-highlight > span)
Is there a better strategy to select these elements?
I think you can try a long sleep before click on the pop option. If long sleep can fix your issue, it proves your wait function waitForElementVisibility has issue or you not give sufficient wait time.
await $('input#esySiteName').sendKeys('Bull');
await browser.sleep(15000)
await $('#ngb-typeahead-2-0 > ngb-highlight > span').click()
You could set up breakpoints and debug your code by following the steps in here.
http://www.protractortest.org/#/debugging
Might want to verify if sendkeys will initiate the typeahead popup or if element needs to be focused in order for that.
Related
I have a div function which has a radio button which I would like to select 'fire' using Pyppeteer. However, when I try to do this, all attempts I try fail
Div
<div _ngcontent-xqm-c396="" class="ng-star-inserted">
<p-radiobutton _ngcontent-xqm-c396="" styleclass="radio-group__input" name="APPLICANT_TYPE" class="ng-untouched ng-valid ng-dirty">
<div class="radio-group__input ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input type="radio" name="APPLICANT_TYPE" value="Corporate">
</div>
<div role="radio" aria-checked="true" class="ui-radiobutton-box ui-widget ui-state-default ui-state-active">
<span class="ui-radiobutton-icon ui-clickable pi pi-circle-on">
</span>
</div>
</div>
<label class="ng-star-inserted ui-radiobutton-label ui-label-active">Corporate</label>
<!---->
</p-radiobutton><validationmsg _ngcontent-xqm-c396="" _nghost-xqm-c395="" hidden="">
<!---->
</validationmsg>
</div>
The pyppeteer command I use
await page.click("input[name='APPLICANT_TYPE']")
This is the XPATH:
//*[#id="lead_request_main_ui_applicant_type"]/div[2]/p-radiobutton/div/div[1]/input
This is the JS PATH
document.querySelector("#lead_request_main_ui_applicant_type > div:nth-child(3) > p-radiobutton > div > div.ui-helper-hidden-accessible > input[type=radio]")
If either of those help you? I've been trying this for the past 2 days and I have had no success :-(
In the end this looks like a bug with Pyppeteer
To get around it, I had to do this workaround which now works:
foo = await page.querySelector('[value="Corporate"]') # or any proper selector
await page.evaluate('(element) => element.click()', foo)
Will probably save you about 4 days of effort!
I would like to be able to dynamically update a quantity field when I click on a '+' (Plus Button) However, depending where I click on the button, I am getting a different result for the parent element.
The HTML that is in use to call the function is below. This is HTML from my frontend developer and I am trying to connect a few things to make this work.
<div id="item-list" class="product_list_container">
<div class="bluedog-flex-container noPaddingLeftRgt payhub-well col-xs-12 col-sm-12 col-lg-12" data-id="32" style="margin-top:0;">
<div class="subtotal-div col-xs-12 col-sm-12 col-lg-12">
<div class="bluedog-inner-flex-container product_info_container col-xs-12 col-sm-12 col-lg-12">
<div class="order-overview-left noPaddingLeft alignLeft col-xs-4 col-sm-4 col-lg-4">Macbook Pro # 50.00</div>
<div class="quantity_range_div col-xs-6 col-sm-6 col-lg-6">
<div class="value-button createPage_decrease_qty decrease_value_btn" style="display:inline;" onclick="decreaseQty(event)"><i class="far fa-minus"></i></div>
<input type="number" class="itm_qty" id="number" value="1">
<div class="value-button increase_value_btn" style="display:inline;" onclick="increaseQty(event)"><i class="far fa-plus"></i></div>
</div>
<input type="hidden" name="item_price" data-qty="1" data-prod-name="Macbook Pro" data-id="32" data-tax="0" value="50.00"><a class="popup-close-btn order-overview-right close_btn_plans col-xs-2 col-sm-2 col-lg-2" onclick="removeItem(event)"> <i class="far fa-times-circle hosted_small_delete"></i></a>
</div>
</div>
</div>
</div>
What I am trying to achieve is, when I click on the Plus Button, (Screenshot attached) https://prnt.sc/oq770q the value will increase.
Originally, I was just using the following code to try and get the parent DIV id, which in this case is item-list
var master = $(e.target).parents().eq(5).attr('id'); // Name of item-list container
However, was receiving unexpected results, whereby if I tapped on the outside of the plus button, the surround grey area, it would not increase, but only if I tapped directly on the plus icon itself.
I noticed it was picking up a different element and the eq(5) was returning an undefined value. As you will see in in the script below, I have put in an if statement for a class check to see which part of the button has been pressed and this returns the expected results.
However, I dont' see this as scalable and transferable if someone was to change the FontAwesome Tag, as the class would likely be different.
function increaseQty(e) {
var clicked = e.path[0];
if ($(clicked).hasClass('fa-plus')) {
var master = $(e.target).parents().eq(5).attr('id'); // Name of item-list container
} else {
var master = $(e.target).parents().eq(4).attr('id'); // Name of item-list container
}
var input = $(e.target).parent().parent().find('input.itm_qty');
var qty = $(input).val();
var newQty = parseInt(qty) + 1;
$(input).val(newQty);
updatePrices(master);
}
I would like to know how, if possible, that regardless where on the container that is being clicked, the plus icon or the gray area around it, to increase the value, without having to do a dirty class check.
Many thanks,
David.
Based on you html code I am seeing like
<input type="number" class="itm_qty" id="number" value="1">
In this line you have id number so you can easily update.Based on your description your above line repeat. So you modify your increaseQty like that.
function increaseQty(e) {
var input = $(e.target).prev('input.itm_qty');
var qty = $(input).val();
var newQty = parseInt(qty) + 1;
$(input).val(newQty);
updatePrices(master);
}
If you see in your code increaseQty bind with div element and input itm_qty is sibling of div. So I am hoping above code works.
So to answer my own question, with some help from #Dhiren (Thank You)
I found out that I could assign FontAwesome Icon to the class of a SPAN. Therefore I have changed the Divs which contained the FontAwesome Icons to Spans, and assigned the FA Icon class to the span, removing the element.
<div class="quantity_range_div col-xs-6 col-sm-6 col-lg-6">
<span class="value-button createPage_decrease_qty decrease_value_btn far fa-minus" style="display:inline;" onclick="decreaseQty(event)"></span>
<input type="number" class="itm_qty" id="number" value="1">
<span class="value-button increase_value_btn far fa-plus" style="display:inline;" onclick="increaseQty(event)"></span>
</div>
In doing so I was able to use a single parents().eq(4) line of code, as the target will now always be a span, and not a Div element or an element.
function increaseQty(e) {
var master = $(e.target).parents().eq(4).attr('id');
var input = $(e.target).prev('input.itm_qty');
var qty = $(input).val();
var newQty = parseInt(qty) + 1;
$(input).val(newQty);
updatePrices(master);
}
Dhiren, thank you for the prev() suggestion as it has helped me better refactor not only this function, but more also! I appreciate the help and support.
David
Update:
I added this:
$("#id_project").select2({dropdownParent: $(".modal-body")});
...and this causes the dropdown to be correctly placed, and the search can be typed into. Unfortunately...this causes the data delivered to be cleared out, and no options are available to be selected.
I have a form that is populated in a Bootstrap modal that looks like this:
<form method="post" action="/dataanalytics/sparc/tasks/create/" class="js-task-create-form">
<input type="hidden" name="csrfmiddlewaretoken" value="W6cnRq9zPDvUdQOpqceXPVulbWJAMFazRStzwnZhLi8UEqa87SYiRKmMoHAKwmvb">
<div class="modal-body">
<div class="form-group">
<select name="project" data-minimum-input-length="2" class="form-control select2-hidden-accessible" required="" id="id_project" data-autocomplete-light-url="/dataanalytics/projectautocomplete/" data-autocomplete-light-function="select2" tabindex="-1" aria-hidden="true">
<option value="" selected="">---------</option>
</select>
<span class="select2 select2-container select2-container--bootstrap select2-container--focus" dir="ltr" style="width: 505.091px;">
<span class="selection"><span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-labelledby="select2-id_project-container">
<span class="select2-selection__rendered" id="select2-id_project-container">
<span class="select2-selection__placeholder">
</span>
</span>
<span class="select2-selection__arrow" role="presentation"><b role="presentation"></b></span></span></span><span class="dropdown-wrapper" aria-hidden="true">
</span>
</span>
</div>
<div class="form-group">
<select name="dataSources" data-minimum-input-length="2" class="form-control select2-hidden-accessible" id="id_dataSources" data-autocomplete-light-url="/dataanalytics/datasourceautocomplete/" data-autocomplete-light-function="select2" multiple="" tabindex="-1" aria-hidden="true">
</select>
<span class="select2 select2-container select2-container--bootstrap" dir="ltr" style="width: 505.091px;">
<span class="selection"><span class="select2-selection select2-selection--multiple" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="-1">
<ul class="select2-selection__rendered">
<li class="select2-search select2-search--inline">
<input class="select2-search__field" type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="none" spellcheck="false" role="textbox" aria-autocomplete="list" placeholder="" style="width: 0.75em;">
</li>
</ul>
</span>
</span>
<span class="dropdown-wrapper" aria-hidden="true">
</span>
</span>
</div>
</div>
</form>
</div>
</div>
The first form group with the select2 single exhibits the problematic behavior. The second form group with the select2 multiple works as expected. Why is there a disparity here?
JavaScript:
var loadForm = function () {
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-task").modal("show");
},
success: function (data) {
$("#modal-task .modal-content").html(data.html_form);
}
});
};
Versions:
jQuery: 1.12.1
Select2: 4.0.5
Bootstrap: 4
Everything works great in Chrome. In Firefox, the Select2 boxes in the modal don't allow typing in the search inputs. This is a known issue (https://select2.org/troubleshooting/common-problems) but none of the known solutions appear to work for me.
To solve this issue, I added this code to set the dropdownParent of each Select2:
$.fn.select2.defaults.set("dropdownParent", $('#modal-task'));
This allows typing in the search inputs. However, my modal is long enough that it requires scrolling. If the modal is scrolled beyond the original position, clicking on a Select2 box causes the choices and the search input to appear above the box at the top of the modal. This makes sense, because all of the Select2 boxes were tied to the modal itself with dropdownParent.
How do I prevent this behavior and force the Select2 choices and search input to appear normally (directly above or below the Select2 depending on where it is in relation to the window edge)? Also, I have Select2 boxes on the page even when a modal is not activated, so affecting all Select2 boxes in this manner is not ideal.
Update: I tried swapping the other code for this line:
$.fn.modal.Constructor.prototype.enforceFocus = function () {};
This has the same effect as doing nothing at all: search inputs don't work in Firefox, but dropdowns are correctly placed.
Update 2: I tried this:
$('#id_project').set("dropdownParent", $('#id_project'));
This caused the dropdown to not appear anywhere, and the options are gone (replaced by ---------).
Update 3: I tried this...
$('#modal-task').css('overflow','visible');
...which resulted in the search input working...but modal scrolling is now broken. In addition, the dropdown is slightly misaligned on the left edge of the Select2 box.
This works fine for me
$(document).ready(function () {
$('select.select2:not(.normal)').each(function () {
$(this).select2({
dropdownParent: $(this).parent().parent()
});
});
});
just use select2 like this to bypass bootstrap modal bugs:
$('.my-select2').each(function () {
$(this).select2({
dropdownParent: $(this).parent(),// fix select2 search input focus bug
})
})
// fix select2 bootstrap modal scroll bug
$(document).on('select2:close', '.my-select2', function (e) {
var evt = "scroll.select2"
$(e.target).parents().off(evt)
$(window).off(evt)
})
I'm pretty much late, could help someone else. If you have tabindex = -1 on your modal then you may not be able to type. Try to remove it. Worked for me.
For me I was using select2 v4 and bootstrap modal. The change event was working with older versions of select2.
I needed to update my event listeners from
selectList.on('change', function(e) {
to select (add item)
selectList.on('select2:select', function(e) {
and unselect (remove item)
selectList.on('select2:unselect', function(e) {
https://select2.org/programmatic-control/events
First of all in select2 options must have
dropdownParent: $(this).parent(),// That fix weird positioning select2 input
After that we doing little trick when select2 opening event. I realized if modal height smaller than window height when select2 opening no problem for scrolling even after need scrolling.
So we put overflow adjustments on select2 events. When opening select2 set modal body to no overflow, after select2 open set back to default.
$(document).on("select2:opening", (e) => {
$('.modal-body').css('overflow', 'visible');
});
$(document).on("select2:open", (e) => {
$('.modal-body').css('overflow', 'auto');
});
That will fix your problem.
This drive me crazy, i've this simple html bootstrap-gentelella template that works almost in every page of the site that im developing, the html is so simple:
(this code make the part in the class "x_content" visible or not visible by clicking the "collapse-link" class in the "a" tag)
<div class="x_panel">
<ul class="nav navbar-right panel_toolbox">
<li>
<a class="collapse-link freccia_feed">Replies
<i class="fa fa-chevron-up"></i>
</a>
</li>
</ul>
<div class="x_content" style="display: none;">
<div class="input-group col-md-12 col-sm-12 col-xs-12">
<input data-role="tagsinput" id="risposta_'+j+'_D_'+element+'" class="form-control risposta_domanda_'+element+'" name="reply" value="" placeholder="Insert one solution" type="text">
<span class="input-group-btn">
<button id="elimina_risp_'+j+'_D_'+element+'" class="btn btn-danger glyphicon glyphicon-trash" > </button>
</span>
</div>
</div>
</div>
be carefull that the part like id="risposta_'+j+'_D_'+element+'" have no sense in this static part, and rendered as is it, just for example, I use that in the jQuery function that fail to make it works!
here:
$("#domanda_"+element).append(
'<div class="x_panel">'+
'<ul class="nav navbar-right panel_toolbox">'+
'<li>'+
'<a class="collapse-link freccia_feed" >Replies'+
'<i class="fa fa-chevron-up"></i>'+
'</a></li></ul>'+
'<div class="x_content" style="display: none;">'+
'<div class="input-group col-md-12 col-sm-12 col-xs-12">'+
'<input data-role="tagsinput" id="risposta_'+j+'_D_'+element+'" class="form-control risposta_domanda_'+element+'" name="reply"'+
'value="" placeholder="Insert one solution" type="text">'+
'<span class="input-group-btn"><button id="elimina_risp_'+j+'_D_'+element+'" class="btn btn-danger glyphicon glyphicon-trash" >'+
'</button></span>'+
'</div></div></div>');
I've tried many options to make this string works inside append() and the only one that seems working it to wrap the whole string with single ' using double " for ids class etc. and then inject javascript variable with single ' and +. Same thing for new line.
I even try to escape the whole string with online escape tools like https://www.freeformatter.com/javascript-escape.html
but still the same result, the component not works if is appended!
the problem is in the "inizialization" of the class ".collapse-link" by gentelella js.
So i move the function under my "div" generation function's.
I even add a "unbind()" func to resolve the problem that "inizialization" can toggle even the allready rendered div making them open anc closing several time...
thats the code if someone can find it usefull
cheers
$(".collapse-link").unbind("click");
$(".collapse-link").on("click", function() {
var a = $(this).closest(".x_panel")
, b = $(this).find("i")
, c = a.find(".x_content");
a.attr("style") ? c.slideToggle(200, function() {
a.removeAttr("style")
}) : (c.slideToggle(200),
a.css("height", "auto")),
b.toggleClass("fa-chevron-up fa-chevron-down")
});
I'm using http://www.makemytrip.com/
The below is the Html code.
<div class="mrgnBot30 clearFix">
<span class="watch_icn flL"></span>
<div class="widget_inner clearFix suggest_me padBot15 flL">
<h3 class="clearFix hasBorderBottom">
<p class="clearFix checkDates">
<span class="check_date flL">
<label for="checkInDate">
Check-in Date:
<span id="checkInDate_day" class="dayLight">(Monday)</span>
</label>
<a id="checkInDateControl" class="cal_icn flL" href="#" tabindex="201"></a>
<input id="checkInDate" class="day flL hasDatepicker" type="text" autocomplete="false" value="01/21/2013" name="searchCriteria.criterion.stayDateRanges[0].start" style="display: none;">
<span class="day date flL">
<select class="selectBox" tabindex="202" style="display: none;">
<span class="left_part flL"></span>
<span class="selectBox center_part flL selectBox-dropdown" style="display: inline-block; -moz-user-select: none;" title="" tabindex="202">
<span class="selectBox-label">21</span>
<span class="selectBox-arrow controls flR">
<a class="select_drop_icon flR" onclick="return false;" href="#"></a>
</span>
</span>
<span class="right_part flL"></span>
</span>
<span class="day month flL">
<select class="selectBox" tabindex="203" style="display: none;">
<span class="left_part flL"></span>
<span class="selectBox center_part flL selectBox-dropdown" style="display: inline-block; -moz-user-select: none;" title="" tabindex="203">
<span class="selectBox-label">Jan,13</span>
<span class="selectBox-arrow controls flR">
<a class="select_drop_icon flR" onclick="return false;" href="#"></a>
</span>
</span>
<span class="right_part flL"></span>
</span>
</span>
<span class="check_date last flL">
<span id="nights" class="nights flL">2 Night(s)</span>
</p>
</div>
</div>
Here i'm having a dropdown to select a Check in date and Check out date. Frankly say, i don't know how to select a value of the dropdown from code. Moreover i am not sure weather it is a dropdown or not. why i am saying mean while recording in selenium IDE it records as click event for selecting a value from the dropdown.
I tried select statement to select a value from dropdown by catching a xpath value using firebug.
The used code:
driver.get("http://www.makemytrip.com/");
driver.findElement(By.xpath("//li[4]/a/span/span")).click();
Select sel = new Select(driver.findElement(By
.xpath("//div[2]/div/p/span/span/span[2]")));
try {
sel.selectByValue("21");
} catch (Exception e) {
e.printStackTrace();
}
Nothing works. Below is the converted code from selenium IDE after the recording.
Selenese Code:
driver.get("http://www.makemytrip.com/");
driver.findElement(By.xpath("//div[#id='chf_navigation']/ul/li[4]/a/span/span")).click();
assertEquals("I want to go to", driver.findElement(By.cssSelector("label")).getText());
assertEquals("Online Hotel Booking for Cheap, Budget & Luxury Hotels in India | MakeMyTrip.com", driver.getTitle());
driver.findElement(By.xpath("(//a[#onclick='return false;'])[2]")).click();
driver.findElement(By.xpath("(//a[#onclick='return false;'])[3]")).click();
driver.findElement(By.xpath("(//a[#onclick='return false;'])[4]")).click();
driver.findElement(By.cssSelector("li.selectBox-hover.selectBox-selected > a")).click();
driver.findElement(By.xpath("(//a[#onclick='return false;'])[5]")).click();
Steps to see the dropdown:
Open http://www.makemytrip.com/
Click Hotels link
U able to see Check in Date dropdown.
Please provide useful suggestions to resolve the problem. Thanks in advance.
You have given the html code but u have not provided us the code which u have written, please provide the code u have written for this program and also let us know the error message or exception displayed.
Check in date select ids are b_checkin_day && b_checkin_month. Here is how to select them
//select the check-in date <select> element
Element el = driver.findElement(By.id('b_checkin_day'));
Select sel = new Select(el)
// go on with selection
Ckeck out select id are : b_checkout_day && b_checkout_month
That's for the US version. Indian version is definitly not a select but does not correspond to your html
EDIT : found that you were talking about Emirates website.
Sor for the day select, you should go with :
Element el = driver.findElement(By.xpath("//input[#id='checkInDate']/following-sibling::span[contains(#class,'date')]/select"))
xpaths are the following for month checkIn, day Checkout && month checkout respectively
"//input[#id='checkInDate']/following-sibling::span[contains(#class,'month')]/select"
"//input[#id='checkOutDate']/following-sibling::span[contains(#class,'day')]/select"
"//input[#id='checkOutDate']/following-sibling::span[contains(#class,'month')]/select"
Your first solution is to use these xpath to select the correct values
You can also more simply check the correct date in the inputs that are used to fill the form
i.e setting the correct date as value in
<input id="checkInDate" class="day flL hasDatepicker" type="text" autocomplete="false" value="01/21/2013" name="searchCriteria.criterion.stayDateRanges[0].start" style="display: none;">
should do the trick. (note the value="01/21/2013")
EDIT2 :
Have you tried to do that with the actual elements used by the visitor ? First, click on the dropdown arrow ("//input[#id='checkInDate']/following-sibling::span[contains(#class,'date')]/"), it will make the select used by the javascript date selector visible.
You then should be able to make the good selection when clicking on :
//ul[contains(#class,'selectBox-dropdown') and contains(#style,'block')]//a[#rel="25"]
if 25 is the day you want. <ul>s/<li>s that are used to make the selection are at the bottom of the page. Look at them, you'll find the correct xpath