I was going through the selenium learning and when I was exploring Handling Windows and frames topic in the text, I found this code. Is it necessary to instantiate the Actions class and why we need to do that if we have never going to use it in the code?
public class SwitchBetweenFrames {
public static void main(String... args) {
WebDriver driver = new FirefoxDriver();
driver.get("file://C:/Frames.html");
Actions action = new Actions(driver);
driver.switchTo().frame(0);
WebElement txt = driver.findElement(By.name("1"));
txt.sendKeys("I'm Frame One");
driver.switchTo().defaultContent();
driver.switchTo().frame(1);
txt = driver.findElement(By.name("2"));
txt.sendKeys("I'm Frame Two");
}
}
No, we do not need the Action if nor required. Switching to frame or alert is different and using Action is different concept.
You can use different functions of Action class
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/interactions/Actions.html
And for switch is only used to shift control of webdriver from one page to another or one frame to another
No, it isn't a necessary step to instantiate Actions class, unless there is an actual need of it. For your code, it's not needed at all. Your code will still work, if you comment that section out.
Usually, Actions class can be used to emulate some user gestures, like: drag and drop, click and hold, etc., that by normal standards, is a tad tricky to implement.
No, it is not necessary to user Action class for passing control to a window. For Frames we are just passing the control to another frame. So SwitchTo is used.
Action classes are commonly used for mouse hover actions, drag and drop, click and hold etc like that.
If you want to know more about action class, check the link,
Actions class
Related
I have registered an action in the EditorPopupMenu (this is right click menu). I also have a bunch of components inside a ToolWindow (that I designed using the GUI Designer plugin) that I want to update the values of.
There have been some posts on the IntelliJ forums about this, and the typical answer seems to advice using the ToolWindow's ContentManager, and obtain the JPanel containing all your components. E.g. the following:
Project p = e.getProject();
ToolWindow toolWindow;
toolWindow = ToolWindowManager.getInstance(p).getToolWindow("My ToolWindow ID");
ContentManager contentManager = toolWindow.getContentManager();
JPanel jp = (JPanel) contentManager.getContent(0).getComponent();
This feels counterintuitive... Having to navigate inside JPanel's to find a bunch of components. What if I decided to put my components inside a different container? Suddenly the way I navigate to my components would break down.
Is it really the most practical way to constrain myself to the way my GUI is built? Can't I access these components in a different way?
I found a way to access my custom myToolWindow. This should help quite some people.
Make sure that your custom MyToolWindow extends the class SimpleToolWindowPanel.
In your custom myToolWindowFactory class, pass your custom MyToolWindow to ContentFactory.createContent() as the first argument. NOT one of the JPanel's inside MyToolWindow as is done in the ToolWindow examples given in the official IntelliJ documentation...
In your MyToolWindow constructor, call the method setContent(<YourJPanelContainingYourComponents>).
I found the answer by experimenting on example 5 from this link:
public JBTabbedTerminalWidget getTerminalWidget(ToolWindow window) {
window.show(null);
if (myTerminalWidget == null) {
JComponent parentPanel = window.getContentManager().getContents()[0].getComponent();
if (parentPanel instanceof SimpleToolWindowPanel) {
SimpleToolWindowPanel panel = (SimpleToolWindowPanel) parentPanel;
JPanel jPanel = (JPanel) panel.getComponents()[0];
myTerminalWidget = (JBTabbedTerminalWidget) jPanel.getComponents()[0];
} else {
NotificationUtils.infoNotification("Wait for Freeline to initialize");
}
}
return myTerminalWidget;
}
For example: Launch Outlook on your desktop. Notice how there is a "splash loading screen" well the driver I have will look at this executable and wait x seconds before trying to click on the "New Email" button. However when it gets to the page where the new email button appears, it can't find it. Strange... hmm okay lets start the application but have it trigger the executable that is already in the process. It looks for the new email button and finds it no problem.
The only thing i can think of is that the driver loads the executable, the executable then changes its data drastically or something. Then all of a sudden i need to build a new driver. But I dont think this is the way to go about it.
[TestInitialize]
public void TestMethod1()
{
options.AddAdditionalCapability("app", #"C:\Program Files (x86)\<PATH>");
_driver = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), options);
System.Threading.Thread.Sleep(5000);
}
[TestMethod]
public void TEST()
{
LoginPage page = new LoginPage(new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), options)); // Notice how i am building a new driver just for this page. This is VERY heavy.
page.Login("USERNAME", "PASSWORD");
}
You probably have the "splash screen issue".
Here's a explantation about what to do about it.
In short, winappdriver creates a new windowhandle for every new window it encounters. As the splash screen counts for a separate window, you should have 2 windowhandles available at the moment you wanted to click that "new email" button. The most recent windowhandle will be the highest index.
You can switch between windowhandles like this (copied from link):
// Return all window handles associated with this process/application.
// At this point hopefully you have one to pick from. Otherwise you can
// simply iterate through them to identify the one you want.
var allWindowHandles = session.WindowHandles;
// Assuming you only have only one window entry in allWindowHandles and it is in fact the correct one,
// switch the session to that window as follows. You can repeat this logic with any top window with the sameĀ²
// process id (any entry of allWindowHandles)
session.SwitchTo().Window(allWindowHandles[0]);
Also take a look at this answer. Could be useful too.
I found two ways to allegedly make the help work for an Eclipse wizard.
The first is to set setHelpAvailable(true) on my instance of Wizard and let the WizardPage override the method:
public void performHelp() {
PlatformUI.getWorkbench().getHelpSystem().displayHelp(CONTEXT_ID);
}
It displays a help button without an icon next to the "Back" button, but the method performHelp is never called.
The second way is to set it on the TrayDialog directly like this:
WizardDialog dialog = new WizardDialog(myShell, myWizard);
dialog.create();
WorkbenchHelp.setHelp(dialog.getShell(), CONTEXT_ID);
dialog.setHelpAvailable(true);
dialog.open();
This displays a button with an icon on the bottom left, but nothing happens when I click it.
The help system is set up (quiet a feat with the documentation, if I say so myself), but I can't figure out how to get either of these solutions to work. And I wonder if one of them should preferred over the other?
With the WizardDialog just call
dialog.setHelpAvailable(true);
In the createControl method of each WizardPage call the help system setHelp:
public void createControl(Composite parent)
{
Composite composite = new Composite(parent, SWT.NONE);
PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, "help id");
... other code
Just for completeness sake: In my case the problem had nothing to do with the sparsely documented help feature, but with the fact that Eclipse Mars can't Hot Code Replace anymore.
I'm working on automating a site which has a number of links which load new pages via a JS event. Basically, there are elements which are clickable, clicking on one causes some JavaScript to run and this leads to a form being submitted and routing to a new page.
Now if these were just standard HTML links there would be no problem as Selenium is smart enough to tell that there's a new page coming and to wait to do things. But as good as it is, Selenium can't tell that the clicks in this instance are leading to new pages to load so it doesn't wait and just keeps going. As such it doesn't wait for the new page, tries to find elements which aren't there and my tests all fail. Bummer.
As a temporary solution I'm just pausing the program for three seconds like so:
oldPageDriver.clickThatButton();
try {
Thread.sleep(3000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
newPageDriver = new NewPageDriver(driver);
newPageDriver.doStuffOnNewPage();
And this works, sort of. I don't like it because it's "hacky," and just interrupting the program instead of doing something smarter. Because the delay is hard coded at three seconds I get failures if the link is working but just slow. I've considered something like an implicit wait but that accomplishes the same thing and I've not found a solid, workable answer in Java anywhere after a considerable amount of looking.
So, can anyone suggest a way around this? Specifically, how to make Selenium know that a new page is expected and to wait until it's available?
The wait for the document.ready event is not the entire fix to this problem, because this code is still in a race condition: Sometimes this code is fired before the click event is processed so this directly returns, since the browser hasn't started loading the new page yet.
After some searching I found a post on Obay the testing goat, which has a solution for this problem. The c# code for that solution is something like this:
IWebElement page = null;
...
public void WaitForPageLoad()
{
if (page != null)
{
var waitForCurrentPageToStale = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForCurrentPageToStale.Until(ExpectedConditions.StalenessOf(page));
}
var waitForDocumentReady = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForDocumentReady.Until((wdriver) => (driver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));
page = driver.FindElement(By.TagName("html"));
}
`
I fire this method directly after the driver.navigate.gotourl, so that it gets a reference of the page as soon as possible. Have fun with it!
Explicit waits are what you need;
http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp
You can directly add this to your test or you may want to DRY it up, especially if there is a common wait expectation such as the disappearance of a spinning icon.
You could extend the click method to always wait after clicking or if following page objects, add a wait_until_loaded method to a base page class. There many other valid approaches but dependent on how the AUT is implemented
Simple ready2use snippet, working perfectly for me
static void waitForPageLoad(WebDriver wdriver) {
WebDriverWait wait = new WebDriverWait(wdriver, 60);
Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {
#Override
public boolean apply(WebDriver input) {
return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
}
};
wait.until(pageLoaded);
}
I have to click on a tile which is generated after mouse hovering. I wrote the code below but it is still not working.
WebElement FrontElement=driver.findElement(By.xpath("//a[#class='sol-itm-bx relative front-app-nm']/span[text()='UI Auto Test12345']"));
WebElement BackElement= driver.findElement(By.xpath("//a[#class='relative back-app-desc']/span[text()='UI Auto Test12345']"));
Actions builder = new Actions(driver);
builder.moveToElement(FrontElement);
builder.perform();
builder.clickAndHold(FrontElement);
BackElement.click();
To use the Actions() class you need to chain the actions together. Separate commands won't work in the way you want.
Actions builder = new Actions(driver);
builder.moveToElement(driver.findElement(By.xpath("//a[#class='sol-itm-bx relative front-app-nm']/span[text()='UI Auto Test12345']")))
.moveToElement(driver.findElement(By.xpath("//a[#class='relative back-app-desc']/span[text()='UI Auto Test12345']")))
.click().perform();
Note: I've separated the lines for ease of reading.
EDIT: 'build' to 'builder' NullPointerException