Selenium + Chrome Driver drag and drop not working properly - selenium

I am using Selenium 3.14 and ChromeDriver 2.42 with Chrome 69.0. I was always using this code to drag and drop, which worked until recently, when tests started failing:
$driver->action()->clickAndHold()->moveByOffset(100, 0)->release()->perform();
After some Chrome update, it just stopped dragging. I also tried dragAndDropBy() function, with no luck. (dragAndDrop() is not an option because I need to move inside one element).

After hours of experimenting I was able to narrow the issue down to this weird thing, when using moveByOffset with bigger number, like 100 in my example fails, it just weirdly bounces in place. But when I tried to move it only by couple of px, it worked.
This is the code I ended up with:
$driver->action()->clickAndHold()->perform();
for($i = 0; $i < 10; $i++){
//moving this 10 times by 10 px instead of once by 100px
$driver->action()->moveByOffset(10, 0)->perform();
}
sleep(1);
$driver->action()->release()->perform();
I just want to share this, if somebody encountered similar issue.

Related

How do I wait for an element to disappear in Cypress?

I'd like to preface this by saying that I really tried looking here and anywhere else for an answer but without a succes.
Here is the problem:
I'm trying to automate a test for a web application that is loading a bigger amount of data and therefore has to be loading for a while. I have to wait for the page to load to do the next step and I'm trying to figure how to wait for the loading gif to be complete so that my tests can continue. The gif is a basic spinning thingy.
I would like to avoid using implicit wait time (cy.wait()) that is really only the last resort if noone is able to solve this.
What I found o far are these two functions:
cy.waitFor - this seems to be used mostly in situations, where you are waiting for an element to apper - I've tried this in different scenarios and works perfcetly but I havent been able to apply it here.
cy.waitUntil - this seems to be the thing I'm looking for but there is one huge problem. This function seems to have a timeout and I haven't been able to change it any other way than by changing timeouts globally for all the functions. If I set the global timeout to some longer period (minute +), then it works exactly how I would want it to work but obviously I dont really want to have such a long timeout for everything.
The way I see it, there are two possible solutions to this problem>
to change/turn off the timeout for the waitUntil function.
2)Or to somehow make it work with waitFor, because there seems to be no implicit timeout there and it just kind of waits forever for something to happen.
here is the code snippet of the situation:
cy.get('#load-data-button').click() // this clicks the button that stars the loading proces
cy.waitUntil(() => cy.get('body > div > my-app > billing > div > div > div.text-center > img').should('not.be.visible',) ) // this is the function that waits until the loading gif is invisible
I would be eternaly grateful for a solution, because unfortunatelly no one at my company is really a Cypress expert so they are not able to help.
Could you try something like:
cy.get([loading-spinner-identifier]).should("not.be.visible", { timeout: 60000 });
cy.get([an element that should now be visible]).should("be.visible");
It's a bit rough and ready, but I've used it when waiting for spinners to finish up. This waits a minute to see the spinner isn't there and then checks to see that something I'm expecting is there. I'd had varying success with this, but it has helped in some situations.
You can indeed use cy.waitUntil(). As you can see in the documentation of that package (https://www.npmjs.com/package/cypress-wait-until#arguments), the timeout that the function has is just the default (5000 ms) of an argument you can change it. You can even change how often cypress checks the condition you want, so if you do something like:
cy.waitUntil(() => cy.get('body > div > my-app > billing > div > div > div.text-center > img').should('not.be.visible'), {
errorMsg: 'The loading time was too long even for this crazy thing!',
timeout: 300000,
interval: 5000
});
...it will try for 300 seconds (5 minutes) each 5 seconds (just an example with very long timeout).
Also, maybe you can consider to wait until some element is visible after that loading spinner, instead of checking if it dissapeared. If you want to specifically test it, is fine, but if some element appears or becomes interactable after the loading, it could happen that is still not in the state you want, for a fraction of a second, after the spinner is not visible. If that is the case, I would avoid the checking of the spinner dissapearing in first place, unless it adds value to your test, and I would just wait for that element to be in the state you want (for example wait until some input is not disabled, element is visible, text appeared somewhere...).
Add positive and negative assertion to make sure loading spinner is visible.
Default Time is 4s for assert statement.
You can increase defaultTime to wait for assertion to validate by adding configuration in cypress.json
{
...
"defaultCommandTimeout": 4000,
...
}
const waitForSpinner = () => {
// First, make sure the loading indicator shows up (positive assertion)
cy.get('[data-qa="qa-waiting-spinner"]').should('be.visible')
// Then Assert it goes away (negative assertion)
cy.get('[data-qa="qa-waiting-spinner"]').should('not.be.visible')
}

Selenium code freezes after opening second window

Following code hangs for about 12 minutes after clicking on "Print Change"
button and then throws error that element not visible at line:
driver.findElement(By.xpath("//button[contains(text(),'Print
Change')]")).click();
System.setProperty("webdriver.chrome.driver",
System.getProperty("user.dir")+ "\\exe\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().deleteAllCookies();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
driver.get(prop.getProperty("https://genpact-qa-smartit.onbmc.com"));
driver.findElement(By.xpath("//*[#id='okta-signin-
username']")).sendKeys(userid);
driver.findElement(By.xpath("//*[#id='okta-signin-
password']")).sendKeys(pwd);
driver.findElement(By.xpath("//*[#id='okta-signin-submit']")).click();
driver.findElement(By.xpath("//a[#id='header-search_button']")).click();
driver.findElement(By.xpath("//input[#id='globalSearchBox']")).
sendKeys("CRQ000000029504");
Robot robot=new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
driver.findElement(By.xpath("//a[text()='View Full Change']")).click();
Thread.sleep(3000);
driver.findElement(By.xpath("//div[#title='Print']")).click();
Thread.sleep(3000);
driver.findElement(By.xpath("//button[contains(text(),'Print
Change')]")).click();
System.out.println("Clicked on Print Change button");
I am using OS: Windows 10; Browser: Chrome 77.0.3865.90; Selenium: 3.141.59
Any help would be highly appreciated.
Regards,
Surender
First of all for your safety please edit your post removing your username and password that are in your code (and afterwards change them).
As far as your problem is concerned there is a high possibility that:
driver.findElement(By.xpath("//button[contains(text(),'Print
Change')]")).click();
there are more than one elements with the given xpath so the one you want might not be visible.
Therefore you should either be more specific with the:
[contains(text(),' ... ']
or try using the css selectors.
Anyway look up the docs for locating elements and if you still don't find a solution I will be happy to help you again.
Edit: In order to help you I logged in and your solution probably is to replace
driver.findElement(By.xpath("//button[contains(text(),'Print
Change')]")).click();
with
driver.findElement(By.xpath("/html/body/div[4]/div/div/div/div[3]/div/button[1])]")).click();
You specified an implicit wait of 120 seconds , so the code will wait for 120 seconds before throwing in to an exception.
in this case i think the xpath is wrong that's why its waiting for long time (may be there is some extra space in between the text print change). Use any xpath identification tool to check whether the xpath is correct or not
i hope the following code may work
driver.findElement(By.xpath("//button[contains(text(),'Print')]")).click();

Drag an element over another in selenium

I am trying to drag and drop an element over another but I am not able to do so. I am trying to perform the above operation on http://the-internet.herokuapp.com/drag_and_drop
This is my code
we1=driver.findElement(By.xpath("//*[#id='column-a']"));
we2=driver.findElement(By.xpath("//*[#id='column-b']"));
action.clickAndHold(we1);
action.moveToElement(we2, 450, 250);
Thread.sleep(3000);
action.release().build().perform();
Instead of action.moveToElement(we2,450,250) I have even tried using action.moveToElement(we2) and action.moveByOffset(450,250).
I even tried to perform this operation using Robot class.
robot.mouseMove(230, 170);
Thread.sleep(3000);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseMove(450, 200);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
Nothing happens in any of the above code. No error or exception is thrown and Code execution gets completed successfully.
After a lot of effort (hit & try :) ) I was able to find a solution for my problem. It is working fine for the site I mentioned as well as for other sites also where drag and drop functionality is present. Here is the solution:
we1CenterX=we1Points.x+we1Dimensions.width/2;
we1CenterY=we1Points.y+we1Dimensions.height/2;
we2CenterX=we2Points.x+we2Dimensions.width/2;
we2CenterY=we2Points.y+we2Dimensions.height/2;
robot.mouseMove(we1CenterX, we1CenterY);
waitForMe(1); //custom wait
robot.mousePress(InputEvent.BUTTON1_MASK);
waitForMe(1);
robot.mouseMove(we2CenterX, we2CenterY);
waitForMe(1);
robot.mouseMove(we2CenterX+100, we2CenterY-70);
/*Moving the cursor over the element before releasing
the mouse button solved my problem*/
waitForMe(1);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
waitForMe(1);

Why Wait.until() doesn't work in Selenium WebDriver?

I have been using Selenium WebDriver. I want to wait until the element is present on the webpage, for which i am using:
WebDriverWait wait = new WebDriverWait(driver, Long.parseLong(timeout));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator)));
but my test get stucks in the second line if the element I am looking for, is not present and even beyond the timeout. Pls Help. Thanks.
Maybe:
- the element is present, so no exception is thrown
- then gets stuck because you are not doing anything else afterwards
Try printing smt after the until call. My guess is it will get printed.
Otherwise maybe it's the timeout:
It must be in seconds, not milli seconds.
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/WebDriverWait.html#WebDriverWait(org.openqa.selenium.WebDriver, long)
I got it worked. I changed the timeout from 60000 to 60 since it takes the second argument as seconds and not millisecs.

Selenium SelectWindow Command not working

Selenium Select Window command fails and shows "Could not find window with title....". but if i Execute the Select Window command alone it passes the case and verifying the elements.
Code i used:
public void testDefaultlogo() throws Exception {
selenium.open("http://Sitename/samp.aspx");
selenium.type("ctl00_mainContentPlaceHolder_txt_LoginName", "uname");
selenium.type("ctl00_mainContentPlaceHolder_txt_Password", "pwd#12");
selenium.click("ctl00_mainContentPlaceHolder_btn_login");
selenium.waitForPageToLoad("60000");
selenium.click("ctl00_defaultLogo");
selenium.selectWindow("Sample~Window-ID");
verifyEquals("http://Sitename/index.html", selenium.getLocation());
selenium.close();
selenium.selectWindow ("null");
verifyTrue(selenium.isElementPresent("ctl00_defaultLogo"));
I mean by clicking one by one of the follwing commands in Selenium IDE it shows green but if i run the case it failed and shows as i mentioned above
What I can get from your code is that, clicking the "ctl00_defaultLogo" will popup another window. The possible issue could be that after write the command selenium.click("ctl00_defaultLogo") you need to wait for the popup to load.
The possible resolution, insert the command
selenium.WaitForPopUp("Sample~Window-ID", "5000");
before the
selenium.selectWindow("Sample~Window-ID");
This will cause selenium to wait for 5 secs before selecting the popup window.
Hope this helps!!!
some times it may not work for that u better use.
open_window("URL","WindowID or title or name");
selenium.selectWindow("WindowID or title or name");