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

Can we use Puppeteer to interact with an Devtools panel? #3699

Closed
dohuuvi-lgg opened this Issue Dec 21, 2018 · 3 comments

Comments

Projects
None yet
3 participants
@dohuuvi-lgg
Copy link

dohuuvi-lgg commented Dec 21, 2018

I'm trying to test an extension using Puppeteer. As this link we can work with background page of Chrome extension. But can we work with the panel in the Devtools?

Thanks!

@gidztech

This comment has been minimized.

Copy link

gidztech commented Dec 21, 2018

You can technically do it (based on my experiment), but there's no nice Puppeteer API to interact with the Devtools UI because that is separate from the DevTools Protocol.

You can obtain the Devtools panel from browser.targets.

However, using target.page() to get hold of the page object doesn't work because the target type is other. I'm wondering if it would work if Puppeteer was to return it as a page type instead.

Anyway, I instead managed to get something working by creating a new page instance and navigating to the Devtools URL. I was then able to query the DOM and interact with the panels. In my example, I click on the Network tab.

const puppeteer = require('puppeteer');

(async() => {
    const browser = await puppeteer.launch({ devtools: true });
    const targets = await browser.targets();

    // find Devtools target URL
    const devtoolsUrl = targets
        .map(({ _targetInfo }) => _targetInfo.url)
        .find((url) => url.indexOf('chrome-devtools://') !== -1);
    
    // load the Devtools page in a new tab
    const page = await browser.newPage();
    await page.goto(devtoolsUrl);
    
    // click on Network tab
    const networkTab = await page.evaluateHandle(`document.querySelector('#-blink-dev-tools > div.widget.vbox.root-view > div > div.widget.vbox.insertion-point-sidebar > div > div').shadowRoot.querySelector('#tab-network');`);
    await networkTab.click();
})();

I haven't tested much more than this small example, but maybe it will be of use.

@dohuuvi-lgg

This comment has been minimized.

Copy link
Author

dohuuvi-lgg commented Dec 24, 2018

Thanks gidztech but this is just a workaround because it just loads the static panel without data inside. We cannot interact with live panel of the devtools of current page.

@gidztech

This comment has been minimized.

Copy link

gidztech commented Dec 29, 2018

@dohuuvi-lgg You're right. I completely missed that. I spent some more time and came up with a new hack! This time, it will connect to the actual page and navigate to a Chrome Extension tab.

It works with the normal DevTools UI, but what I'm finding is that the Chrome Extension isn't getting the blocked requests. I think it's because Adblock connects to a particular tab and we're using a new one, so it won't get messages for the old tab. Whether this affects your extension or not I don't know.

// Use Puppeteer to interact with the DevTools UI while inspecting a page
// This is a complete hack, but it allows you to interact with the DevTools UI using Puppeteer.
// In this example, I'm able to install Adblock Plus and navigate to the extension's tab

const puppeteer = require('puppeteer');

(async() => {
    // launch with devtools, which enables debugging capabilities
    // and load the Adblock extension (assumes the unpacked extension is in a folder called `adblock-unpacked`)
    const browser = await puppeteer.launch({ 
        devtools: true,
        args: [
            '--disable-extensions-except=adblock-unpacked',
            '--load-extension=adblock-unpacked/',
          ]
    });

    const wsEndpoint = browser.wsEndpoint();

    // the page I want to debug
    const myPage = await browser.newPage();
    const pageId = myPage.target()._targetId;

    // use the host:port that Chromium provided, but replace the browser endpoint with the page to inspect
    const pageTargeUrl = `${wsEndpoint.replace('ws://', '').match(/.*(?=\/browser)/)[0]}/page/${pageId}`;
                
    // generate the full debugging url for the page I want to inspect
    const pageDebuggingUrl = `chrome-devtools://devtools/bundled/devtools_app.html?ws=${pageTargeUrl}`;

    // open the debugging UI in a new tab that Puppeteer can interact with
    const devtoolsPage = await browser.newPage();
    await devtoolsPage.goto(pageDebuggingUrl);

    // navigate to the page now so that we start capturing data in the debugger UI
    await myPage.goto('http://news.bbc.co.uk');
    
    // the installed extension may open a new tab so make sure we select the debugger UI tab
    await devtoolsPage.bringToFront()

    // use Cmd + ] shortut to move across tabs until we're on the the Adblock Plus tab
    let selectedAdblockTab = null;

    while (!selectedAdblockTab) {
        await devtoolsPage.keyboard.down('MetaLeft');
        await devtoolsPage.keyboard.press(']');
        await devtoolsPage.keyboard.up('MetaLeft');

        selectedAdblockTab = await devtoolsPage.evaluate(() => {
            return document.querySelector('#-blink-dev-tools > div.widget.vbox.root-view > div > div > div').shadowRoot.querySelector('#tab-chrome-extension\\\:\\\/\\\/cfhdojbkjhnklbpkdaibdccddilifddbAdblockPlus[aria-selected="true"]');
        })
    }
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment