I have problem with browse button and switching to file dialog. I cannot use my file path control and just send there my string with file path and file itself, as it's readonly and in fact some behind control is my input filepath.
Here's my code
driver.FindElement(By.Id("browseButton")).Click();
driver.SwitchTo().ActiveElement().SendKeys(filepath);
Above code fills my control for file path, as i can see that on UI. But my open file dialog is still opened and i do not know how to close it and submit my upload.
Uploading files in Selenium can be a pain, to say the least. The real problem comes from the fact that it does not support dialog boxes such as file upload and download.
I go over this in an answer to another question, so I will just copy/paste my answer from there here. The code examples should actually be relevant in your case, since you are using C#:
Copied from previous answer on question here:
Selenium Webdriver doesn't really support this. Interacting with non-browser windows (such as native file upload dialogs and basic auth dialogs) has been a topic of much discussion on the WebDriver discussion board, but there has been little to no progress on the subject.
I have, in the past, been able to work around this by capturing the underlying request with a tool such as Fiddler2, and then just sending the request with the specified file attached as a byte blob.
If you need cookies from an authenticated session, WebDriver.magage().getCookies() should help you in that aspect.
edit: I have code for this somewhere that worked, I'll see if I can get ahold of something that you can use.
public RosterPage UploadRosterFile(String filePath){
Face().Log("Importing Roster...");
LoginRequest login = new LoginRequest();
login.username = Prefs.EmailLogin;
login.password = Prefs.PasswordLogin;
login.rememberMe = false;
login.forward = "";
login.schoolId = "";
//Set up request data
String url = "http://www.foo.bar.com" + "/ManageRoster/UploadRoster";
String javaScript = "return $('#seasons li.selected') .attr('data-season-id');";
String seasonId = (String)((IJavaScriptExecutor)Driver().GetBaseDriver()).ExecuteScript(javaScript);
javaScript = "return Foo.Bar.data.selectedTeamId;";
String teamId = (String)((IJavaScriptExecutor)Driver().GetBaseDriver()).ExecuteScript(javaScript);
//Send Request and parse the response into the new Driver URL
MultipartForm form = new MultipartForm(url);
form.SetField("teamId", teamId);
form.SetField("seasonId", seasonId);
form.SendFile(filePath,LoginRequest.sendLoginRequest(login));
String response = form.ResponseText.ToString();
String newURL = StaticBaseTestObjs.RemoveStringSubString("http://www.foo.bar.com" + response.Split('"')[1].Split('"')[0],"amp;");
Face().Log("Navigating to URL: "+ newURL);
Driver().GoTo(new Uri(newURL));
return this;
}
Where MultiPartForm is:
MultiPartForm
And LoginRequest/Response:
LoginRequest
LoginResponse
The code above is in C#, but there are equivalent base classes in Java that will do what you need them to do to mimic this functionality.
The most important part of all of that code is the MultiPartForm.SendFile method, which is where the magic happens.
One of the many ways to do that is to remove the disable attribute and then use typical selenium SendKeys() to accomplish that
public void test(string path)
{
By byId = By.Id("removeAttribute");
const string removeAttribute = #"document.getElementById('browseButton').removeAttribute('disabled');";
((IJavaScriptExecutor)Driver).ExecuteScript(removeAttribute);
driver.FindElement(byId).Clear();
driver.FindElement(byId).SendKeys(path);
}
You can use this Auto IT Script to Handle File Upload Option.
Auto IT Script for File Upload:
AutoItSetOption("WinTitleMatchMode","2") ; set the select mode to
Do
Sleep ("1000")
until WinExists("File Upload")
WinWait("File Upload")
WinActivate("File Upload")
ControlFocus("File Upload","","Edit1")
Sleep(2000)
ControlSetText("File Upload" , "", "Edit1", $CmdLineRaw)
Sleep(2000)
ControlClick("File Upload" , "","Button1");
Build and Compile the above code and place the EXE in a path and call it when u need it.
Call this Once you click in the Browse Button.
Process p = System.Diagnostics.Process.Start(txt_Browse.Text + "\\File Upload", DocFileName);
p.WaitForExit();
Related
I'm querying the graph api using this URL:
https://graph.microsoft.com/v1.0/sites/{siteID}/drives/{driveID}/root/children
which is giving me the webURL
"https://MY DOMAIN.sharepoint.com/sites/{SITE}/{FILENAME}.url
Is there any way to get the value that the shortcut item points to, as opposed to downloading a .url file?
I think Get url address from url file answers half of my question, however, I'm unable to get the contents of the url as a File type object to be able to read through it.
I'm getting each of the quicklinks and adding them to a list via ReadAsStringAsync
public static async Task<List<QuickLinkViewModel>> GetQuickLinksAsync (dynamic quicklinksJson)
{
List<QuickLinkViewModel> quickLinks = new List<QuickLinkViewModel>();
var quickLink = quicklinksJson.value;
string title;
HttpClient client = new HttpClient();
byte[] reply;
foreach (var q in quickLink)
{
reply = await client.GetByteArrayAsync(q.webUrl);
title = q.name;
title = System.IO.Path.GetFileNameWithoutExtension(title);
quickLinks.Add(new QuickLinkViewModel
{
Title = title,
webUrl = q.webUrl
});
}
return quickLinks;
}
When I run this I'm getting the error:
The best overloaded method match for
'System.Net.Http.HttpClient.GetByteArrayAsync(string)' has some
invalid arguments
.url file is not supported to be previewed in SharePoint. So the webUrl format in the query results of Microsoft Graph is different from other files. Other files can be previewed through this webUrl. The .url file will be downloaded directly through webUrl.
You can download it and open it with the edit tool to see the value that the shortcut item points to.
The content of .url file:
[InternetShortcut]
URL={the value that the shortcut item points to}
UPDATE:
If you want to get the content of the .url file in your code, you need to call another Graph endpoint: GET /drives/{drive-id}/items/{item-id}/content. See reference here. Use client.DownloadString to read the content in C#.
Here is a simple example (Please note that I didn't implement the authorization process here, just put the Authorization herder for convenience):
In short, I need to detect a webpage's GET requests programmatically.
The long story is that my company is currently trying to write a small installer for a piece of proprietary software that installs another piece of software.
To get this other piece of software, I realize it's as simple as calling the download link through C#'s lovely WebClient class (Dir is just the Temp directory in AppData/Local):
using (WebClient client = new WebClient())
{
client.DownloadFile("[download link]", Dir.FullName + "\\setup.exe");
}
However, the page which the installer comes from does is not a direct download page. The actual download link is subject to change (our company's specific installer might be hosted on a different download server another time around).
To get around this, I realized that I can just monitor the GET requests the page makes and dynamically grab the URL from there.
So, I know I'm going to do, but I was just wondering, is there was a built-in part of the language that allows you to see what requests a page has made? Or do I have to write this functionality myself, and what would be a good starting point?
I think I'd do it like this. First download the HTML contents of the download page (the page that contains the link to download the file). Then scrape the HTML to find the download link URL. And finally, download the file from the scraped address.
using (WebClient client = new WebClient())
{
// Get the website HTML.
string html = client.DownloadString("http://[website that contains the download link]");
// Scrape the HTML to find the download URL (see below).
// Download the desired file.
client.DownloadFile(downloadLink, Dir.FullName + "\\setup.exe");
}
For scraping the download URL from the website I'd recommend using the HTML Agility Pack. See here for getting started with it.
I think you have to write your own "mediahandler", which returns a HttpResponseMessage.
e.g. with webapi2
[HttpGet]
[AllowAnonymous]
[Route("route")]
public HttpResponseMessage GetFile([FromUri] string path)
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(path, FileMode.Open, FileAccess.Read));
string fileName = Path.GetFileNameWithoutExtension(path);
string disposition = "attachment";
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(disposition) { FileName = fileName + Path.GetExtension(absolutePath) };
result.Content.Headers.ContentType = new MediaTypeHeaderValue(MimeMapping.GetMimeMapping(Path.GetExtension(path)));
return result;
}
I want to make a small application that would read a title from current opened youtube video from my firefox or chrome browser and save it in .txt file on my computer.
I need an idea on how to accomplish this. Is it somehow possible to access tabs opened in firefox or chrome via c#?
Do you understand me? I want to somehow parse the data from browser from seleceted tab and save it into .txt file.
Would I have to use greasemonkey scripts for this?
If the tab is currently active then you could do this in C#:
string browser = "Firefox"; //or change to chrome/iexplore
var browserProc = Process.GetProcessesByName(browser)
.Where(b => b.MainWindowTitle.Contains("YouTube"))
.FirstOrDefault();
if (browserProc != null)
{
string mainTitle = browserProc.MainWindowTitle;
}
You can then parse the relevant parts of mainTitle if you need to.
You could use Win32 API calls to do this. FindWindowEx, GetWindowText, etc.
http://msdn.microsoft.com/en-us/library/windows/desktop/ff468919(v=vs.85).aspx
Please be gentle. I am not a terribly proficient developer!
So this is the last thing I need to fix in my Windows Phone 7.5 app before I consider it done. In short, the data sources on the menus are driven by an xml file. That file is stored locally with the app. I would like to store that file somewhere on the Internet). Currently if I need to make a change to this xml file, I have to re-submit the app to the Marketplace taking about 5 days before the change goes live. How 2003 of me.
So I can't figure out what they are expecting returned in the code below. I've hacked away and it always give some error I don't understand.
I've set the filename variable to a URL of a file on the Internet but apparently that is not supported. So I either need a new way for that whole section to work or a way to convert the hosted filename converted into something that will work.
private static void FirstLaunch()
{
// On the first launch, just add everything from the OPML file
string filename;
//This file should really be hosted on the Internet somewhere.
filename = "/RSSReader;component/LyncNews-opml.xml";
StreamResourceInfo xml = App.GetResourceStream(new Uri(filename, UriKind.Relative));
List<RSSPage> rssPages = ParseOPML(xml.Stream);
}
You can set it to a URL, but you'll need to download the content, not through App.GetResourceStream. Try WebClient, it's easy and simple.
A simple usage:
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Client_DownloadStringCompleted);
Uri token = new Uri("your url");
client.DownloadStringAsync(token);
and handle xml parsing in the event.
I'm using selenium webdriver, C#.
Is it possible to make work webdriver with Firefox select file dialog?
Or must I use something like AutoIt?
If you are trying to select a file for upload Selenium 2 supports HTML file inputs. For example:
HTML
<input type="file" id="uploadhere" />
Selenium Code
IWebElement element = driver.FindElement(By.Id("uploadhere"));
element.SendKeys("C:\\Some_Folder\\MyFile.txt");
Basically you "type" (with SendKeys) the full file path to the file input element. Selenium handles the file selection dialog for you.
However if you want to manipulate an arbitrary file selection dialog, then like Anders said, you have to go outside of Selenium.
No, WebDriver cannot interact with dialogs - this is because dialogs are the domain of the operating system and not the webpage.
I know people that have had luck with autoit as well as the Automation API provided by .Net.
Another option would be to skip the file dialog entirely and issue a POST or a GET, but this requires more advanced knowledge of the website as well as understanding how construct a POST/GET.
You could try Webinator, it is similar to Selenium in the sense that it is powered by WebDriver. It provides file dialog capabilities and I've had great success with it.
Here is another solution using remotewebdriver, it works like magic and I loved it.
Here is the class I have:
driver.findElementByLinkText("Upload Files").click();
driver.setLogLevel(Level.ALL);
System.out.println(driver.getCurrentUrl());
WebElement element = driver.findElement(By.xpath("//input[#name='file_1']"));
LocalFileDetector detector = new LocalFileDetector();
//Now, give the file path and see the magic :)
String path = "D://test66T.txt";
File f = detector.getLocalFile(path);
((RemoteWebElement)element).setFileDetector(detector);
element.sendKeys(f.getAbsolutePath());
//now click the button to finish
driver.findElementByXPath("//html/body/div[9]/div[1]/a/span").click();
You asked for using AutoIt for the file dialog. This is easy and you can do it with C#.
Install nuget package AutoItX.Net
Use the demo code below
Change the dialog title string as you need
public static void InsertIntoFileDialog(string file, int timeout = 10)
{
int aiDialogHandle = AutoItX.WinWaitActive("Save As", "", timeout); // adjust string as you need
if (aiDialogHandle <= 0)
{
Assert.Fail("Can't find file dialog.");
}
AutoItX.Send(file);
Thread.Sleep(500);
AutoItX.Send("{ENTER}");
Thread.Sleep(500);
}
This helped me after I had trouble with Appium/Selenium related to file dialogs.
According to Nadim Saker
.Net has a library to handle file upload dialog. It has a SendKeys class that has a method SendWait(string keys). It sends the given key on the active application and waits for the message to be processed. It does not return any value.
This can be done as follows, tested and working with Internet Explorer and Chrome driver
var allowsDetection = this.Driver as IAllowsFileDetection;
if (allowsDetection != null)
{
allowsDetection.FileDetector = new LocalFileDetector();
}
Driver.FindElement(By.Id("your-upload-input")).SendKeys(#"C:\PathToYourFile");
Reference https://groups.google.com/forum/#!msg/webdriver/KxmRZ8MkM4M/45CT4ID_WjQJ
If you want to upload a file, and not use the WebDriver, the only solution I've come across is AutoIt. It allows you to write a script and convert it to an executable which you can then call from within your code. I've used it successfully while working with an ActiveX control.
Another approach is to use System.Windows.Forms.SendKeys.SendWait("pathToFile"). I use it with success everywhere where i cant just send keys to element like described by #prestomanifesto.
I used this to solve the problem... try it if all above does not works
Actions action = new Actions(driver);
action.SendKeys(pObjElement, Keys.Space).Build().Perform();
Thread.Sleep(TimeSpan.FromSeconds(2));
var dialogHWnd = FindWindow(null, "Elegir archivos para cargar"); // Here goes the title of the dialog window
var setFocus = SetForegroundWindow(dialogHWnd);
if (setFocus)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
System.Windows.Forms.SendKeys.SendWait(pFile);
System.Windows.Forms.SendKeys.SendWait("{DOWN}");
System.Windows.Forms.SendKeys.SendWait("{TAB}");
System.Windows.Forms.SendKeys.SendWait("{TAB}");
System.Windows.Forms.SendKeys.SendWait("{ENTER}");
}
Thread.Sleep(TimeSpan.FromSeconds(2));
}