How to switch between current opened tab to a new tab opened after clicking on a button, using dotnetbrowser? Is it possible?
I'm trying to download a PDF file from a page, that is displayed on a new tab after clicking on a button on the home page. However, all my attempts to retrieve the PDF failed (I've already added the CustomPluginFilter).
EDIT:
Here is the code I use, after getting the page containing the PDF button (after clicking it, a new tab is opened displaying the content of the pdf)
public class CustomPluginFilter : PluginFilter
{
public bool IsPluginAllowed (PluginInfo pluginInfo)
{
if (pluginInfo.MimeTypes.Contains("application/pdf"))
{
return false;
}
return pluginInfo.MimeTypes.Contains("application/pdf");
}
}
DotNetBrowser.BrowserContextParams parameters = new DotNetBrowser.BrowserContextParams(directory);
DotNetBrowser.BrowserContext context = new DotNetBrowser.BrowserContext(parameters);
Browser browser = DotNetBrowser.BrowserFactory.Create(context);
this is where I make the requests to get the page with the button, it is working until here. Next is the steps to get the PDF
browser.PluginManager.PluginFilter = new CustomPluginFilter();
SampleDownloadHandler downloadHandler = new SampleDownloadHandler();
browser.DownloadHandler = downloadHandler;
DOMDocument document = browser.GetDocument();
XPathResult xpath = document.Evaluate(".//table[contains(#id, \"formulario:tabelaIE\")]//tr//a", XPathResultType.FIRST_ORDERED_NODE_TYPE);
DOMElement element = xpath.SingleNode as DOMElement;
element.Click();
Related
I opened a new tab by clicking something in selenium in c #. I want to scroll after changing to a new tab, but I get a timeout error.
I get a timeout message and no scroll.
this is c# code.
Used Chrome 79
Chrome option is
options.AddArguments("handlesAlerts=false");
options.AddArguments("--disable-infobars");
options.AddArguments("--no-sandbox");
options.AddArguments("--disable-background-networking");
options.AddArguments("--disable-component-extensions-with-background-pages");
options.AddArguments("--dns-prefetch-disable");
options.AddArguments("--ignore-certificate-errors");
options.AddArguments("--ignore-certificate-errors-spki-list");
options.AddArguments("--ignore-ssl-errors");
options.AddArguments("--allow-running-insecure-content");
options.AddArguments("lang=ko_KR");
if (this.driver.WindowHandles.Count > 1)
{
this.driver.SwitchTo().Window(this.driver.WindowHandles[1]);
}
Utils.sleep(3000);
((IJavaScriptExecutor)this.driver).ExecuteScript("window.scrollBy(0,500);");
you can do this by two steps,
move to the new tab and do the scroll there.
ArrayList<String> AllTabs = new ArrayList<String> (driver.getWindowHandles());
driver.switchTo().window(AllTabs.get(1));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0 , window.innerHeight)");
And you can close the tab after you finish.
Please use the below code it will work fine
//Open link in new tab
Actions act = new Actions(driver);
act.KeyDown(Keys.Control).MoveToElement(elementToopenInNewTab).Click().Perform();
// Switch to new tab
driver.SwitchTo().Window(driver.WindowHandles.Last());
//Scroll down in new tab
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight)");
//Move to first tab again
driver.SwitchTo().Window(driver.WindowHandles.First());
So, i am trying to use Selenium to scrape this webpage that updates every couple seconds. I am looking to click on the most recent link which, in this case, is the link by Edward Researcher. This list will update multiple times and get updated with new links stacking at the top.
My current code basically takes the top most link of the entire page when I want it to take links that are shown on the page starting from the top
allLinks = driver.FindElements(By.XPath("/html/body/div[6]//a")).ToHashSet();
This will get all the clickable links going top down using a tags to grab the links. My problem is trying to only get links from one place on the webpage and grab that link everytime it updates. Not really sure how to do that since the code and xPath changes with every added link. Any help would be greatly appreciated
The bottom most mark in red is the current link that I inspected that is topmost but when the page gets updated with new Links the two top red marks are where they will be updated in another DIV.
The Code that I have a t the moment works to grab the first link on the page but I would prefer to start at the Logged hits section as shown in the first image. Here is the code that makes it work:
public static void searchAllLinks()
{
//HitForker is labelled as '0'
//PandaCrazy tab is labellled as '1'
//Start index at 1
int listIndex = 1;
//Different numbers need for the first run down the list
bool firstRun = true;
//HashSet to store all IWebElements found on page at runtime
HashSet<IWebElement> allLinks;
//Get browser tabs open at current time
var browserTabs = driver.WindowHandles;
//Switch to HF
driver.SwitchTo().Window(driver.WindowHandles[0]);
//Grab links from page starting at Logged Hits Most recent Div
allLinks = driver.FindElements(By.XPath("/html/body/div[6]//a")).ToHashSet();
//Loop through all links in hash
//Hashset contains every link on the page. Only need the middle link to access the content
foreach(IWebElement value in allLinks)
{
if(firstRun == true)
{
//Second link in the hash
if(listIndex == 2)
{
value.Click();
firstRun = false;
listIndex = 0;
whatToClick(value);
}
}
//When linkIndex is 5 then click the value and reset to 0
if(listIndex == 5)
{
value.Click();
whatToClick(value);
listIndex = 0;
}
listIndex++;
}
}
//Method to find which webpage opened on successfull click
public static void whatToClick(IWebElement currentLink)
{
//Grabs the browser handles open
var browserTabs = driver.WindowHandles;
//When the link is clicked on switch to that tab
driver.SwitchTo().Window(driver.WindowHandles[2]);
//2 options
//Hit is not available then add to PC
//Hit is available then accept
try
{
if (driver.FindElement(By.XPath("/html/body/div[3]/div[2]/div/div/div/div[2]/p/span/span/button[2]")).Displayed == true)
{
driver.FindElement(By.XPath("/html/body/div[3]/div[2]/div/div/div/div[2]/p/span/span/button[2]")).Click();
driver.Close();
}
else
{
driver.Close();
driver.SwitchTo().Window(driver.WindowHandles[0]);
}
//Switch Back to the HF
driver.SwitchTo().Window(driver.WindowHandles[0]);
//Catch exception to catch if the hit cannot be accepted
} catch (OpenQA.Selenium.NoSuchElementException e )
{
if (driver.FindElement(By.XPath("/html/body/div[2]/div[1]/nav/div/div[1]/div/div[3]/span/span/button")).Displayed == true)
{
driver.FindElement(By.XPath("/html/body/div[2]/div[1]/nav/div/div[1]/div/div[3]/span/span/button")).Click();
driver.Close();
}
driver.SwitchTo().Window(driver.WindowHandles[0]);
}
catch (OpenQA.Selenium.NoSuchWindowException w)
{
Console.WriteLine("Window Not open");
}
}
Please click the element using relative xpath as follows
driver.FindElement(By.Xpath("//div[#id='log_table']/div[0]/div/div[1]/span[1]//a")).Click()
The above xpath will focus on the first of the table and accesses the hyperlink of that.
I'm newbie in C# and specially in Selenium. The code I'm providing works as intended, but I would like to add to it. Basically how to use Selenium to log into Linkedin, search for CURRENT EMPLOYEES of a company (Walmart for this example) and scrape the links for "send inmail" for every user.... clicking the "next" button on every page until there are no more. The following will open linkedin, login, enter walmart into searchbox, then click the next button.
I would like to write the links found within all the Send InMail buttons to a text file. Inspecting one of the Send InMail buttons gives the following:
<a class="primary-action-button label" href="/requestList?displayProposal=&destID=262919732&creationType=DC&authToken=BrmS&authType=name&trk=vsrp_people_res_pri_act&* amp;trkInfo=VSRPsearchId%3A5225861601486589992400%2CVSRPtargetId%3A262919732%2CVSRPcmpt%3Aprimary">Send InMail</a>
I would like to write all of these links into a text file as it cycles through all the "next" buttons. Also, I would like to know how to select a value from a drop down list that I haven't been able to "inspect" ... When you type "Walmart" or whatever into the search box, a drop-down gives you the option of selecting "people that currently work at walmart", etc. I haven't even been able to inspect that option in developer mode for some reason.
I've updated my code... This now SEEMS to WANT to do what i need...but there seems to be a timing issue where the "next" button might be loading before the "Send InMail" buttons...it will print a few results to the console and clicks next a few times, but then seems to melt down:
// Go to the home page
driver.Navigate().GoToUrl("https://www.linkedin.com");
// Get User Name field, Password field and Login Button
var userNameField = driver.FindElementById("login-email");
var userPasswordField = driver.FindElementById("login-password");
var loginButton = driver.FindElementByXPath("//input[#value='Sign in']");
// Type user name and password
userNameField.SendKeys("me#hotmail.com");
userPasswordField.SendKeys("Password123");
// and click the login button
loginButton.Click();
// perform search
var newSearch = driver.FindElementById("main-search-box");
var searchButton = driver.FindElementByName("search");
// search
newSearch.SendKeys("walmart");
searchButton.Click();
// Get all links from Send InMail buttons
List<IWebElement> elementList = new List<IWebElement>();
elementList.AddRange(driver.FindElements(By.LinkText("Next >")));
if (elementList.Count > 0)
{
foreach(IWebElement item in driver.FindElements(By.LinkText("Send InMail")))
{
Console.WriteLine(item.GetAttribute("href"));
var goForward = driver.FindElementByLinkText("Next >");
goForward.Click();
}
}
Console.ReadLine();
As far as I understand, after you perform search, there will be a search results which will be populated in the list like the ones in the figure attached.
screenshot of the Linkedin search result.
Then iterate through the results using similar method (code sample here is in Java, might be similar in C#)
List<WebElements> results_div = driver.findElemnts(By.xpath("//*[#id="results"]")) // where xpath of the <ul> element
int counter = 2 // because the data starts from id = 2. Refer image.
while(counter <= results_div)
{
WebElement element = driver.findElements(By.xpath("//*[#data-li-position=\"+counter+\"])) //xpath of the <li> element
String anchor_text = element.findElement(By.linkText("Send InMail")).getAtribute("href")
//Write a logic to save the data to a text file
}
Iterate the above until all the results are reached!
Hope it helps.
Edit : Try this, its not a working code! But try it on these grounds. It might help.
#Test(description = "Search the Site with some predefined words after Login and print the href attribute")
public void printUserID()
{
StartPage startPage = new StartPage(driver);
HomePage homePage = startPage.loginIntoAccount(LinkdinAccount.linkedEmail,LinkdinAccount.linkedPassword); // Logs in in to the account
driver.findElement(By.xpath("//*[#id=\"main-search-box\"]")).sendKeys("herbalife");
driver.findElement(By.xpath("//*[#id=\"global-search\"]/fieldset/button")).click();
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.xpath("//*[#id=\"results\"]"))));
List<WebElement> results_div = driver.findElements(By.xpath("//*[#id=\"results\"]/li")); // where xpath of the <ul> element
System.out.println(results_div.size()); //*[#id="results"]
#driver.findElement(By.xpath("//*[#id=\"results-pagination\"]/ul/li[11]/a")).click();
int count = 1;
wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.xpath("//*[#id=\"results\"]"))));
while(driver.findElement(By.xpath("//*[#id=\"results-pagination\"]/ul/li[11]/a")).isDisplayed())
{
while(count <= results_div.size())
{
WebElement element = driver.findElement(By.xpath("//*[#data-li-position=\"" + count + "\"]"));
if(element.findElements(By.linkText("Send Inmail")).size() > 0)
{
String anchor_text = element.findElement(By.linkText("Send InMail")).getAttribute("href");
System.out.println(anchor_text);
}
count ++;
}
//for clicking the next button
driver.findElement(By.xpath("//*[#id=\"results-pagination\"]/ul/li[11]/a")).click()
}
Trying to write some test cases using selenium webdriver in c# and have a scenario which i'm unsure of how to resolve
user scenario is searching a table for a patient, select a patient then a new window opens and then assert various items on the window
my issue is i'm unable to select the new window to assert anything from, it's not a pop-up window, it's a full new browser window but it has no window title/name to identify it by, how would I be able to switch driver focus to this window?
thanks in advance
It is really easy in Selenium WebDriver. By using SwitchTo method
driver.SwitchTo().Window(driver.WindowHandles.Last());
See this blog post as well
http://binaryclips.com/2015/03/13/selenium-webdriver-in-c-switch-to-new-window/
This code worked for me. In my case the new window/tab is a PDF that have some weight, so I make some custom waits while it loads.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
int previousWinCount = driver.WindowHandles.Count;
// Perform the action to open a new Window
wait.Until(driver => driver.WindowHandles.Count == (previousWinCount + 1));
driver.SwitchTo().Window(driver.WindowHandles.Last());
wait.Until(driver => driver.Url.Contains("desired_url_or_a_substring_of_it"));
Note that the driver.Url when the PDF is loading is "about:blank".
IWebDriver _driver = new FirefoxDriver();
_driver.Navigate().GoToUrl("https://www.google.com");
ReadOnlyCollection<string> WindowHandles = _driver.WindowHandles;
foreach (string item in WindowHandles)
{
_driver.SwitchTo().Window(item);
string browserTitle = _driver.Title;
string browserPageSource = _driver.PageSource;
string browserURL = _driver.Url;
}
Use ReadOnlyCollection and handle browser, get the title of your window and compare and get focus on your desire browser window.
If I gather correctly your application will produce the window on it's own without further userintervention. You should be able to wait for the page to load and then you can call your asserts as normal.
Selenium already has your browser-session, so a new window is not an issue for selenium, it is just new content.
foreach (string defwindow in driver.WindowHandles)
{
driver.SwitchTo().Window(defwindow);
if(driver.Title == "")
{
selenium.WindowFocus();
selenium.SelectWindow("");
}
}
"" - indicates your window Title
I've got some code you might like. The quickest solution is to use Popup Finder, but I've made my own method as well. I would never rely on the order the Window Handles are in to select the appropriate window.
Popup Window Finder:
PopupWindowFinder finder = new PopupWindowFinder(driver);
driver.SwitchTo().Window(newWin);
My Custom method. Basically you pass it the element you want to click, your webdriver, and optionally the time to wait before searching after you click the element.
It takes all of your current handles and makes a list. It uses that list to eliminate the previously existing windows from accidentally getting switched to. Then it clicks the element that launches the new window. There should always be some sort of a delay after the click, as nothing happens instantly. And then it makes a new list and compares that against the old one until it finds a new window or the loop expires. If it fails to find a new window it returns null, so if you have an iffy webelement that doesn't always work, you can do a null check to see if the switch worked.
public static string ClickAndSwitchWindow(IWebElement elementToBeClicked,
IWebDriver driver, int timer = 2000)
{
System.Collections.Generic.List<string> previousHandles = new
System.Collections.Generic.List<string>();
System.Collections.Generic.List<string> currentHandles = new
System.Collections.Generic.List<string>();
previousHandles.AddRange(driver.WindowHandles);
elementToBeClicked.Click();
Thread.Sleep(timer);
for (int i = 0; i < 20; i++)
{
currentHandles.Clear();
currentHandles.AddRange(driver.WindowHandles);
foreach (string s in previousHandles)
{
currentHandles.RemoveAll(p => p == s);
}
if (currentHandles.Count == 1)
{
driver.SwitchTo().Window(currentHandles[0]);
Thread.Sleep(100);
return currentHandles[0];
}
else
{
Thread.Sleep(500);
}
}
return null;
}
I'm trying to test file download with Watin 2.1.0 against IE9. I used the suggested code from the accepted answer to the question Downloading a file with Watin in IE9, like this:
var downloadHandler = new FileDownloadHandler(fname);
WebBrowser.Current.AddDialogHandler(downloadHandler);
link.ClickNoWait();
downloadHandler.WaitUntilFileDownloadDialogIsHandled(15);
downloadHandler.WaitUntilDownloadCompleted(200);
However, the downloadHandler.WaitUntilFileDownloadDialogIsHandled(15) call times out. What should I do?
File download dialog doesn't work in IE9 (Windows7) NetFramework 4.0.
Following code snippet might help you resolve the issue:
First you must add references UIAutomationClient and UIAutomationTypes to your test project.
After In Ie9 Tools -> View Downloads -> Options define path to your save folder.
The next method extends Browser class
public static void DownloadIEFile(this Browser browser)
{
// see information here (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515(v=vs.85).aspx)
Window windowMain = new Window(WatiN.Core.Native.Windows.NativeMethods.GetWindow(browser.hWnd, 5));
System.Windows.Automation.TreeWalker trw = new System.Windows.Automation.TreeWalker(System.Windows.Automation.Condition.TrueCondition);
System.Windows.Automation.AutomationElement mainWindow = trw.GetParent(System.Windows.Automation.AutomationElement.FromHandle(browser.hWnd));
Window windowDialog = new Window(WatiN.Core.Native.Windows.NativeMethods.GetWindow(windowMain.Hwnd, 5));
// if doesn't work try to increase sleep interval or write your own waitUntill method
Thread.Sleep(1000);
windowDialog.SetActivate();
System.Windows.Automation.AutomationElementCollection amc = System.Windows.Automation.AutomationElement.FromHandle(windowDialog.Hwnd).FindAll(System.Windows.Automation.TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
foreach (System.Windows.Automation.AutomationElement element in amc)
{
// You can use "Save ", "Open", ''Cancel', or "Close" to find necessary button Or write your own enum
if (element.Current.Name.Equals("Save"))
{
// if doesn't work try to increase sleep interval or write your own waitUntil method
// WaitUntilButtonExsist(element,100);
Thread.Sleep(1000);
System.Windows.Automation.AutomationPattern[] pats = element.GetSupportedPatterns();
// replace this foreach if you need 'Save as' with code bellow
foreach (System.Windows.Automation.AutomationPattern pat in pats)
{
// '10000' button click event id
if (pat.Id == 10000)
{
System.Windows.Automation.InvokePattern click = (System.Windows.Automation.InvokePattern)element.GetCurrentPattern(pat);
click.Invoke();
}
}
}
}
}
if you want click 'Save As' replace foreach code with this
System.Windows.Automation.AutomationElementCollection bmc = element.FindAll(System.Windows.Automation.TreeScope.Children, System.Windows.Automation.Automation.ControlViewCondition);
System.Windows.Automation.InvokePattern click1 = (System.Windows.Automation.InvokePattern)bmc[0].GetCurrentPattern(System.Windows.Automation.AutomationPattern.LookupById(10000));
click1.Invoke();
Thread.Sleep(10000);
System.Windows.Automation.AutomationElementCollection main = mainWindow.FindAll(System.Windows.Automation.TreeScope.Children
,System.Windows.Automation.Condition.TrueCondition);
foreach (System.Windows.Automation.AutomationElement el in main)
{
if (el.Current.LocalizedControlType == "menu")
{
// first array element 'Save', second array element 'Save as', third second array element 'Save and open'
System.Windows.Automation.InvokePattern clickMenu = (System.Windows.Automation.InvokePattern)
el.FindAll(System.Windows.Automation.TreeScope.Children, System.Windows.Automation.Condition.TrueCondition) [1].GetCurrentPattern(System.Windows.Automation.AutomationPattern.LookupById(10000));
clickMenu.Invoke();
//add ControlSaveDialog(mainWindow, filename) here if needed
break;
}
}
Edit:
Also if you need to automate the save as dialog specifying a path and clicking save you can do it by adding this code just before break;
private static void ControlSaveDialog(System.Windows.Automation.AutomationElement mainWindow, string path)
{
//obtain the save as dialog
var saveAsDialog = mainWindow
.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.NameProperty, "Save As"));
//get the file name box
var saveAsText = saveAsDialog
.FindFirst(TreeScope.Descendants,
new AndCondition(
new PropertyCondition(AutomationElement.NameProperty, "File name:"),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)))
.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
//fill the filename box
saveAsText.SetValue(path);
Thread.Sleep(1000);
//find the save button
var saveButton =
saveAsDialog.FindFirst(TreeScope.Descendants,
new AndCondition(
new PropertyCondition(AutomationElement.NameProperty, "Save"),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button)));
//invoke the button
var pattern = saveButton.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
pattern.Invoke();
}
IE9 no longer uses a dialog window for saving files. Instead, it uses the notification bar to prevent focus from being removed from the web site. See http://msdn.microsoft.com/en-us/ie/ff959805.aspx under "Download Manager" for reference.
Unfortunately, this means that the current FileDownloadHandler in WatiN will not work. It instantiates a "DialogWatcher" class per browser instance that is a basic message pump for any kind of child window. When child windows are encountered, the DialogWatcher checks to see if the window is specifically a dialog (which the notification bar is not). If it is a dialog, it then iterates over the registered IDialogHandler instances calling "CanHandleDialog." Even if the notification bar were a dialog, it is of a different Window Style (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx), which is how WatiN detects the type of dialog.
From what I can see, there is no support yet for detecting the IE 9 notification bar and its prompts in WatiN. Until that support is added, you will not be able to automate downloading files in IE9.