I want to automate an application where user has to enter the OTP at a particular interval . Is it possible to automate is such a way using Selenium?
Ideally there should be no Manual Intervention when Automated Test Execution is In Pogress.
If entering an OTP is one of the step of the Usecase it should be automated too.
Note : OTP can be sent to an email address and can be validated.
If your are running the tests in Dev environment, One possible solution would be to request the developers to set a constant value for the OTP and then validate the field with the value.
More complex solution would be to get the value from message box which will include appium concepts or to read the OTP value from the mail box
You don't have to handle this with Selenium, rely on programming language. Display a box/message, when user enters pass that to the form via selenium send keys and continue your automation. Selenium will actually wait unless your page expires. Below code can help.
driver.findElement(By.id("username")).sendKeys("username");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String otp;
System.out.println("Please Enter the OTP Code:: ");
otp = br.readLine();
System.out.println("Entered OTP Code is:: "+otp);
driver.findElement(By.id("password")).sendKeys("otp");
Suppose you want to enter your OTP at this page,
www.your-page.com/OTP
once this page spawns, use new Scanner(System.in).nextLine
to manually wait for user-input of any key on your console. Before pressing Enter on your console, you can insert your OTP in the page (and press submit if any) after which you can resume your execution from your console by pressing any key.
This shall create a manual-halt-like feature during which you can perform your manual interactions.
Related
I want to automate "amazon-add-to-cart" procedure.
the flow is to send http get method of the requested items, and then
submitting a button of the returning html.
the 1st url for example is:
https://www.amazon.com/gp/aws/cart/add.html?AssociateTag=your-tag&ASIN.1=B003IXYJYO&Quantity.1=2&ASIN.2=B0002KR8J4&Quantity.2=1&ASIN.3=B0002ZP18E&Quantity.3=1&ASIN.4=B0002ZP3ZA&Quantity.4=2&ASIN.5=B004J2JG6O&Quantity.5=1%22
after that the user should click the continue button in order to indeed adding the items to the cart.
can you provide an example of how to code this flow with the button click using java selenium - without openning the browser?
thanks.
use the "HTMLUnitDriver" Webdriver
WebDriver driver = new HtmlUnitDriver();
driver.get("Enter the URL");
I'm trying to test my Hotmail account using selenium Webdriver 3.0. I set my account to ask for two way authentication, which means Indeed to enter the last 4 digits of my mobile number and then send a message to me. Then I have to enter that code in order to open my email Account.
It worked good with me when I used implicit, waited for 60 seconds until i receive the code then enter it manually and so the test continues to my email page >> all works fine.
BUT my question is, is there any way to make the test wait until I enter the code rather than waiting for 60s?!
Is that acceptable to enter some things manually while using Selenium webdriver?
is that acceptable to enter some things manually while using selenium webdriver?
Yes, because this thing is made for stopping robot activity just like Captcha code entering the process. So, in this scenario, this is acceptable to enter text manually after reading the text from mail while using selenium.
You can do one thing more if you want to do it automatically, you should implement mail API to read the last mail from your provided account in the background and fetch necessary text from the last mail using some programming stuff and enter it into textbox using selenium.
is there any way to make the test wait until I enter the code rather than waiting for 60s?
Yes, to achieve this you need to create your own custom ExpectedConditions with WebDriverWait which will wait until located text box has value greater or equal 4 character or other suitable condition which you want as below :-
//Initialize WebDriverWait first which will wait maximum 60 seconds
WebDriverWait wait = new WebDriverWait(driver, 60);
//Create suitable locator to locate textbox element eg. with xpath locator
By byObject = By.xpath("enter here textbox xpath");
//This condition will wait until text box has value greater or equal 4 character
wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return (d.findElement(byObject).getAttribute ("value").length() >= 4)
}
});
I am creating a framework in selenium from scratch where i am scripting below scenarios:
1.Login in to https://www.yahoomail.com
2.entering username
3.entering password
4.click on Sign-In
5.click on Compose button
6.Enter Email ID, Subject and Message body.
Below is the code script i have written for above scenario:
WebDriver oYahoo = new FirefoxDriver();
oYahoo.get("http://www.yahoomail.com/");
oYahoo.manage().window().maximize();
oYahoo.findElement(By.xpath(".//*[#id='login-username']")).sendKeys("abcdefasdf#yahoo.com");
oYahoo.findElement(By.xpath(".//*[#id='login-passwd']")).sendKeys("sfgas234#123");
oYahoo.findElement(By.xpath(".//*[#id='login-signin']")).click();
oYahoo.findElement(By.xpath(".//*[#id='Compose']/button")).click();
oYahoo.findElement(By.xpath(".//*[#id='yui_3_16_0_1_1448364357109_2222']")).sendKeys("abcdefgh#gmail.com");
oYahoo.findElement(By.xpath(".//*[#id='subject-field']")).sendKeys("Hi This is my first automated mail");
oYahoo.findElement(By.xpath(".//*[#id='yui_3_16_0_1_1448364357109_1966']")).sendKeys("Hi This is my first automated mail");
oYahoo.findElement(By.xpath(".//*[#id='yui_3_16_0_1_1448364357109_2465']")).click();
oYahoo.quit();
Scripts fine till it clicks on "Compose" button, Once i get Mail editor, Script does not enters email-ID,Subject, and Message body.
What other action i should perform to achieve the same so that script will enter these parameters and can send a mail to particular user.
Do we need to create some class which will maps the locators to "compose-Email" screen?
If yes, how we can map/assign x-path to particular web element of Compose-Email page.
Thanks in Advance.
Well you should try by using the xpath and enter the required text. Something like this (it works for me)-
oYahoo.findElement(By.xpath(".//*[#id='to-field']")).sendKeys("xxxx#xxx.com");
oYahoo.findElement(By.xpath(".//*[#id='subject-field']")).sendKeys("My first automated email");
oYahoo.findElement(By.id("rtetext")).sendKeys("Hello....Hi....This is my first automated email");
The problem I'd like to solve is the following:
I need to manage an external web page through PHP, for example, login and then change the profile info on the external web after sending an ajax request on my own web.
For this, I'm calling PhantomJS from PHP to do those tasks, but before login to the external web I need to fill the captcha input. So, I'd like to send back the Captcha image to my web, write the correct code and send it back to the WebPage module of PhantomJS to login using that code.
In other words, I need a 'syncronous' program like this:
1) PHP -> Send a request to login and obtain the captcha image.
2) PhantomJS -> Open a WebPage instance and render the captcha code to an image.
3) PHP -> Get the captcha image, show it to an user and send a text input to PhantomJS.
4) PhantomJS -> Get the text code from PHP, fill the captcha input using 'page.evaluate' and login. Send to PHP some data ('Login successfull', 'Login failed', etc)
5) PHP -> Get the callback and send another task or data.
callback = 'Login successfull' --> Change profile picture or update user info.
callback = 'Login failed' --> Try to login again (like point 1)
Etc...
There are many things I don't know how to handle. For example:
1) How could I keep the WebPage module open and waiting for the text code of the captcha? If I close it, a new captcha code will appear next time, and I need a way to wait the code and get it. Do I need to start a server for this?
2)Get the captcha image from PHP isn't a problem (because of 'page.render'), but how I could send a text back to the WebPage instance of PhantomJS? I think is better to send data bidirectionally between both systems. Again, do I need a server?
I think I need a socket server in PhantomJS (how can this be done?). This server should have the WebPage instance that I need to keep open, but I'm not completely sure about this.
Thanks.
I recently published a project that gives PHP access to a browser. Get it here: https://github.com/merlinthemagic/MTS, Under the hood is an instance of PhantomJS.
The main issue is keeping a resource alive after initial execution. Here is how i propose you do it.
After downloading and setup you would simply use the following code:
Start of "Setup" session:
if (isset($_POST['sessionUID']) === false) {
//set the execution timeout long enough to cover the entire process (setup and working time), it dictates when phantomJS shuts down automatically.
ini_set('max_execution_time', 300);
//open the login page:
$myUrl = "http://www.example.com";
$browserObj = \MTS\Factories::getDevices()->getLocalHost()->getBrowser('phantomjs');
//allow the page to live after php shuts down.
$browserObj->setKeepalive(true);
$windowObj = $browserObj->getNewWindow($myUrl);
//find the username input box, here it has id=username
$windowObj->mouseEventOnElement("[id=username]", 'leftclick');
//type your username
$windowObj->sendKeyPresses("yourUsername");
//find the password input box, here it has id=passwd
$windowObj->mouseEventOnElement("[id=passwd]", 'leftclick');
//type your password
$windowObj->sendKeyPresses("yourPassword");
//click on the login button, here it has id=login
$windowObj->mouseEventOnElement("[id=login]", 'leftclick');
//i assume this is when you encounter the CAPTCHA image
//find the CAPTCHA image element, here it has id=captchaImage
$element = $windowObj->getElement("[id=captchaImage]");
$loc = $element['location'];
//tell the screenshot to only get the CAPTCHA image
$windowObj->setRasterSize($loc['top'], $loc['left'], ($loc['right'] - $loc['left']), ($loc['bottom'] - $loc['top']));
$imageData = $windowObj->screenshot("png");
$sessionUID = uniqid();
$saveWindowObj = serialize($windowObj);
//save the window object so we can pick it up again
file_put_contents("/tmp/" . $sessionUID, $saveWindowObj);
}
//now render the CAPTCHA image to the user as part of a form they can resubmit and make sure to keep the $sessionUId as a hidden variable in the form on the page
End of the "Setup" session, php shuts down here.
Start of "Working" session:
We assume the user submits the form and it is a post containing the $sessionUID and the text string for CAPTCHA.
if (isset($_POST['sessionUID']) === true && isset($_POST['captchaTxt']) === true) {
$savedWindow = file_get_contents("/tmp/" . $sessionUID);
//delete the saved object
unlink("/tmp/" . $sessionUID);
//bring back the object to life
$windowObj = unserialize($savedWindow);
//make sure the browser is now shutdown on exit
$windowObj->getBrowser()->setKeepalive(false);
//find the CAPTCHA input box, here it has id=captchaInput
$windowObj->mouseEventOnElement("[id=captchaInput]", 'leftclick');
//type the CAPTCHA string
$windowObj->sendKeyPresses($_POST['captchaTxt']);
//click on the button to accept CAPTCHA, here it has id=captchaOK
$windowObj->mouseEventOnElement("[id=captchaOK]", 'leftclick');
//now use the clickElement() etc functions on $windowObj to do what you need to do.
}
End of the "Working" session, php shuts down here.
I have started using Webdriver to automate our testing which is 100% manual.
In one of the use cases I need to click on a link sent to the user's inbox. I am facing problems with Gmail in this case. After logging in I am not able to figure out how to open a particular email.
I know the email subject etc but I am unable use it to access the element. Gmail receives all its data as JSON and then build the entire page through js functions. So the webdriver is not able to access any of the elements built using the JSOn data received.
Any help is greatly appreciated.
Thanks,
Chris.
I would suggest NOT to use UI to verify Gmail. Gmail's UI is extremely complicated and it's a trap. To me, automating with selenium is not a solution at all.
Consider using JavaMail API and HTTPURLConnection. This is what I do in a similar testing scenario.
While running the webdriver test, after doing certain action if you expect an email then using JavaMail API poll (for a certain timeout if its not immediate) for the email in the background with certain 'subject' or 'sender' etc. Once the email is found then grab the link from the email content and then simulate a click using HTTPURLConnection
If you can search the specific email you can use the following code to locate the email you are looking for:
//div [#class='y6']/span[contains(.,'<your original search text>')]
mind that google will cut off the subject which results in something like 'subject...' if the subject is too long. We use a unique number to identify messages in our automated test environment.
I don't think I got your question correctly but I suppose you are having trouble finding the locator to open the mail after you've entered text in search box of gmail.
//div[5]/div/div/table/tbody/tr[n]" //n is the row no. of mailbox, for first result use 1 and like
use this as identifier for element before cliking on it.
Hope this helps.
In my case, I found the solution by using Action class of Web driver
Pre-requisite: Your driver needs to move to specific frame to locate element
wd.switchTo().frame("canvas_frame");
Step 1) Search for specific email that is created/generated using below code
String searchvalue="html/body/div[1]/div[2]/div/div[1]/div[3]/div/div[1]/div[2]/div[2]/div/form/fieldset[2]/div/div/div[2]/input";
wd.findElement(By.xpath(searchvalue)).sendKeys(sendkeys);
String clickSearch=".//*[#id='gbqfb']";
wd.findElement(By.xpath(clickSearch)).click();
Step 2) Now use Actions class to navigate through.
Actions action= new Actions(wd);
action.click(firstrecord).build().perform();
Hope this helps out!
The above answer is correct to identify a mail in Gmail if we replace the subject.
I have tried with Selenium IDE to find the object with the
target as
xpath=//div [#class='y6']/span[contains(.,'<your original search text>')]
The object was found but click is not opening the mail.
So after some investigation I found that mouseDown method is working with the above xpath to open a mail.
So command will be
selenium.mouseDown("xpath=//div [#class='y6']/span[contains(.,'<your original search text>')]");
or
<td>mouseDown</td>
<td>xpath=//div[#class='y6']/span[contains(.,'£10 OFF when you spend £30 or more online')]</td>
<td></td>
in the IDE.
Hope this helps.
The current locator for gmail body is:
driver.findElement(By.className("LW-avf")).click();
driver.findElement(By.className("LW-avf")).clear();
driver.findElement(By.className("LW-avf")).sendKeys("your body message");
The below selenese command would do:
clickAt | //table/tbody/tr/td[5]/div[#class='yW'] |
Click at the FROM field of first/recent/top most mail to go to mail detail page. // note: tr for first mail, tr[2] for second and so on.
Try this out , working perfectly for me. This will select random emails, you can also modify as your requirement
for i in xrange(int(num)):
time.sleep(3)
m=random.randint(1,10)
print("Mail Number "+str(m)+" is selected")
browser.find_element_by_xpath("//div[#role='tabpanel'][1]//table//tr"+str([m])).click()
time.sleep(3)
browser.find_element_by_xpath('//*[#id=":5"]/div[2]/div[1]/div/div[1]/div/div/div').click()
You can use this also if you want to open a particular mail in gmail:
driver.findElement(By.xpath("//tr[i[td[4[div[contains(#class,'yW')]]]")).click();
Here i is the mail number which you want