I've been trying to access a new window (well tab) when using Capybara, but keep getting
Selenium::WebDriver::Error::NoSuchWindowError: no such window
My process and understanding so far is
#session_1 = Capybara::Session.new(:chrome)
#session_1.visit("www.google.com")
So at this stage i have google open. Now lets say i want to open google in a new tab/window
#session_1.open_new_window
This opens a new window, and to access those windows I can do
#session_1.windows
which returns an array of windows
[#<Window #handle="CDwindow-09B6E81E-7874-4686-86A9-8BFB917E0F4F">,
#<Window #handle="CDwindow-5DA14173-8D63-422A-BF98-39B7C2A5D2DB">]
So as a test I wanted to check that latest windows url matches about:blank
#new_tab = #session_1.windows.last
# #new_tab = #<Window #handle="CDwindow-5DA14173-8D63-422A-BF98-39B7C2A5D2DB">
page.within_window #new_tab do
expect(current_url).to eq('about:blank')
end
It's here I get the error.
What I would like to know is
1) How to select the new tab
2) how to open a new url within the new tab
So I found the answer, turns out it was a lot simpler than i was trying, credit goes to Keiran Betteley and this post
#session_1.open_new_window
#session_1.switch_to_window(#session_1.windows.last)
#session_1.visit("url")
Capybara has a number of methods for dealing with windows, and open_new_window returns the window it opened so there's no need to go looking through the list of all windows
#session1.within_window(#session_1.open_new_window) do
#sessuion1.visit("url")
... more actions performed in the new window
end
Related
edit: My issue was never quite resolved, but the answer below provided an interesting result.
The app will eventually be called by a powershell script and in this situation, I don't have the issue explained below. No additional {ENTER} is required in the PS console, so no more issue! I couldn't care less if an extra ENTER is required when my app is launched manually via cmd.exe
Problem: In a VB.NET
form app, I'm unable to get the console back to it's "default" state after the code is finished running. I need to press enter manually.
My app can also be executed from command line (in this case, no form is opened. Code is being executed automatically and output sent to console for user to see what happens)
I call AttachConsole(-1), run some code, and when everything's finished I see my latest message in console, but it's as if the process wasn't quite finished.
I have tried SendKeys.SendWait("{ENTER}"). It works well, but only when the console is the current focus. If I click outside the console while the code is running, the ENTER key is sent to whichever window I made active.
So I tried to make the console the current window:
Dim bProcess As Process = Process.GetProcessesByName("cmd").FirstOrDefault()
SetForegroundWindow(bProcess.MainWindowHandle)
// I also tried AppActivate(bProcess.Id)
SendKeys.SendWait("{ENTER}")
FreeConsole()
Nope, the ENTER key will still be sent somewhere else and not to the console. But it does make the console blink orange, so SetForegroundWindow seems to do something...
Any help will be greatly appreciated :)
EDIT
In response to #TnTinMn's answer:
FreeConsole()
// SendKeys.SendWait("test")
PieceOfCodeFromTnTinMn()
Same behavior as I've had so far: This will send the SendKeys.SendWait("~")command "outside" the console if it loses focus while the code is running.
BUT with the 2nd line above un-commented, "test" is sent outside the console and SendKeys.SendWait("~") is sent to the console, as expected.
I'm still trying to figure out what is happening here...
You can use the VB Interaction.AppActivate Method to activate the parent console prior to calling SendKeys.SendWait. This requires that you obtain the ProcessID of the console window that is the parent process of your application.
One way to do this is using Windows Management Instrumentation (WMI). The following is not pretty, but it appears to work. You would execute this after calling FreeConsole
Using currentProcess As Process = Process.GetCurrentProcess
Dim query As New SelectQuery()
Dim props As New StringCollection
props.Add("ProcessId")
props.Add("ParentProcessId")
With query
.ClassName = "Win32_Process"
.Condition = $"ProcessId={currentProcess.Id}"
.SelectedProperties = props
End With
Dim parentProcessId As Int32
Using searcher As New ManagementObjectSearcher(query)
Using mos As ManagementObjectCollection = searcher.Get
Using en As ManagementObjectCollection.ManagementObjectEnumerator = mos.GetEnumerator
If en.MoveNext() Then
parentProcessId = CInt(en.Current.Item("ParentProcessId"))
End If
End Using 'en
End Using ' mos
End Using 'searcher
If parentProcessId <> 0 Then
AppActivate(parentProcessId)
SendKeys.SendWait("~")
End If
End Using 'currentProcess
I'm implementing an invisible reCAPTCHA as per the instructions in the documentation: reCAPTCHA V2 documentation
I've managed to implement it without any problems. But, what I'd like to know is whether I can simulate being a robot for testing purposes?
Is there a way to force the reCAPTCHA to respond as if it thought I was a robot?
Thanks in advance for any assistance.
In the Dev Tools, open Settings, then Devices, add a custom device with any name and user agent equal to Googlebot/2.1.
Finally, in Device Mode, at the left of the top bar, choose the device (the default is Responsive).
You can test the captcha in https://www.google.com/recaptcha/api2/demo?invisible=true
(This is a demo of the Invisible Recaptcha. You can remove the url invisible parameter to test with the captcha button)
You can use a Chrome Plugin like Modify Headers and Add a user-agent like Googlebot/2.1 (+http://www.google.com/bot.html).
For Firefox, if you don't want to install any add-ons, you can easily manually change the user agent :
Enter about:config into the URL box and hit return;
Search for “useragent” (one word), just to check what is already there;
Create a new string (right-click somewhere in the window) titled (i.e. new
preference) “general.useragent.override”, and with string value
"Googlebot/2.1" (or any other you want to test with).
I tried this with Recaptcha v3, and it indeed returns a score of 0.1
And don't forget to remove this line from about:config when done testing !
I found this method here (it is an Apple OS article, but the Firefox method also works for Windows) : http://osxdaily.com/2013/01/16/change-user-agent-chrome-safari-firefox/
I find that if you click on the reCaptcha logo rather than the text box, it tends to fail.
This is because bots detect clickable hitboxes, and since the checkbox is an image, as well as the "I'm not a robot" text, and bots can't process images as text properly, but they CAN process clickable hitboxes, which the reCaptcha tells them to click, it just doesn't tell them where.
Click as far away from the checkbox as possible while keeping your mouse cursor in the reCaptcha. You will then most likely fail it. ( it will just bring up the thing where you have to identify the pictures).
The pictures are on there because like I said, bots can't process images and recognize things like cars.
yes it is possible to force fail a recaptcha v2 for testing purposes.
there are two ways to do that
First way :
you need to have firefox browser for that just make a simple form request
and then wait for response and after getting response click on refresh button firefox will prompt a box saying that " To display this page, Firefox must send information that will repeat any action (such as a search or order confirmation) that was performed earlier. " then click on "resend"
by doing this browser will send previous " g-recaptcha-response " key and this will fail your recaptcha.
Second way
you can make any simple post request by any application like in linux you can use curl to make post request.
just make sure that you specify all your form filed and also header for request and most important thing POST one field name as " g-recaptcha-response " and give any random value to this field
Just completing the answer of Rafael, follow how to use the plugin
None of proposed answers worked for me. I just wrote a simple Node.js script which opens a browser window with a page. ReCaptcha detects automated browser and shows the challenge. The script is below:
const puppeteer = require('puppeteer');
let testReCaptcha = async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://yourpage.com');
};
testReCaptcha();
Don't forget to install puppeteer by running npm i puppeteer and change yourpage.com to your page address
I'd like to extend my WatiN automated tests to drive a page that guards against the user accidentally leaving the page without saving changes.
The page uses the "beforeunload" technique to seek confirmation from the user:
$(window).bind('beforeunload', function (event) {
if (confirmationRequired) {
return "Sure??";
}
});
My WatIn test is driving the page using IE. I cannot find a way to get WatIn to attach to the popup dialog so I can control it from my test.
All the following have failed (where the hard-coded strings refer to strings that I can see on the popup):
Browser.AttachTo<IE>(Find.ByTitle("Windows Internet Explorer");
browser.HtmlDialog(Find.FindByTitle("Windows Internet Explorer));
browser.HtmlDialog(Find.FindByTitle("Are you sure you want to leave this page?));
browser.HtmlDialog(Find.FindFirst());
Thanks!
You'll need to create and add the dialog handler.
Example Go to example site, click link, click leave page on confirmation dialog:
IE browser = new IE();
browser.GoTo("http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/refs/onbeforeunload.htm");
WatiN.Core.DialogHandlers.ReturnDialogHandlerIe9 myHandler = new WatiN.Core.DialogHandlers.ReturnDialogHandlerIe9();
browser.AddDialogHandler(myHandler);
browser.Link(Find.ByUrl("http://www.microsoft.com")).ClickNoWait();
myHandler.WaitUntilExists();
myHandler.OKButton.Click();
browser.RemoveDialogHandler(myHandler);
The above is working on WatiN2.1, IE9, Win7. If using IE8 or before, you will likely need to use the ReturnDialogHandler object instead of the Ie9 specific handler
I need to navigate to new url from the current opened browser using Wating Code, Let me know if any one tried the same scenario. Also I need to get the url in the current opened browser.
using (IE browser = new IE())
{
browser.GoTo("www.google.co.uk");
string curentUrl = browser.Url;
}
If the browser is already open, you use the AttachTo static method
http://watinandmore.blogspot.com/2010/01/browserattachto-and-iattachto.html
HTH!
Some Background on architecture of the app is needed:
Windows 2003/Apache-v2.2/IE7/Watir-v1.6.2/Ruby-v1.8.5
Apache running under 'localsystem' account.
Request to run a Watir script comes in.
Apache CGI kicks off IE7 under a particular user, e.g. 'tester', and attaches the IE7 window to the "default" desktop environment. This allows us to VNC into the machine and see all IE7 windows from all the accounts running.
IE7 has ruby embedded into the process through plugin and executes the ruby script in a thread.
For clicking on links/buttons in IE, Watir supplies a synchronous 'click' method and async 'click_no_wait' method. 'click_no_wait' spawns a completely new ruby process to connect back to the IE7 window to click the link/button.
This is what is failing for me. Since click_no_wait is spawning a new process. It cannot seem to see the IE7 window to connect to it and click on the link/button.
I have to use 'click_no_wait' due to a dialog box that IE pops up on a certain page, so that another ruby thread can close it.
I've tried a few things:
- using fire_event('OnClick') instead of click_no_wait hangs script like 'click' would.
- Modifying 'click' by commenting out '#container.wait', but the 'click!' itself is the API that hangs waiting for the dialog box to close.
- Make 'click_no_wait' spawn a new thread instead of a process', but other threads appear to be suspended while the 'click!' call executes in that thread. Which is strange.
- Executing the 'click_no_wait' process using the exact same code that is used to spawn the IE7 process, but it still can't find any IE7 windows.
By 'default' desktop described above, the code that spawns IE basically does a series of C++ calls to attach the IE7 window to the 'winsta0' desktop:
- LogonUser() // log in as tester account
- OpenWindowStation("winsta0") // to get default desktop
- SetProcessWindowStation()
- // add the user to interactive window station using (GetUserObjectSecurity, GetSecurityDescriptorDacl, GetAclInformation, AddAce, SetSecurityDescriptorDacl, SetUserObjectSecurity)
- // add user to "default" desktop using APIs listed above.
- CreateEnvironmentBlock
- ImpersonateLoggedOnUser
- CreateProcessAsUser('iexplore.exe')
- // cleanup
Running the following Watir script under the particular user IE7 is running under yields:
$IE = Watir::IE.attach(:title, /Google/)
$IE.button(:name, 'btnG').click!
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246:in `method_missing': Windows (WIN32OLERuntimeError)
OLE error code:80040154 in
HRESULT error code:0x80020009
Exception occurred. from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246:in "each"
Which contains:
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246
shell = WIN32OLE.new("Shell.Application")
windows = shell.Windows ## Fails here
Let me know if I can supply more details or disambiguation! :)
Thanks,
Shane.
Ok, I have solved my own issue.
It turns out that the method that Watir uses to enumerate IE windows (i.e. Shell.Application) does not work across user spaces. So I had to write an intermediate application to retrieve the IWebBrowser2 COM pointer for the IE window, and modify the 'eval_in_spawned_process' Watir function to use this handle for 'pc = Watir::IE.bind(iWebBrowserPtr)'.
It's possible that I didn't need the external app to retrieve the IWebBrowser2 object, but I didn't know how to do it in Ruby, and I already had an IE BHO app that I could leverage for the purposes.
This now works fine. :)
Watir/page-container.rb:56
# This evaluates a cmd (e.g. "button(:id, 1).click!") in a new ruby process
# This is to primarily avoid a script hanging while a modal dialog is displayed in IE.
# It gets an IE handle from our IE BHO based off of window handle. It needs to do this
# to get around the problem of finding the IE window itself using Shell.Application
# which does not work across User-contexts.
# Note: This change probably invalidates the Watir unit-test for this API.
def eval_in_spawned_process(command)
command.strip!
load_path_code = _code_that_copies_readonly_array($LOAD_PATH, '$LOAD_PATH')
ruby_code = "require 'watir/ie'; "
ruby_code << 'controller = WIN32OLE.new("HttpPlugin.Controller"); '
ruby_code << "window = controller.BrowserFromHWND(#{hwnd}); "
ruby_code << "pc = Watir::IE.bind(window); "
ruby_code << "pc.#{command}; "
exec_string = "start rubyw -e #{(load_path_code + '; ' + ruby_code).inspect}"
result = system(exec_string)
end