How to deal with Date Picker - selenium

I've to select a user specified date and the snippet for picker is below.
sendkeys() functionality isn't working so I tried the below code.
JavascriptExecutor check = (JavascriptExecutor)driver;
check.executeScript("document.getElementById('hotel-checkin').setAttribute('value','10 Jan 2018')");
On entering the value, the date picker stays alive wherein the script fails to click the search button which is actually overlapped by date picker.
Any leads would be of great help. Thanks in advance!

Ok, you asked for leads so here're some thoughts and wild guesses (as long as you didn't give us neither url nor html).
sendkeys() doesn't work because the input field most probably has an event handler attached that opens datepicker widget. So, your first try to set value through JS is OK. I use slightly different way (sorry, python code here): driver.execute_script("arguments[0].value = arguments[1];", webelement, value)
But this mightn't work because you're entering a value to the visible field and an actual field (supposed to be filled by the datepicker widget) used by the page (a form or JS code) is hidden and holds no value. Then, try to find that field and enter a value to it by JS method.
In my current project I couldn't find that hidden field. I've decided to implement full user-like interaction with the datepicker widget. The scenario: click on the date field (datepicker widget opens), click on year or month selector buttons, then click on a day wanted. This way widget sets relevant data in a relevant fields (whatever and wherever they are) and closes.
Why I said fields (plural)? My recent thought was: May be setting the visible date field is right but there's some other field that must be set (like, say, date_was_set = "true").
Hope, this was helpful.
Edit. As for the 3rd paragraph. Here is my somewhat edited example (python, again).
The datepicker looks like this
As you can see it has buttons to adjust month and year combined.
from selenium.webdriver.support import expected_conditions as EC
class SetValCalendarStrategy(object):
def __init__(self, driver, calendar_param):
self.driver = driver
# this object holds parameters to find the calendar itself and its components
# pairs:
# sel_type - selector type ('xpath', 'id', 'name' etc.)
# sel_value - selector value to find ("//tr/td" etc)
self.param = calendar_param
def __call__(self, field, value, timeout):
"""
:param <webelement> field - input field
:param <datetime> value - value (date) to set
"""
# initiate datepicker with click on date input field
field.click()
# wait for a widget to show
cal = WebDriverWait(self.driver, timeout, 0.3).until(
EC.visibility_of_element_located(
(self.param.sel_type, self.param.sel_value)))
# decrease month/year button
prev_button = cal.find_element(
self.param.prev_month.sel_type,
self.param.prev_month.sel_value)
# increase button
next_button = cal.find_element(
self.param.next_month.sel_type,
self.param.next_month.sel_value)
today = datetime.now()
# calculate difference in months between today and the target date
month_diff = value.month + (value.year - today.year) * 12 - today.month
# select month/date
if month_diff < 0:
button = prev_button
else:
button = next_button
for i in range(abs(month_diff)):
button.click()
# template looks like this. It selects only days from target month (bold font)
# "//div[contains(#class, 'datePickerDay') and not(contains(#class, 'datePickerDayIsFiller')) and text()='{}']"
# insert day (21) into template. then it becomes
# "//div[contains(#class, 'datePickerDay') and not(contains(#class, 'datePickerDayIsFiller')) and text()='21']"
day_picker_sel_value =
self.param.day_picker.sel_template.format(value.day)
day = cal.find_element(
self.param.day_picker.sel_type,
day_picker_sel_value)
day.click()

Related

Selenium - Python: send_keys does not send data

I have a problem.
I am trying to fill out the Facebook registration form using selenium. I can fill in all the fields except the 'month' field and I don't really understand why. I don't get any error, the field is simply not filled in. I am sure that the values are generated correctly, but I cannot understand why I cannot fill in the month field. This is the part of the code in question:
from faker import Faker
fake = Faker()
day = fake.day_of_month()
month = fake.month()
year = random.randint(1982, 1995)
driver.find_element(By.ID, "day").send_keys(day)
time.sleep(3)
#driver.find_element(By.ID, "month").send_keys(month)
#time.sleep(3)
#m = Select(driver.find_element(By.ID, "month"))
#m.select_by_value(month)
driver.find_element(By.NAME, "birthday_month").send_keys(month)
time.sleep(3)
driver.find_element(By.NAME, "birthday_year").send_keys(year)
time.sleep(3)
Day and year are filled in correctly, as opposed to month. I have tried everything, including not having 'Faker' generate the random values, but nothing. Can you help me?
One reason it's not working could be that fake.month() function returns integer values while Facebook registration form declares string values such as 'May' 'June' etc. I suggest you try with a list of months.

There's no input tag where there should be one [duplicate]

I'd like to modify part of the text in a textarea with Selenium. The textarea seems almost as if it were read-only.
In this very simple example using a sample algo, it would be great to be able to change the stock id on this line:
context.aapl = sid(24)
... to something like:
context.aapl = sid(39840)
... which is the Tesla stock id. The variable name will no longer make sense, doesn't matter, just a start.
This Selenium code for me is able to open the sample with no login required.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
t = webdriver.Firefox() # t stands for tab as in browser tab in my mind
t.implicitly_wait(10)
t.get('https://www.quantopian.com/algorithms/')
o = t.find_element_by_xpath("//body") # o stands for object
o.send_keys(Keys.ESCAPE) # clearing the popup
o = t.find_element_by_link_text("Hello World Algorithm")
o.click()
''' for the fun of it if you want to run the backtest
o = t.find_element_by_xpath('//body')
o.send_keys(Keys.CONTROL + 'b')
o.send_keys(Keys.ESCAPE)
'''
print t.find_element_by_id('code-area').text
Here's the output from that
1
# Called once at the start of the simulation.
2
def initialize(context):
3
# Reference to the AAPL security.
4
context.aapl = sid(24)
5
6
# Rebalance every day, one hour and a half after market open.
7
schedule_function(my_rebalance,
8
date_rules.every_day(),
9
time_rules.market_open(hours=1, minutes=30))
10
11
# This function was scheduled to run once per day at 11AM ET.
12
def my_rebalance(context, data):
13
14
# Take a 100% long position in AAPL. Readjusts each day to
15
# account for price fluctuations.
16
if data.can_trade(context.aapl):
17
order_target_percent(context.aapl, 1.00)
That id is 'code-area'. The content includes margin numbers which might be a problem.
Next nested area is 'code-area-internal', seems the same.
Followed by these two.
<div class='ide-container' id='ide-container'>
<textarea class='width_100pct' id='codebox'>
In trying to obtain the content of the algorithm with 'codebox', content doesn't appear to be present, just u'' ...
>>> p = t.find_element_by_id('codebox').text
>>> p
u''
Attempt to do CTRL-A on it results in this exception...
>>> o = t.find_element_by_id('codebox')
>>> o.send_keys(Keys.CONTROL + 'a')
ElementNotInteractableException: Message: Element is not reachable by keyboard
If the text can be completely cut, then replace can done in Python and paste, that would be fine.
I wouldn't expect Selenium to be able to find and replace text, just surprised it finds a visible area for user input to be off limits from interactivity.
That textarea does have its own Find, and hoping won't have to resort to trying to use it as a workaround.
(The environment is an online IDE for stock market algorithms called Quantopian)
This is the one other thing I tried, with no apparent effect:
>>> t.execute_script("arguments[0].value = arguments[1]", t.find_element_by_id("ide-container"), "_new_")
Appreciate any pointers.
Textarea has style="display: none" attribute which means that you cannot get its content with text property. In this case you can use:
p = t.find_element_by_id('codebox').get_attribute("textContent")
To set new value to code field you can use:
field = driver.find_element_by_css_selector('div[role="presentation"]')
driver.execute_script("arguments[0].textContent = 'New value';", field)
But note that initially each code line in code field displayed as separate div node with specific value and styles. So to make new value looks exactly as code (in the same formatting) you can prepare HTML sample e.g.
value = """<div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="left: -48px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 15px; width: 21px;">1</div></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment"># Comment for new code.</span></span></pre></div>"""
and do
driver.execute_script("arguments[0].innerHTML = arguments[1];", field, value)
The content of the algorithm with codebox which you are trying to extract is having the style attribute set to display: none;. So to extract the text you can use the following lines of code :
p = t.find_element_by_xpath("//div[#class='ide-container']/textarea[#id='codebox']")
t.execute_script("arguments[0].removeAttribute('style')", p)
print(t.get_attribute("innerHTML"))

How to sendkeys "time" in time type element?

I need to pass data in time format in "time" type element in "10:00 AM" format.
I am using following code:
public static void setShift()
{
txttime.sendkeys("1030AM");
}
this is not working. what is a correct way to enter such data?
Use Following Code :
It will work it for textbox/text area control
SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
Date date = new Date();
txttime.sendkeys(date);
For the HTML input type datetime-local handling it from selenium is not ideal. It is not the most used date time picker, and it is not supported in firefox or safari.
For chrome, the date time format shows the format set in the browser's machine.
If you haven't changed anything, I'm guessing you are getting the format shown in the guru99 tutorial.
If that is the case, then you have missed that they also have provided the solution there.
After entering the date part you need to press tab to input the time part. Which is missing from your given code.
Try this:
First, input the date
WebElement dateBox = driver.findElement(By.xpath("//form//input[#name='bdaytime']"));
dateBox.sendKeys("09252013");
Second, press tab
dateBox.sendKeys(Keys.TAB);
Last, input the time
dateBox.sendKeys("0245PM");
Note:
If your machine has different DateTime formatting then this might not work. You have to check which part of the date time senKeys can actually input then split up that part and use Keys.TAB to press tab. Then input the next part until completion.

How to Select Choices input field having same class, type, Xpath everything is same

I have two input fields to enter choices which have same class, type. Id is different by it is dynamic and create on run time so i can't use id.I used indexing ,it's not working properly.
driver.findElement(By.xpath("//input[#type='text'][#placeholder='Provide a response entry that customers can select'][1]")).click();
driver.findElement(By.xpath("//input[#type='text'][#placeholder='Provide a response entry that customers can select'][1]")).sendKeys("Iphone 6");
driver.findElement(By.xpath("//input[#type='text'][#placeholder='Provide a response entry that customers can select'][2]")).click();
driver.findElement(By.xpath("//input[#type='text'][#placeholder='Provide a response entry that customers can select'][2]")).sendKeys("Iphone 7");
I used indexing in given image link.
click link to view code in organized way
Index 1 works in this case but unable to find index 2.
Given inspected html code is below of input field 1 and field 2
Field 1
Input field 1 image Xpath link
field 2
Input field 2 image link
If these two inputs are always in this sequence (so the first input is always first and second always second)
You can use:
driver.findElement(By.xpath("(//input[#type='text'][#placeholder='Provide a response entry that customers can select'])[1]")).click();
driver.findElement(By.xpath("(//input[#type='text'][#placeholder='Provide a response entry that customers can select'])[2]")).click();
At the same time I have corrected the syntax in indexing
Building on #Anand 's answer, you can simplify a little:
WebElement button1 = driver.findElement(By.xpath("(//input[#type='text' and #placeholder='Provide a response entry that customers can select'])[1]"));
WebElement button2 = driver.findElement(By.xpath("(//input[#type='text' and #placeholder='Provide a response entry that customers can select'])[2]"));
I think it's a little easier to read using and instead of stacking brackets.
I use it similarly for widgets:
WebElement header = driver.findElement(By.xpath("//div[contains(#class,'panel')]/div[contains(#class,'panel-heading') and text()[contains(.,'News Feed')]]"));

Protractor sendKeys issue with scripted input fields

I'm automating e2e tests with Protractor on an angular app.
However, I have an issue when sending keys on input fields.
The sendKeys would miss few characters everytime so I found a workaround :
static sendKeys(value, element){
value.split('').forEach((c) => element.sendKeys(c));
}
This works well but it takes more than 3 times the time the original sendKeys function would.
Well no problem my tests are still functionnal right ?
My app now has new fields with scripts behind them.
One of them is a datepicker input, you can either choose from the datePicker or type it manually. However, for today's date you would type 09022018 and the slashes are automatically appended at the right place (like so 09/02/2018). If you were to enter a wrong date the field is cleared.
Now back to the problem : it seems that both my implementation of sendKeys and the original one loose focus after each submitted key. This means that I can't enter a valid date in the input field as it's cleared after each simulated keypress.
I could use browser.executeScript to fix it but I wouldn't be able to test the functionnality adding slashes. Also, as you type, the datepicker is still open and refreshes after each keypress, you can select a date from it at any time and that is also a feature I want to test.
Thanks in advance
Use executeScript to set the date in backgrond, then use sendKeys to enter a space or Tab at the end to trigger the Keyborad event which will check the input and format the input with slash
function enterDate(date) {
var script = 'arguments[0].value=arguments[1]';
// input box for date
var dateBox = element(by.xxx(yyy));
browser.executeScript(script, dateBox, date);
dateBox.sendKeys(" ");
// or try send Tab
dateBox.sendKeys(protractor.Key.TAB);
}
enterDate('09022018');
You can try this solution on other fields you fixed but take 3 more time.