angular / protractor

E2E test framework for Angular apps
http://www.protractortest.org
MIT License
8.75k stars 2.31k forks source link

Switched to Chrome window does not get focus [switchTo().window(handle)] - Protractor 3/Webdriver 2.53 case #3124

Open latobibor opened 8 years ago

latobibor commented 8 years ago

Hi all!

I have a similar problem to this: https://github.com/angular/protractor/issues/55 - though the difference is the expectations working fine, no errors, no exceptions, but it does not switch back to the previous window. I am at my wits end. I tried first with tabs, it did not work, so I switched to windows since them being tabs and not windows is not part of any of our test cases.

How to reproduce it: http://stackoverflow.com/questions/36578927/protractor-3-0-0-webdriver-2-53-0-switching-tabs-error

it('checks tabs', async () => {
    const url1 = '/login';
    const url2 = config.chatLaunchUrl;

    let windowHandles = {
      oldTab: '',
      newTab: ''
    };

    await browser.get(url1);
    await browser.getWindowHandle().then(handle => {
      windowHandles.oldTab = handle;
    });

    // opening new window sending CTRL+N
    await browser.actions()
      .sendKeys(protractor.Key.chord(protractor.Key.CONTROL, "n"))
      .perform();

    await browser.getAllWindowHandles()
      .then(handles => {
        expect(handles[0]).toEqual(windowHandles.oldTab);

        windowHandles.newTab = handles[1];
        return browser.driver.switchTo().window(windowHandles.newTab);
      })
      .then(() => {
        // this works
        return browser.get(url2);
      })
      .then(() => {
        return browser.driver.switchTo()
          .window(windowHandles.oldTab)
          .then(() => browser.driver.executeScript('window.focus();'));
      })
      .then(() => {
        let handle = browser.driver.getWindowHandle();
        expect(handle).toEqual(windowHandles.oldTab);
      })
      .then(() => browser.sleep(6000));
  });

I have added a sleep to make sure you can see it did not switch. (At least UI is not moved to forward, doesn't get the focus).

Works with FireFox but not with Chrome. Expectations are all verified in both browsers, though Chrome does not switch, while FireFox does. I tried out the window.focus() script trick, but it did not switch. On FireFox you don't even need that trick to make it work.


latobibor commented 8 years ago

I will revisit this issue a bit later (I have a deadline today) since I have found a workaround that uses windows instead of tabs. Though I think in case of tabs, it should be better if the actual switch and focus have been done and the actual handle would be consistent with it.

latobibor commented 8 years ago

Since then I have found out that the actual switch happens and the test can continue in Chrome as well. The difference between the FireFox and the Chrome is that if I switch to a Firefox window it gets the focus (moves up in the z order), but Chrome does not and it was hard to see what does it do when the view was blocked by the previous window (from where I was switching form).

jsolmosi commented 8 years ago

I got same problem. It makes my tests fail in Chrome because of opening more browser instances.

Akta3d commented 8 years ago

Same problem here. And I need to open new tab on chrome. I need test multi browser and multi tab.

latobibor commented 8 years ago

I have written these snippets to help with handling browsers. (Then we substituted multibrowser with one of the participant using API). I hope it helps, this is just a draft. It returns an object you can use to handle the browsers naturally. (Sorry for ES7 but ES5 is just pain in the ass).

    let windowHandle;

    async function openNewWindow() {
      // opening new window sending CTRL+N
      await browser.actions()
        .sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'n'))
        .perform();
      let newHandles = await browser.getAllWindowHandles();   // eslint-disable-line prefer-const
      windowHandle = newHandles[newHandles.length - 1];
      return browser.driver.switchTo().window(windowHandle);
    }

    // etc. etc. ...
    const handle = await browser.driver.getWindowHandle();
    return {
      switchTo: async () => {
        return await browser.driver.switchTo().window(handle);
      },
      getHandle: () => handle,
      close: async () => {
        await browser.driver.switchTo().window(handle);
        return await browser.driver.close();
      }
    };