How to setup Selenium on Heroku for Firefox? - javascript

I've made a node.js script like this:
const { Builder, By, Key, until } = require('selenium-webdriver');
const driver = new Builder().forBrowser("firefox").build();
const search_query = 'tigers';
(async () => {
await driver.get(`https://www.google.com/search?q=${search_query}`);
const h3Elements = await driver.findElements(By.css('h3'));
for (const h3 of h3Elements) {
console.log(await h3.getText());
}
console.log('...Task Complete!')
})();
and now I want to test it on a heroku server
but sadly I have no experience or understanding when it comes to setup
I tried following these link:
How to use Selenium Webdriver on Heroku?
How to run Selenium-Webdriver on Heroku with node.js (Firefox or Chrome)
but neither are for firefox
so how do I launch the above script on a heroku server? and what exactly is the process that is going on when it comes to web drivers on the server?
EDIT
I've added https://github.com/hamitaksln/heroku-integrated-firefox-geckodriver as a build pack
and set configuration vars as such:
FIREFOX_BIN=/app/vendor/firefox/firefox
GECKODRIVER_PATH=/app/vendor/geckodriver/geckodriver
LD_LIBRARY_PATH=/usr/local/lib:/usr/lib:/lib:/app/vendor
PATH=/usr/local/bin:/usr/bin:/bin:/app/vendor/
but it still shows an ERROR of incorrect path to geckodriver

Related

My Javascript file won't run because of bigint error

I am trying to use #metaplex/js to do some NFT minting. Usually my .js files work properly but when I run the file this error comes up.
bigint: Failed to load bindings, pure JS will be used (try npm run rebuild?)
I don't really get what that means. So, I tried to run npm run rebuild but rebuild is said to be a missing script and I couldn't find a way to install it.
Here is my code:
import { Connection, programs} from "#metaplex/js";
import { Loader } from "#solana/web3.js";
const { metadata: {Metadata}} = programs;
const connection = new Connection("devnet");
const tokenPublicKey = 'my_adress';
const run = async() => {
try{
const ownedMetadata = await Metadata.Loader(connection,tokenPublicKey)
console.log(ownedMetadata)
}
catch{
console.log('Failed to fetch')
}
};
run();
If you have any idea, or simply an explanation of what my error means, I'd be grateful.
You are getting this error because a nested dependency has a compilation step that might not succeed in your platform. This issue provides a good explanation.
[...] This happens because one of our dependencies (bigint-buffer) runs a compilation step on installation and this can step may fail for a couple of reasons. One of the reasons is that your system might not have the build-tools the library is looking for. You can install these build tools on Windows (see https://www.npmjs.com/package/windows-build-tools), but you don't actually need to as it automatically falls back to a pure JS solution instead. Though I agree... that warning is very annoying.
However, this should give you a warning and still allow you to compile your code.
It is worth noting that the current JS SDK from Metaplex is going to be deprecated in favour of the new one: https://github.com/metaplex-foundation/js-next
With the new JS SDK, you can fetch an NFT using the following piece of code.
import { Metaplex } from "#metaplex-foundation/js";
import { Connection, clusterApiUrl } from "#solana/web3.js";
const connection = new Connection(clusterApiUrl("mainnet-beta"));
const metaplex = new Metaplex(connection);
const mintAddress = new PublicKey("ATe3DymKZadrUoqAMn7HSpraxE4gB88uo1L9zLGmzJeL");
const nft = await metaplex.nfts().findByMint({ mintAddress });

Passing custom Chrome profile directory when starting Cypress

We would like to use a custom Chrome profile directory for our Cypress tests. The application we are testing uses a Web SQL database which needs to be loaded into the Chrome browser. We already tried this command which should be a valid chromium argument.
launchOptions.args.push('--user-data-dir=/Users/testuser/dev/chrome')
Our setup:
MacOs
Chrome v93
Cypress v8.3.0
Cypress Cucumber Preprocessor v4.1.0
The code we tried in our index.js (plugins folder):
const browserify = require('#cypress/browserify-preprocessor');
const cucumber = require('cypress-cucumber-preprocessor').default;
const resolve = require('resolve');
module.exports = (on, config) => {
const options = {
...browserify.defaultOptions,
typescript: resolve.sync('typescript', { baseDir: config.projectRoot }),
};
on('file:preprocessor', cucumber(options));
on('before:browser:launch', (browser = {}, launchOptions) => {
// `args` is an array of all the arguments that will
// be passed to browsers when it launches
console.log(launchOptions.args) // print all current args
launchOptions.args.push('--user-data-dir=/Users/testuser/dev/chrome')
launchOptions.args.push('--auto-open-devtools-for-tabs')
return launchOptions
})
};
This seems not to be working while the --auto-open-devtools-for-tabs command is working fine, but the custom profile is not loaded. Is this a known issue? Or can we debug to see what is happening?
update 24/9/2021
I see that the argument is passed to Chrome by Cypress, but Cypress overrides the Chrome profile path. Steps to reproduce:
Add launchOptions argument with --user-data-dir like mentioned above
Open Cypress dashboard (npx cypress open)
Run 1 test in Chrome
Chrome browser opens, type chrome://version/ in URL bar
--user-data-dir=/Users/testuser/dev/chrome is listed in the Command Line panel, but I also see --user-data-dir=/Users/xxxxx/Library/Application Support/Cypress/cy/production/browsers/chrome-stable/interactive listed, and that is the Profile Path which is being used by Cypress
According to this thread I understand that this is how Cypress works https://github.com/cypress-io/cypress/issues/3671

How do I open a file saved in the user directory using Electron's Shell API

I'd like an Electron app to natively open a file stored in the User directory, with the path as %userprofile%/Documents/Dir1/ThisFile.txt.
From Electron's Shell Documentation:
const { shell } = require('electron')
shell.openPath('%userprofile%/Documents/Dir1/ThisFile.txt')
yields an error:
Windows cannot find '%userprofile%/Documents/Dir1/ThisFile.txt'. Make sure you typed the name correctly and try again.
I have also tried using:
shell.openPath(path.relative('./','%userprofile%/Documents/Dir1/ThisFile.txt')); which results in the same error.
What am I doing wrong? Is there a way to open a file stored in %userprofile%.
Use electron's cross-platform .getPath() method for that:
const path = require("path");
const { app, shell } = require("electron");
shell.openPath(path.join(app.getPath("documents"), "Dir1", "ThisFile.txt"));
See here: https://www.electronjs.org/docs/api/app#appgetpathname

Using Puppeteer with Electron throws 'Could not find browser revision' error. Runs fine with node

I've tried with Puppeteer v5.4.0, v5.4.1, and v5.5.0, Windows 10/MacOS, and Node v12/v14.0.1/v15.0.3 to try to get Puppeteer to run in Electron.
Doing a simple puppeteer.launch() like this in the main process of a React application:
const puppeteer = require('puppeteer');
(async function(){
const browser = await puppeteer.launch();
})();
returns this:
Uncaught (in promise) Error: Could not find browser revision 818858. Run "PUPPETEER_PRODUCT=firefox npm install" or "PUPPETEER_PRODUCT=firefox yarn install" to download a supported Firefox browser binary.
at ChromeLauncher.launch (Launcher.js:120)
at async http:/localhost:8080/main.js:61295
I've tried running PUPPETEER_PRODUCT=firefox yarn install, setting the executablePath in the launch() method, deleting node_modules and package-lock.json, but none of these solutions seem to work. In the case of setting a path, it returns a ENOENT error. Weird enough, though, writing a small script and running it through node test.js seems to work fine.
After some hours of tinkering, here's how I figured it out:
Instead of calling from the main process, set the function in the renderer process and call it, like this:
/* main.js - Renderer Process */
ipcMain.on('spawn-browser', (event, arg) => {
const browser = await puppeteer.launch();
// Your other functions...
});
And from the main process, you can call something like:
require('electron').ipcRenderer.send('spawn-browser', args);
which works.
According to this, try one of the following:
sudo npm install puppeteer --unsafe-perm=true --allow-root
Or:
for linux:
1- you must have installed chromium browser using this command :
$sudo apt install -y chromium-browser
2- you have to get the excutable path of chromium using this command :
$which chromium-browser
3-put the executable path as an argument to the launch function :
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium-browser',
headless: false
});
const page = await browser.newPage();
await page.goto('https://google.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();

Execute single Javascript file with headless chrome from the command line

We use PhantomJS as simple test runner like this:
phantomjs path/to/test.js
Is there a similar way with headless chrome?
Selenium WebDriver is a NPM package that can help you to run a headless browser.
Try the below example:
const chrome = require('selenium-webdriver/chrome');
const {Builder, By, Key, until} = require('selenium-webdriver');
const width = 640;
const height = 480;
let driver = new Builder()
.forBrowser('chrome')
.setChromeOptions(
new chrome.Options().headless().windowSize({width, height}))
.build();
driver.get('http://www.google.com/ncr')
.then(_ =>
driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN))
.then(_ => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
.then(
_ => driver.quit(),
e => driver.quit().then(() => { throw e; }));
According to the API, the driver methods return Promises and, as a result, can be called using the async/await syntax:
const chrome = require('selenium-webdriver/chrome');
const {Builder, By, Key, until} = require('selenium-webdriver');
async function test() {
const width = 640;
const height = 480;
let driver = new Builder()
.forBrowser('chrome')
.setChromeOptions(
new chrome.Options().headless().windowSize({width, height}))
.build();
await driver.get('http://www.google.com/ncr')
await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN))
await driver.wait(until.titleIs('webdriver - Google Search'), 1000))
await driver.quit()
}
test();
You can run you tests with Karma and headless Chrome. Here's a guide for doing that.
Puppeteer's also pretty well-equipped to do this. Here's a guide for that too.
You're looking for Puppeteer, an API for headless Chrome/Chromium.
Once you have your script (the docs are good), you can run it with node script.js.
as explained on developers.google you have option of using Node or Selenium, in either case you will have to re-write part of your test cases to use the new api instead of the phantomjs api.
The following options are based on Node:
Puppeteer
I suggest you to head over to their github page for installation and usage instructions.
Your test case should be written using the Puppetteer api and run with:
node path/to/test.js
There is a list of puppeteer resources, you can use puppeteer with jest, mocha, angular, e2e..
chrome-remote-interface
library
chrome-remote-interface is a lower-level library than Puppeteer's API. I recommend it if you want to be close to the metal and use the DevTools protocol directly.
You need to start chrome in headless mode or use lighthouse or nodejs:
node --inspect=9222 path/to/test.js
write your javascript test case using the chrome DevTools protocol and follow the instructions on their github page to install and run your tests.
The other option is using Selenium configured to run headless Chrome. The following options use Selenium:
ChromeDriver
Webdriver

Categories