Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extensions: Ability to click browser action buttons #2486

Open
tomholub opened this issue May 1, 2018 · 26 comments
Open

extensions: Ability to click browser action buttons #2486

tomholub opened this issue May 1, 2018 · 26 comments
Labels
chromium Issues with Puppeteer-Chromium feature upstream

Comments

@tomholub
Copy link

tomholub commented May 1, 2018

We are relying on puppeteer to automate testing of our extension. I can automate most things except I cannot click the button that our extension adds to the browser's toolbar.

Could there be an API to interact with browser action buttons?

Something to the tune of

let actionButtons = await browser.actionButtons();
await actionButtons[0].click();

would be great.

This will allow us to fully automate testing of our extension workflow. Thanks!

@aslushnikov
Copy link
Contributor

This would require some work in DevTools protocol, but should be doable. This is low-pri for us unless it proves to have high demand.

@mcpine9
Copy link

mcpine9 commented May 13, 2018

High Demand Here! High Demand!

@aslushnikov
Copy link
Contributor

@mcpine9 please upvote the issue itself - we sort by upvotes when figuring what to do next

@jorgerosal
Copy link

High demand.

@mboeser
Copy link

mboeser commented Nov 16, 2018

@aslushnikov is this still being considered? I would like to help test this feature when its in beta. If there's a workaround, I would also like to help QA it too.

@aslushnikov aslushnikov added the chromium Issues with Puppeteer-Chromium label Dec 6, 2018
@aslushnikov
Copy link
Contributor

Clicking extension buttons should enable other testing scenarios, e.g. "tab capture" API requires user gesture: #2229

@jenda
Copy link

jenda commented Dec 15, 2018

I would want this too please

@SimplGy
Copy link

SimplGy commented Feb 3, 2019

Right now the docs say "Test Chrome Extensions" as a use case.
I suggest they read "Test Chrome Extensions (background only, not action button triggered)"

This may help assess demand for the feature as well. I got pretty far in before realizing I probably have to do some workaround like side-load and manually trigger my extension's code to do any kind of testing using puppeteer.

@rinoldsimon
Copy link

Is there any workaround for this? Could someone suggest any solution for now ?
It's highly needed.!

Problem: I want to click a browser extension from Chromium toolbar.

@dbjorge
Copy link

dbjorge commented Nov 25, 2019

Our team has been using Puppeteer to test our extension (Accessibility Insights) for a while now, using a workaround for this issue where we open our popup page directly and pass the tab ID to associate with as a query param to the page for testing purposes.

Unfortunately, this workaround doesn't work very well now that we're trying to follow best practices and switch our extension to use activeTab permissions rather than https://*/** origin permissions; we haven't found any meaningful way to test the activeTab permission interaction because we don't have any way to use puppeteer to simulate any of the actions that trigger activeTab permissions. So far, the best we've come up with has been updating our end to end tests to inject the broad origin permission into the manifest file before running the tests, but that doesn't help us to verify that we're gathering activeTab permissions correctly :(

@s7x
Copy link

s7x commented Nov 26, 2019

Working on a chrome extension testing automation too here and I must say it would make things 10 times more easier to have the possibility of clicking toolbar/extension icons too!

@WebReflection
Copy link
Contributor

Rising my thumb for this issue, as we'd love to be able to test the ABP popup through automation.

Having an ETA could also help us prioritizing/organizing better, or look for alternatives.

Thanks in advance for any sort of outcome.

@GrayStrider
Copy link

Found this on google; what is the best workaround currently to test toolbar button? What about context menu?

@298068845
Copy link

any news?

@haydnba
Copy link

haydnba commented Mar 21, 2020

Found this on google; what is the best workaround currently to test toolbar button? What about context menu?

Assuming you have a background script and the required permissions specified in manifest.json, from context of extension background page query chrome APIs directly via <background_page>.evaluate(). The browserAction.onClicked event can be dispatched with a tab payload. Access the tab via chrome.tabs.query and then pass it to chrome.browserAction.onClicked.dispatch()

Note: Chrome type definitions do not include dispatch on Events so Typescript will complain...

  // find extension background target and load the page
  const extBackgroundTarget = await browser.waitForTarget(t => t.type() === 'background_page')
  const extBackgroundPage = await extBackgroundTarget.page()

  // load a page from which to click browser action, make it the active tab
  const someOtherPage = await browser.newPage()
  await someOtherPage.goto('<some_url>')
  await someOtherPage.bringToFront()

  // evaluate chrome object in context of background page:
  await extBackgroundPage.evaluate(() => {
    chrome.tabs.query({ active: true }, tabs => {
      chrome.browserAction.onClicked.dispatch(tabs[0]);
    })
  })

This works nicely to trigger whatever should happen when BrowserAction is clicked. I assume it should be possible also with chrome.contextMenus.onClicked.

@aayushsingla
Copy link

Please build this. Much needed.

@itayadler
Copy link

itayadler commented Dec 16, 2020

I have an extension that its browserAction opens a popup, so the suggested solution didn't work for me using Puppeteer v2.1.1. (using Chromium v80).
However one could simply use chrome.browserAction.openPopup((x)=> x); to open a popup:

 await extBackgroundPage.evaluate(() => {
    chrome.tabs.query({ active: true }, tabs => {
      chrome.browserAction.openPopup((x)=> x);
    })
  })

Also I wanted not only to open the popup, but to also interact with elements inside it, so I had to patch puppeteer to make the target.page() available for me, and not return null (patch is here teamwalnut@8e8cbfa)
After doing this I could access the elements popup.
The patch is a hack, I would like a more appropriate solution, I guess one would need to detect that the target is a popup, and only in that case make the target.page() return a Page instance.

@WebReflection
Copy link
Contributor

@itayadler this is awesome, thanks for the update and the hacky solution ♥

I hope they'll manage to properly provide the same feature with a less awkward dance soon!

@paambaati
Copy link

This would be vastly helpful for testing things like browser extensions. At OSlash, we're building a Chrome/Firefox extension that can immensely benefit from testing with Playwright. The one scenario that we'd love to cover is trigger the browser popup, which isn't possible today.

@LeggoMahEggo
Copy link

Went on a hell of a journey to get this working. For those who are using manifest v3, you need to use service worker, target.worker(), and chrome.action instead:

`// find extension service worker and get it
const extBackgroundTarget = await browser.waitForTarget(t => t.type() === 'service_worker');
const extWorker = await extBackgroundTarget.worker();

// load a page from which to open the extension popup, make it the active tab
const someOtherPage = await browser.newPage();
await someOtherPage.goto("https://www.google.com", { waitUntil: ['domcontentloaded', "networkidle2"] });
await someOtherPage.bringToFront();

await extWorker.evaluate(() => {
chrome.action.openPopup(); // Add arguments as needed
});`

asciimoo added a commit to asciimoo/omnom that referenced this issue Sep 19, 2022
@andreasvirkus
Copy link

This works nicely to trigger whatever should happen when BrowserAction is clicked. I assume it should be possible also with chrome.contextMenus.onClicked.

@haydnba we have a simple listener in our background script:

chrome.action.onClicked.addListener((tab) => {

That would send a message back to that same tab's content script. But for some reason this doesn't trigger with your proposed solution, nor the MV3 version that @LeggoMahEggo showed. Anything specific that might need to be changed if we don't have a popup.html that would open by default and just the listener in the background context?

@haydnba
Copy link

haydnba commented Nov 5, 2022

Hello @andreasvirkus - if I'm right in understanding you are trying to do this in a MV3 context, it's not something I've tried yet but I would hope the only thing you are missing is providing the correct tab id to the chrome.action.onClickedevent (invoking the pop up doesn't require a tab I don't believe...). So, following the @LeggoMahEggo rewrite to access the worker instead of background script, my guess is something like this should work (but I've not tested this out!)

  // find extension service worker and get it
const extBackgroundTarget = await browser.waitForTarget(t => t.type() === 'service_worker');
const extWorker = await extBackgroundTarget.worker();

// load a page from which to click browser action, make it the active tab
  const someOtherPage = await browser.newPage()
  await someOtherPage.goto('<some_url>')
  await someOtherPage.bringToFront()

  // evaluate chrome object in context of service worker:
  await extWorker.evaluate(() => {
    chrome.tabs.query({ active: true }, tabs => {
      chrome.action.onClicked.dispatch(tabs[0]);
    })
  })

@dvdvdmt
Copy link

dvdvdmt commented May 8, 2023

UPDATE: The solution works when the chrome.action.openPopup() is evaluated using Puppeteer, but not directly in Chrome's background (service-worker) page. 🥳
Here is the result of the script execution in Chrome v111.0.5555.0:
image

DEPRECATED:
Tried the solution from @LeggoMahEggo

// find extension service worker and get it
const extBackgroundTarget = await browser.waitForTarget(t => t.type() === 'service_worker');
const extWorker = await extBackgroundTarget.worker();

// load a page from which to open the extension popup, make it the active tab
const someOtherPage = await browser.newPage();
await someOtherPage.goto("https://www.google.com/", { waitUntil: ['domcontentloaded', "networkidle2"] });
await someOtherPage.bringToFront();

await extWorker.evaluate(() => {
chrome.action.openPopup(); // Add arguments as needed
});

And it doesn't work for me throwing an error when I execute chrome.action.openPopup() in background script:

TypeError: chrome.action.openPopup is not a function

@mutoe
Copy link

mutoe commented Mar 26, 2024

:) Is there a plan to support the devtools protocol? Which is important for the automated testing of extensions, thank you~

@smashedr
Copy link

I am trying to open my Web Extension popup. Which I can do with:
await worker.evaluate('chrome.action.openPopup();')
However, this popup is not able to interact with the current page and inject a script and return the results.
Is this going to be possible in puppeteer?

@johnwheeler
Copy link

If anyone is reading this in 2024, and they're trying to get an extension with activeTab permission running make sure you do this

  const browser = await puppeteer.launch({
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      `--disable-extensions-except=${extensionPath}`,
      `--allowlisted-extension-id=alfblnhfpeijnmifkfhaejkaagpopbfi`,
    ],
    headless: false,
  })

Note that --whitelisted-extension-id has been deprecated in favor of --allowlisted-extension-id

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chromium Issues with Puppeteer-Chromium feature upstream
Projects
None yet
Development

No branches or pull requests