On a WebApp, I am trying to simulate a Hammer.js "press" (a long-press vs a simple 'Click') using Selenium WebDriver with ChromeDriver. Coming up empty on searches.
Something like a driver.FindElement(By.Id("elem_id")).ClickLong()?
Edit: Figures... just saw THIS - will investigate and get back..
OK - here we go. Sorry for the VB.
First for the documentation: Selenium Actions for ClickAndHold.
Imports OpenQA.Selenium
Imports OpenQA.Selenium.Chrome
Imports OpenQA.Selenium.Interactions
Dim opts = New ChromeOptions With {.BinaryLocation = "pathTo_Chrome.exe"}
Dim d As ChromeDriver = New ChromeDriver("pathTo_ChromeDriver", opts)
'... (you would probably have all the above already setup)
Sub LongPress(d As ChromeDriver, elemId As String)
Dim actions As Actions = New Actions(d)
Dim wElem As IWebElement = d.FindElement(By.Id(elemId))
actions.ClickAndHold(wElem).Perform()
actions.Release() 'releases at virtual "click" at last mouse position
End Sub
Function will be used like:
LongPress(d, "elemId")
I'm sure there are better ways to do this, but I'm off to the races again. Hope this helps.
Related
I am attempting to control two browser windows via selenium using c# and a single chromedriver. The reason being that I need to share session details accross browser windows.
The code that I have tried and failed with is below;
var options = new ChromeOptions();
options.AddArguments("chrome.switches", "--disable-extensions --disable-extensions-file-access-check --disable-extensions-http-throttling --disable-infobars --enable-automation ");
options.AddUserProfilePreference("credentials_enable_service", false);
options.AddUserProfilePreference("profile.password_manager_enabled", false);
options.PageLoadStrategy = PageLoadStrategy.Default;
ChromeDriverService service = ChromeDriverService.CreateDefaultService();
service.HideCommandPromptWindow = true;
var Driver = new ChromeDriver(service, options);
//THIS WILL OPEN A NEW WINDOW. BUT BECAUSE IT IS A NEW DRIVER DOES NOT WORK FOR SHARING SESSION DETAILS.
//var TestDriver = new ChromeDriver(service, options);
//TestDriver.Manage().Window.Maximize();
//THIS JUST OPENS UP A NEW TAB. NOT A NEW WINDOW (IT WOULD SEEM MOST DOCUMENTATION SUGGESTS THAT IT SHOULD)
IJavaScriptExecutor jscript = Driver as IJavaScriptExecutor;
jscript.ExecuteScript("window.open();", "google.com.au");
//TRY USING THE SEND KEYS TECHNIQUE. NOTHING HAPPENS
var test = Driver.FindElement(By.TagName("html"));
test.SendKeys(Keys.Control + "n");
test.SendKeys(Keys.Control + "t");
//TRY AGAIN USING THE SEND KEYS TECHNIQUE USING A DIFFERENT TAG. NOTHING HAPPENS
var blah = Driver.FindElements(By.TagName("body"));
blah[0].SendKeys(Keys.Control + "t");
//TRY USING ACTIONS. NOTHING HAPPENS
Actions action = new Actions(Driver);
action.SendKeys(OpenQA.Selenium.Keys.Control + "n");
action.Build().Perform();
I may resort to AutoIt to open a browser if I have to, but one more dependency is not what I need. Documentation everywhere around the web seems to suggest than all the options I tried above should work...I suspect it may be a chromedriver issue of some kind.
Any ideas on how to achieve my goal would be greatly appreciated
UPDATE.
Arnons answer below lead me to the solution. If you are in a similar situation the best thing to do is just open up the browser console (from developers tools) and experiment with javascript until you get what you want. Then just execute that. In the end executing the following code has worked for me.
IJavaScriptExecutor jscript = Driver as IJavaScriptExecutor;
jscript.ExecuteScript("window.open('https://www.bing.com.au','_blank','toolbar = 0, location = 0, menubar = 0')");
The other alternative was to use Autoit, which I also got working, much easier than I did figuring out the javascript. But one less dependency is best :)
UPDATE2.
Further complications arise with trying to control the window as an independent browser window. I believe any new window created from a parent window, has the same process id (at least my testing has indicated so), and for all intense and purpose is treated as a tab in the selinium driver. I therefore conclude that certain things are just not possible (for example relocating the child browser window on the screen).
Your first attempt using ExecuteJavaScript was very close, but In order for it to open a new window instead of new tab, you should add the following arguments: `"_blank", "toolbar=0,location=0,menubar=0" to it.
See this question for more details.
I should have read the question better, here is my solution. Ended up using this for selecting windows that popped up after clicking a button but should work with swapping between windows.
//---- Setup Handles ----
//Create a Handle to come back to window 1
string currentHandle = driver.CurrentWindowHandle;
//Creates a target handle for window 2
string popupWindowHandle = wait.Until<string>((d) =>
{
string foundHandle = null;
// Subtract out the list of known handles. In the case of a single
// popup, the newHandles list will only have one value.
List<string> newHandles = driver.WindowHandles.Except(originalHandles).ToList();
if (newHandles.Count > 0)
{
foundHandle = newHandles[0];
}
return foundHandle;
});
//Now you can use these next 2 lines to continuously swap
//Swaps to window 2
driver.SwitchTo().Window(popupWindowHandle);
// Do stuff here in second window
//Swap back to window 1
driver.SwitchTo().Window(currentHandle);
// Do stuff here in first window
You need to explicitly tell Selenium which tab you wish to interact with, which in this case would be;
driver.SwitchTo().Window(driver.WindowHandles.Last());
Hi I am new to Selenium Webdriver. I can successfully open a webpage and find elements on it.
In one case I have noted that there is a link on a page that becomes clickable after a while. In Firebug on the Script tab, I can see the code for the javascript that does the timer function.
But using Selenium Webdriver if I issue:
driver.PageSource
I cannot see the source code for the Javascript. Delaying for 30 seconds before requesting the source makes no difference. I have tried finding it with various By options using:
driver.FindElement
and so on, but it isnt there.
How does firebug manage to find and show the Javascript source code? Is there a way that I can coerce Selenium Webdriver to return all code referenced by the page?
Or is there a better approach?
Thanks for any advice!
EDIT---------------------
I tried the following in Firefox:
Dim Driver2 As IWebDriver = New Chrome.ChromeDriver
Driver2.Url = "http://mypage"
Dim js As IJavaScriptExecutor = TryCast(Driver2, IJavaScriptExecutor)
Dim title As String = DirectCast(js.ExecuteScript("return JSON.stringify(window)"), String)
and I got
Permission denied to access property 'toJSON'
I read that this wont work in firefox so I tried in Chrome, and got
Blocked a frame with origin "http://mypage" from accessing a
cross-origin frame
and from there no solutions because according to this its a security restriction, apparently you can't access an with Javascript
I'm starting to think Im a bit out of my depth here.
PageSource probably doesn't return an exact snapshot of the DOM & etc.
You can instead inspect javascript using driver.executeScript() but the burden of analyzing the return object may be discouraging.
Regardless - Here's a contrived example:
Object result = driver.executeScript("return JSON.stringify(window)");
System.out.println(result.toString());
I've built a Sub to interact with PowerShells on other servers within my domain. I never needed any return values of the PS console so far. As I want to control the Computer Management on my FileShare I need the list of all open file-sessions (net file) as you need the session ID to close it with net file "ID" /close.
This is the modified Sub:
Public Sub remoteMSPowershell(ByVal Script As String)
Dim shellUri As String = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell"
Dim newCred As PSCredential = DirectCast(Nothing, PSCredential)
Dim connectionInfo As WSManConnectionInfo = New WSManConnectionInfo(False, "SVR2012r2-file", 5985, "/wsman", shellUri, newCred)
Using Runspace As Runspace = RunspaceFactory.CreateRunspace(connectionInfo)
Runspace.Open()
Dim pipeline As Pipeline = Runspace.CreatePipeline(Script)
Dim results = pipeline.Invoke()
For Each outputItem As PSObject In results
Console.WriteLine(outputItem.Members("Path").Value)
Console.WriteLine(outputItem.Members("Id").Value)
Next
Console.ReadLine()
End Using
End Sub
While outputItem.BaseObject.ToString() gives you 1:1 the same output as you see on the PS console, I only need the Attributes "Path" and "Id".
If I run this Sub on commands like Get-Command, Get-Service and so on it'll form a column with the values of the specified attribute. However if I run it on net file the script fails with a NullReferenceException. The only thing that I can imagine is that .NET is only capable of filtering to members (attributes) of Cmdlets, but I didn't find any reference on that.
EDIT (24.05.16): It doesn't work for all the NET.exe - commands.. Is there another way to read the return values out or even another method to get the return values using PS or .NET?
EDIT (26.05.16): I've been working on two work-arounds.. Both seem to be a dead end though:
Unify the results from outputItem.BaseObject.ToString() and form Arrays of the "Id" and "Path" column. This won't work as the only indicator to split the rows into attributes are (blancs). You can imagine what happens if the File-Path contains a blanc..
A more clean work-around would be to query the desired attributes already in PowerShell like the answers to this SO question. However none of the given answers works for me as you can't query NET commands. See example:
its possible to get list recent item in windows like in this picture? how can i access that from vb.net?
list recent item(right click on icon bar)
http://i.stack.imgur.com/hnPtQ.png
Thanks
What you are referring to is a Jump List. You can access from within .NET starting with .NET 4. Since you want this in VB.Net check out this article
and the official documentation on msdn
Imports System.Windows.Shell
Class Application
Public Sub New()
Dim jl As New JumpList
JumpList.SetJumpList(Application.Current, jl)
Dim SaveAs As New JumpTask
SaveAs.ApplicationPath = System.Reflection.Assembly.GetExecutingAssembly.Location()
SaveAs.Title = "Save as..."
SaveAs.Arguments = "-saveas"
jl.JumpItems.Add(SaveAs)
Dim Configuration As New JumpTask
Configuration.ApplicationPath = System.Reflection.Assembly.GetExecutingAssembly.Location()
Configuration.Title = "Configuration"
Configuration.CustomCategory = "Settings"
Configuration.Arguments = "-config"
jl.JumpItems.Add(Configuration)
jl.Apply()
End Sub
Private Sub Application_Startup(ByVal sender As Object, ByVal e As System.Windows.StartupEventArgs) Handles Me.Startup
' Handle "Save As" JumpList example
If e.Args.Contains("-saveas") Then
' Fancy Code Funtime
' -- Remember, this launches as a new instance - if you don't want that, this end kills it when your done --
End
End If
' Handle "Configuration" JumpList example
If e.Args.Contains("-config") Then
' I launch a configuration window here, really up to you
' -- Remember, this launches as a new instance - if you don't want that, this end kills it when your done --
End
End If
End Sub
End Class
People claim the following VB script works for changing network adapter names. However I am having a decidedly difficult time trying to convert this to a c# appliaction that can do the same thing. The problem I seem to be facing is that calls to the NetworkInterface.Name is readonly.
Option Explicit
Const NETWORK_CONNECTIONS = &H31&
Dim sOldName= WScript.Arguments(0)
Dim sNewName= WScript.Arguments(1)
Dim objShell, objFolder, colItems, objItem
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(NETWORK_CONNECTIONS)
Set colItems = objFolder.Items
For Each objItem in colItems
If objItem.Name = sOldName Then
objItem.Name =sNewName
End If
Next
I found this which explains it a bit more: http://blogs.technet.com/b/heyscriptingguy/archive/2005/05/11/how-can-i-rename-a-local-area-connection.aspx.
Ok, so there are special folders where the NIC names are stored and you access those folders by binding to the them via the SHELL. How then do you do something like this in c#?
You can change the name of a NIC easily through the registry if you know how the registry structure works.
You will need the NetworkAdapters GUID in order to locate which path to open. To get the network adapter GUID I recommend first querying the WMI "Win32_NetworkAdapter" class. There is a GUID property along with all the other properties needed to identify specific adapters.
You will notice this GUID in the registry path: {4D36E972-E325-11CE-BFC1-08002BE10318}Visit link for information on it:
http://technet.microsoft.com/en-us/library/cc780532(v=ws.10).aspx
string fRegistryKey = string.Format(#"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{0}\Connection", NIC_GUID);
RegistryKey RegistryKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, #"\\" + Server.Name);
RegistryKey = RegistryKey.OpenSubKey(fRegistryKey, true); //true is for WriteAble.
RegistryKey.SetValue("Name", "<DesiredAdapterName>");
By design the windows UI will not allow for duplicate NIC names. However, you can force duplicate NIC names via the registry. We have done tests, there seem to be nothing critically effected by having duplicate names. Windows seems to still function fine. You just want to be wary about scripting against NIC names if you don’t incorporate anti-duplicate name logic.
To create uniqueness you can use the adapter index property associated with the WMI query.
You can use the System.Management assembly and use this class.
Follow the sample here - http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/727c8766-8189-4ad6-956d-958e52b97c05/
You can also create a VB.NET dll with the functionality you need and reference and call it from your C# code.
Here is a console app demonstrating the code (I tested and it works :)
Option Explicit On
Module Module1
Sub Main()
Const NETWORK_CONNECTIONS = &H31&
Dim sOldName = "Local Area Connection"
Dim sNewName = "Network"
Dim objShell, objFolder, colItems, objItem
objShell = CreateObject("Shell.Application")
objFolder = objShell.Namespace(NETWORK_CONNECTIONS)
colItems = objFolder.Items
For Each objItem In colItems
Console.WriteLine(objItem.Name)
If objItem.Name = sOldName Then
objItem.Name = sNewName
End If
Console.WriteLine(objItem.Name)
Next
End Sub
End Module
It prints out:
Local Area Connection
Network