15

I use WebDriver with Chrome Driver 2.35 with Selenium.

I have a dual monitor setup in which I run my test cases. I do run my cases headlessly most of the times but sometimes, when I want to debug, I run it with the browser.

The window opens, I drag it to my second monitor and continue working with other stuff in my primary monitor. But whenever there is an action in the secondary Chrome Selenium screen, the focus shifts to that window and I lose control.

This is really annoying, has anyone else faced this issue? Any solutions?

whydoieven
  • 589
  • 2
  • 7
  • 21
  • 1
    Maybe that's a Chrome specialty, because I use Firefox and it only steals the focus when it starts at the begin of the test, but otherwise works nicely in the background. Can you try with Firefox just to see if it's browser dependent? – AlvaHenrik Feb 28 '18 at 16:52
  • Yes, it is indeed a problem with the browser. Firefox works just fine. But, still bummed out that it won't work that way in Chrome. – whydoieven Mar 01 '18 at 09:34
  • I have the same problem on some computers. It started with ChromeDriver 2.29, so ChromeDriver 2.28 also works fine. – Sosian Mar 13 '18 at 16:01

4 Answers4

2

Selenium chromedriver does steal the focus only once at startup. Afterwards you can run the browser in the background without any problems (we're doing it that way, using chromedriver 2.30, so I'm sure it works)

Therefore you probably have some code in your web tests which performs the focus stealing:

1) Changing the active window or opening a new window / new tab causes focus stealing.

2) You explicitly call Focus() on an element.

Are you sure your code is free of such calls?

D.R.
  • 20,268
  • 21
  • 102
  • 205
  • In our case we are sure, as the code runs fine on other machines. Only some of them are affected with that behaviour – Sosian Mar 14 '18 at 10:08
  • I assume you are using a portable chrome that matches the chromedriver version. In that case, have you tried to delete the profile and/or start the chromedriver in incognito mode? – D.R. Mar 14 '18 at 10:13
  • 2
    I have a case where I actually do change the active window (tab), and tried out Rescis' answer which did not solve the issue. I can indeed confirm that switching the active tab is what causes the browserwindow to steal focus. You can find my specific question here: https://stackoverflow.com/questions/49262548/selenium-chromedriver-run-in-background-but-not-headless – S. Van den Wyngaert Mar 14 '18 at 11:08
  • In my case, all the actions take place in the same window, I do not switch between Tabs or Windows. Focus steal happs for trivial functions like set and select. I use ChromeDriver 2.35 and I have a vague memory that it used to be better with older versions. On a sidenote - Chrome Headless works great! – whydoieven Mar 15 '18 at 13:10
0

I would suggest setting the window position to be always on bottom. In C#, you can do this through a class that looks like:

public static class SetWindowPosition
{
    [DllImport("user32.dll")]
    private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
    static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
    private const UInt32 SWP_NOSIZE = 0x0001;
    private const UInt32 SWP_NOMOVE = 0x0002;
    private const UInt32 SWP_NOACTIVATE = 0x0010;

    [DllImport("user32.dll")]
    private static extern bool LockSetForegroundWindow(uint uLockCode);
    private const UInt32 LSFW_LOCK = 1;

    public static void ForceWindowToStayOnBottom(Process process)
    {
        SetWindowPos(
            process.MainWindowHandle, // The handle of the browser window
            HWND_BOTTOM, // Tells it the position, in this case the bottom
            0, 0, 0, 0, // Coordinates for sizing of the window - Will be overriden by NOSIZE
            SWP_NOSIZE | // Says to keep the window its current size
            SWP_NOMOVE | // Says to keep the window in its current spot
            SWP_NOACTIVATE // Activation brings the window to the top, we don't want that
        );

        // If you don't notice this helping, it can probably be deleted.
        // It only deals with other applications and gets automatically undone on user interaction
        LockSetForegroundWindow(
            LSFW_LOCK); // Locks calls to SetForegroundWindow 
    }

    /// <returns> Returns the parent process of each process by the name of processName </returns>
    public static List<Process> GetPrimaryProcesses(string processName) =>

        Process.GetProcesses() // Gets a list of every process on computer
            .Where(process => process.ProcessName.Contains(processName) // Reduces the list to every process by the name we are looking for
                && process.MainWindowHandle != IntPtr.Zero) // Removes any process without a MainWindow (which amounts to every child process)
            .ToList();
}

called as:

SetWindowPosition.ForceWindowToStayOnBottom(
    SetWindowPosition.GetPrimaryProcesses("chrome")[0]);

where [0] is the index of the window you want to minimize (generally they get returned in the order opened).

What this does is similar to what you may have done when you set a window to be AlwaysOnTop (try opening task manager, clicking options, and then selecting Always On Top for an example), except in reverse. You should be able to call this on any process you like, including the web driver console window.

If you want further reading on how this works, these two posts (1, 2) were what I used to get it working, aswell as the MSDN documentation here.

Rescis
  • 547
  • 5
  • 19
  • I love that approach, didnt think of that. Sadly, we tried it on one of the affected computers and it didnt fix the issue. We are really puzzled about that. – Sosian Mar 14 '18 at 10:24
  • @Sosian I just spent some more time playing around with it and I noticed that there was an issue with getting the wrong window handle, so I updated it with a method called "GetPrimaryProcesses" that should deal with that. Otherwise, my only other guess as to why it isn;t working for you is that it is forcing itself to foreground, so I added the LockSetForeground method that should solve that. Otherwise, can you describe how it is not working a bit more? – Rescis Mar 14 '18 at 23:57
0

My solution to focus being stolen has always been to just use a VM or a remote computer and attach to the process remotely to do the debugging if needed.

IamBatman
  • 975
  • 12
  • 18
  • Yes, I got a dual monitor setup to avoid doing this but apparently having a remote machine or a VM could be the best possible way out. – whydoieven Mar 20 '18 at 10:50
0

Even I have faced this Issue, the solution I found was i ran my solution from the second monitor (i.e) Dragged the Eclipse to the second monitor and then Ran the test.

Vemula Dheeraj
  • 64
  • 1
  • 11