Jest Setup and share global variables - jestjs

I am using Jest to write Puppeteer tests and I want to do a single time setup(of opening a browser) and share it across all the tests.
The setup I need to do is returns a promise.
I tried used setupTestFrameworkScriptFile and set global.browser
But this global.browser is not available
If I set it in the global config of Jest, I can write custom logic of setting the browser object
Like event If I declare __BROWSER__ I cant set it
__BROWSER__ = await puppeteer.launch({
headless: false,
ignoreHTTPSErrors: true,
dumpio: true,
devtools: false
});

Related

react electron frameless window (contextBridge API error)

I am trying to make an electron react project with my own custom frameless window.
I've accomplished this before, just without react, but not it seems like introducing react is causing some error I can't solve.
I was following this tutorial on how to add a frameless window.
And I have my electron.js file containing this code:
// Create the native browser window.
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
enableRemoteModule: true,
nodeIntegration: true,
contextIsolation: false,
preload: path.join(__dirname, "preload.js"),
},
frame: false,
backgroundColor: '#FFF',
});
// In production, set the initial browser path to the local bundle generated
// by the Create React App build process.
// In development, set it to localhost to allow live/hot-reloading.
const appURL = app.isPackaged
? url.format({
pathname: path.join(__dirname, "index.html"),
protocol: "file:",
slashes: true,
})
: "http://localhost:3000";
mainWindow.loadURL(appURL);
Which loads my index.html file, inside that index.html file I have a link to renderer.js at the bottom:
<script src="renderer.js"></script>
</body>
</html>
inside renderer.js, the first lines have some require() lines
const remote = require('electron').remote;
const app = require('electron')
const win = remote.getCurrentWindow(); /* Note this is different to the
html global `window` variable */
But I havent been able to get these lines to pass correctly. my electron branch is 'frameless-window' located here:
https://github.com/MartinBarker/electron-react/tree/frameless-window
My current error message is:
node:electron/js2c/renderer_init:45 Uncaught Error: contextBridge API can only be used when contextIsolation is enabled
at node:electron/js2c/renderer_init:45
at Object.exposeInMainWorld (node:electron/js2c/renderer_init:45)
at process.<anonymous> (C:\Users\marti\Documents\projects\react-electron-oct023\electron-react\public\preload.js:9)
at Object.onceWrapper (node:events:513)
at process.emit (node:events:394)
renderer.js:4 Uncaught TypeError: Cannot read properties of undefined (reading 'getCurrentWindow')
at renderer.js:4
but if i change contextIsolation: true, in electron.js, the error changes to this:
renderer.js:1 Uncaught ReferenceError: require is not defined
Am I missing some way to make this renderer.js file work?

Enable Chrome Extension in Puppeteer version 10.1.0

I am attempting to open Chrome with Puppeteer enabling a Chrome extension.
I have been searching for solutions and have tried to implement many with no success.
chrome://version/
Google Chrome: 91.0.4472.164 (Official Build) (x86_64)
Revision: 541163496c9982c98f61819bab7cf2183ea8180f-refs/branch-heads/4472#{#1569}
OS: macOS Version 10.15.7
JavaScript: V8 9.1.269.39
Executable Path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
Puppeteer: 10.1.0
Code (one of many attempts, but latest):
const puppeteer = require('puppeteer');
const path = require('path');
const extension_id_string = 'copjnifc....example.....gaodgpbh';
const extension_version = '1.5.1_0';
const extension_path = path.resolve(__dirname, '../../..', `/Library/Application\ Support/Google/Chrome/Default/Extensions/${extension_id_string}/${extension_version}`);
(async() => {
const browser = await puppeteer.launch({
headless: false,
args: [
`--load-extension=${extension_path}`,
`--disable-extensions-except=${extension_path}`
]
})
const page = await browser.newPage()
await page.goto('http://google.com');
})();
I've used Node JS path module to get absolute path to the extensions directory.
On running the code with Node v14.17.1 Chromium opens a browser and an alert pops up saying:
alert => Failed to load extension from: . Manifest file is missing or unreadable
When I follow the extension_path (denoted above on line 6) in terminal I can see a Manifest.json file, so there is one.
What am I missing here? Am I defining the path to the extension incorrectly? Or do I need to set the executablePath for my current Chrome path inside the options when launching a browser? (I did try this with no success).
const chrome_executablePath = path.resolve(__dirname, '../../..', '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome')
...
const browser = await puppeteer.launch({
headless: false,
executablePath: chrome_executablePath, //<-- added this line in previous attempts, but still didn't work
args: [
`--load-extension=${extension_path}`,
`--disable-extensions-except=${extension_path}`
]
})
...
Any pointers / help greatly appreciated.
I think you can do three things here:
Check if the manifest.json is encoded to UTF-8.
Make sure your extension path points to the extension area (i.e development area).
After headless false, add "devtools: true" option.

puppeteer ignoring args pass for proxy pac url

I am trying to use pac file as an argument for puppeteer proxy settings as define here: https://www.chromium.org/developers/design-documents/network-settings
--proxy-pac-url=<pac-file-url>
here is my code,
const puppeteer = require('puppeteer');
(async() => {
const proxyUrl = 'http://{IPAddress}:{Port}';
const browser = await puppeteer.launch({
args: [`--proxy-pac=url=${proxypacUrl}`],
headless: false,
});
const page = await browser.newPage();
await page.goto('https://stackoverflow.com/');
await browser.close();
})();
However, when I execute the code, the code just works and visit stackoverflow.com, but completely ignore
--proxy-pac=url=${proxypacUrl}
I know this because I can monitor the proxy logs. Proxy PAC URL file specifically says to use proxy for all traffic.
Here is my proxy pac file,
function FindProxyForURL(url, host) {
return "PROXY IP:PORT; PROXY IP:PORT";
}
When I change --proxy-pac-url=<pac-file-url> to --proxy-server and specify ip and port directly, the traffic goes through the proxy.
Can someone please let me know what I am doing wrong with Proxy PAC URL?
You have an error in your code
--proxy-pac=url=${proxypacUrl} should be --proxy-pac-url=${proxypacUrl}.
Unfortunately fixing it won't help because proxy pac files aren't supported in headless chromium, here is an issue.

node.js i18n: "ReferenceError: __ is not defined"

Throughout my app I use i18n without problem. However, for email send through a cron job, I get the error:
ReferenceError: __ is not defined
In app.js I configure i18n:
const i18n = require("i18n");
i18n.configure({
locales: ["en"],
register: global,
directory: path.join(__dirname, "locales"),
defaultLocale: "en",
objectNotation: true,
updateFiles: false,
});
app.use(i18n.init);
Throughout my app I use it as __('authentication.flashes.not-logged-in'), like I said without problems. In a mail controller, that is called upon by a cron job, I use it in the same way: __('mailers.buttons.upgrade-now'). However there, and only there, it produces the mentioned error.
Just to try, I've changed this in the mail controller to i18n.__('authentication.flashes.not-logged-in'). But then I get another error:
(node:11058) UnhandledPromiseRejectionWarning: TypeError: logWarnFn is not a function
at logWarn (/data/web/my_app/node_modules/i18n/i18n.js:1180:5)
Any idea how to make the emails work that are sent through a cron job?
In comments, the asker clarified that the cron job calls mailController.executeCrons() directly, instead of making an HTTP request to the app. Because of this, the i18n global object never gets defined, because the app setup code in app.js isn't run.
The best solution would be to use i18n's instance usage. You could separate the instantiation and configuration of an I18N object out into a separate function, then call it both in app.js to set it up as Express middleware, and in the mailController.executeCrons() function to use it when being called through the cronjob.
Code outline:
i18n.js (new file)
const i18n = require("i18n");
// factory function for centralizing config;
// either register i18n for global use in handling HTTP requests,
// or register it as `i18nObj` for local CLI use
const configureI18n = (isGlobal) => {
let i18nObj = {};
i18n.configure({
locales: ["en"],
register: isGlobal ? global : i18nObj,
directory: path.join(__dirname, "locales"),
defaultLocale: "en",
objectNotation: true,
updateFiles: false,
});
return [i18n, i18nObj];
};
module.exports = configureI18n;
app.js
const configureI18n = require('./path/to/i18n.js');
const [i18n, _] = configureI18n(true);
app.use(i18n.init);
mailController.js
const configureI18n = require('./path/to/i18n.js');
const [_, i18nObj] = configureI18n(false);
executeCrons() {
i18nObj.__('authentication.flashes.not-logged-in');
}

Tell Puppeteer to open Chrome tab instead of window

If I have an existing Google Chrome window open, I'd like to tell puppeteer to open a new tab instead of opening a new window. Is there a way to do that? is there some option or flag I can pass to puppeteer to accomplish this?
I have:
const puppeteer = require('puppeteer');
(async function () {
const b = await puppeteer.launch({
devtools: true,
openInExistingWindow: true /// ? something like this?
});
const page = await b.newPage();
await page.goto('https://example.com');
})();
const browser = puppeteer.launch();
const page = browser.newPage();
This will open a new tab (Puppeteer calls them "pages") in your current browser instance. You can check out the Page class docs here and the Browser class docs here.
You'll need to use:
/usr/bin/google-chrome-stable --remote-debugging-port=9220
to get the websocket connection for debugging which then can be fed to Puppeteer:
await puppeteer.connect({browserWSEndpoint: chromeWebsocket})

Resources