Amit Pe'er
Amit Pe'er

Reputation: 193

Selenium: Opening an extension's popup window

I'm trying to write E2E tests for my extension using Selenium. For my tests, I need to have the extension's pop-up page open - as if the user clicked on the extension's logo (on the bottom right corner of the browser).

I already managed to init the ChromeDriver with the extension, by using:

ChromeOptions options = new ChromeOptions();
options.addExtensions(new File("...\\dist.crx"));

This way the browser (web-driver) is opened with it installed as required. But the thing is, I somehow need to open the popup page.

So I thought of a nice solution that unfortunately didn't work: I set up a keyboard shortcut to open the extension (using Google's Command API). The problem is - it works only manually.

Manually the shortcut I chose (Ctrl + Shift + Y) opens the extension as required. But when using Selenium to send these keys to the browser, nothing happens*:

Actions actions = new Actions(webDriver);
actions.sendKeys(Keys.chord(Keys.CONTROL, Keys.SHIFT, "Y")).perform();

So having this not working, I used Java's Robot to click on the extension's icon, by giving it x,y offset coordinates. This solution is working, but it's very ugly and not good since it will not click properly on a different screen. I'm trying to find a global solution which would run on all screen sizes.

Thanks in advance.

*other actions are working well for me when I send keys this way (for example Control + A to mark all) - So I'm guessing the problem is not with the way I'm sending keys.

Clarification: I want to test the interaction between my pop-up page (and background script) with the DOM itself (content script). That means I need to have both the popup page open, do some actions on it, and then make assertions on the "real" DOM of a web page. So opening only the popup page on full screen is not giving me the ability to write all the E2E tests I want.

Upvotes: 6

Views: 6768

Answers (2)

MivaScott
MivaScott

Reputation: 1806

The way I have gotten around this is to open the page directly.

In other words, all the pages in a Chrome extension are just HTML pages built into the package. As such you can open them directly with a specially crafted URL.

The first step is to find out your package ID. It is a unique 32-character string. This value is derived from the key used to sign the package so it should be fairly consistent. The quickest way to find this value is:

  1. Open Chrome with your extension installed
  2. Go to the Extension list (Menu > More Tools > Extensions)
  3. At the top make sure the "Developer mode" checkbox is checked
  4. Find your extension in the list and there will be a entry called "ID:"
  5. Copy down this value

As an example, the app launcher for Drive is "ID: lmjegmlicamnimmfhcmpkclmigmmcbeh"

Knowing this value means you can now access any page within the package.

String EXTENSION_PROTOCOL = "chrome-extension";
String EXTENSION_ID = "lmjegmlicamnimmfhcmpkclmigmmcbeh";
indexPage = EXTENSION_PROTOCOL + "://" + EXTENSION_ID + "/index.html";
optionsPage = EXTENSION_PROTOCOL + "://" + EXTENSION_ID + "/options.html"; 
popupPage = EXTENSION_PROTOCOL + "://" + EXTENSION_ID + "/popup.html";

driver.get(indexPage);

There are a few drawbacks to this:

  • It doesn't test the button itself
  • The pages are always rendered full-screen so you may get some layout issues

If you can work around those, you can at least test a majority of the functionality of a Chrome extension.

Upvotes: 4

Amit Pe'er
Amit Pe'er

Reputation: 193

OK, I managed to get this working. I used Java's Robot to send the required keys I set to open the extension (Control + Shift + Y), and it works, the popup opens. sendKeys didn't work because Selenium disabled the ability to send keys that trigger the browser's functionality, so it's a nice hack I guess.

import java.awt.*;
import java.awt.event.KeyEvent;

private void openExtension() throws AWTException {
    Robot robot = new Robot();

    robot.keyPress(KeyEvent.VK_CONTROL);
    robot.keyPress(KeyEvent.VK_SHIFT);
    robot.keyPress(KeyEvent.VK_Y);
}

Edit: And of course, it would be a good idea to release these keys after pressing (else they would remain pressed). So the final solution would look something like:

    public void openExtension() {
    robotKeyPress(KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT, KeyEvent.VK_Y);
    robotKeyRelease(KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT, KeyEvent.VK_Y);
}

private void robotKeyPress(int... keys) {
    for (int k : keys) {
        robot.keyPress(k);
    }
}

private void robotKeyRelease(int... keys) {
    for (int k : keys) {
        robot.keyRelease(k);
    }
}

Upvotes: 2

Related Questions