How to run setup code before extension loaded in puppeteer? - google-chrome-extension

I am testing the behavior of a chrome extension using puppeteer.
Upon installation, the extension opens a page. I would like to do initial setup in the browser before the extension is loaded (for example, setting local storage or injecting a jest mock).
The problem I have now is that the extension gets loaded upon browser start, so I don't know of any way to execute setup code before the extension is loaded.
This is how I load the extension currently (which resides in the dist/chrome folder):
const browser = await puppeteer.launch({
args: [
'--disable-extensions-except=dist/chrome',
'--load-extension=dist/chrome',
],
headless: false,
ignoreDefaultArgs: ['--disable-extensions'],
});
How can I do initial setup before the extension is loaded?
Some options I can think of are: 1) load the extension after the browser is launched 2) intercept the extension installation and execute setup code before the extension initializes

I came searching for an answer and I found it reading your question, so I'm leaving it here in case I have to search for it again in the future ...
The trick is to create a "launcher" extension with the sole purpose running the setup code, before the actual extension is ran. It would look like:
'--disable-extensions-except=dist/launcher,dist/chrome',
'--load-extension=dist/launcher,dist/chrome',

Related

How do I add and use Chrome Extensions with Cypress.io?

I'm currently dealing with a an X-Frame-Options issue being blocked when running my Cypress.io tests. I cannot change the server setup to modify the X-Frame settings. Somebody mentioned to me that I should try a chrome extension called "Ignore X-Frame headers."
I have the extension installed on my non-Cypress Chrome, but how do I install it for use in my Cypress.io tests? If I go into developer tools while running a Cypress test, I can see that no extensions are loaded for Cypress/Chrome.
Any ideas on how or IF I can do this? I'm using a Mac.
You could try to install the extension through Cypress chrome (and enable it).
You can use the before:browser:launch event to load a Chrome extension.
More information on how to use this event here.
For those wondering what the link is to that extension is:
https://chrome.google.com/webstore/detail/ignore-x-frame-headers/gleekbfjekiniecknbkamfmkohkpodhe
paste that link into the chrome window Cypress is running in and install it then try to re-load your test. :)
const path = require("path")
module.exports = (on, config) => {
on('before:browser:launch', (browser, launchOptions) => {
// supply the absolute path to an unpacked extension's folder
// NOTE: extensions cannot be loaded in headless Chrome
launchOptions.extensions.push(path.resolve(__dirname,"../../extension_name"))
return launchOptions
})

How to inject script using node.js code?

You all know open npm package: https://www.npmjs.com/package/open
Using this package, one can write the following code:
var open = require('./node_modules/open/lib/open.js')
open('http://www.cnn.com')
and activating it by:
$ node app.js
will open a browser window of cnn.com.
I want my script to open this site and inject some code to the console. I mean that the browser will behave like I clicked F12, went to 'console' tab and typed in console the code:
alert('Hello World')
Do you know how to do it?
The open module is used to "Open a file or url in the user's preferred application."
It can open the preferred application (a browser in this case) but it cannot control it. In fact, it doesn't even know what browser will that be (or even if that will be a browser).
What you are asking for can be achieved with tools like PhantomJS ("PhantomJS is a headless WebKit scriptable with a JavaScript API."), Nightmare.js ("A high-level browser automation library.") or CasperJS ("Navigation scripting & testing for PhantomJS and SlimerJS"), see:
http://phantomjs.org/
http://www.nightmarejs.org/
http://casperjs.org/

Using Protractor how to run multiple spec files without closing browser for each spec file

I'm using page object design pattern in my automation tests. I have spec file per page object. When the tests run, browser restarts in between spec files where it asks to login again. But what I'm trying to achieve is that I want to login at the start of the tests, run tests from multiple specs without closing the browser in between executing the spec files.
In protractor.conf.js, under capabilities, setting shardTestFiles: false will open one browser, run all spec files sequentially in that browser, then exit the browser when all tests have finished.
You can add "Before all" in your first spec file which is needed to load the browser. Once that Spec is run then again next spec is starting to load in same browser window and you won't require login attempt.
beforeAll(() => {
browser.driver.get("https://stackoverflow.com"),
browser.driver.manage().window().maximize();
});

Chromedriver extension id does not match key in manifest.json

I am testing a chrome extension using selenium webdriver.js and chromedriver. I've been able to successfully launch chrome, with my extension installed, but the extension id is randomly generated instead of matching the key property of my manifest.json. This makes it impossible to test extension pages like the options page.
manifest.json
// ...
"key": "pjnhffdkdckcagdmfmidafhppbomjdjg", // id from chrome web store
// ...
test.js
var webdriver = require('selenium-webdriver');
var chrome = require('selenium-webdriver/chrome');
// load unpacked extension
var chromeOptions = new chrome.Options();
chromeOptions.addArguments('load-extension=/path/to/my/extension');
var service = new chrome.ServiceBuilder().build();
var driver = chrome.createDriver(chromeOptions, service)
// this page is not available T_T
driver.get('chrome-extension://pjnhffdkdckcagdmfmidafhppbomjdjg/html/options.html');
My assumption is that the extension id would match the key (and it does when installing from the web store), but this does not seem to be true for loading the extension via chromedriver. Is there a way to get the loaded extension to have a consistent ID? Or should I take another approach?
The manifest key value is not the extension ID. You have to install the extension from the web store and look in the manifest.json file on your desk. Use they key value inside that file. The documentation describes how to find the install directory.
I was having the same issue.
Just load your extensions from a crx file and you will get a consistent id.

Check if Chrome extension installed in unpacked mode

Is there a way to detect whether I'm running an extension that was installed from my .crx file or the extension was loaded as via 'Load unpacked extension...' button?
I'm aware about ID differences in that case, but I don't want to rely on hardcoded strings in the code.
If by "installed from my .crx file" you mean installed from Chrome Web Store you can simply check extension manifest.json for value of update_url attribute. CWS adds it when you upload your extension.
If you have a self-hosted .crx file, get your extension information using chrome.management.getSelf() and check installType of returned ExtensionInfo object. If it says "development" that means that extension was loaded unpacked in developer mode. "normal" means that it was installed from .crx file.
Here is a code sample how to do this:
function isDevMode() {
return !('update_url' in chrome.runtime.getManifest());
}
or
const isProdMode = 'update_url' in chrome.runtime.getManifest()
An extension is running in developer mode (i.e. unpacked), when it does not contain the update_url field in its manifest.
This works because an unpacked extension's JSON manifest file should not contain the update_url field. This field is automatically added when publishing via the Chrome Developer Dashboard.
For example, debug logs that only appear during development.
const IS_DEV_MODE = !('update_url' in chrome.runtime.getManifest());
function debugLog(str) {
if (IS_DEV_MODE) console.log(str);
}
debugLog('This only appears in developer mode');

Resources