Why chromium doesn't open in headless Mode? - node.js

I have the following NodeJS code to open Chromium in headless mode and record a web page to a video :
const { launch, getStream } = require("puppeteer-stream");
const fs = require("fs");
const { exec } = require("child_process");
async function test() {
const browser = await launch({headless: true});
const page = await browser.newPage();
await page.goto("https://www.someurl.com");
const stream = await getStream(page, { audio: true, video: true});
// record the web page to mp4 video
const ffmpeg = exec('ffmpeg -y -i - output.mp4');
stream.pipe(ffmpeg.stdin);
setTimeout(async () => {
await stream.destroy();
stream.on("end", () => {});
}, 1000 * 60);
}
The following code works properly but doesn't open chromium in headless mode. No matter what I do, the browser is still opened and visible when browsing the page. No error is thrown.
Does anyone know why it's not opened in headless mode please ?
Thanks

It says in the documentation for puppeteer-stream:
Notice: This will only work in headful mode
This is due to a limitation of Chromium where the Tab Capture API for the extension doesn't work in headless mode. (There are a couple bug reports about this, but I can't find the links at the moment.)

I had the same issue that headless doesn't work with some Websites and Elements (showing blank page content, not finding an element etc.).
But there is another method to "simulate" the headless mode by minimizing and moving the window to a location that can not be seen by the user.
This doesn't hide the chrome task from the taskbar, but the Chrome tab itself will still be hidden for the User.
Just use the following arguments:
var chromeOptions = new ChromeOptions();
chromeOptions.AddArguments(new List<string>() { "--window-size=1,1", "window-position=-2000,0" }); // This hides the chrome window
var chromeDriverService = ChromeDriverService.CreateDefaultService();
chromeDriverService.HideCommandPromptWindow = true; // This is to hid the console.
ChromeDriver driver = new ChromeDriver(chromeDriverService, chromeOptions);
driver.Navigate().GoToUrl("https://google.com");
in short the important part:
chromeOptions.AddArguments(new List<string>() { "--window-size=1,1", "window-position=-2000,0" });
chromeDriverService.HideCommandPromptWindow = true;
//driver.Manage().Window.Minimize(); //use this if the code above does not work

Related

Bulk Excel Upload from Angular shows Page Unresponsive

I am trying to upload the excel from UI (angular8 and node 14) and try to process it, but while retrieving data from excel for bulk data(1800 rows almost 12mb file ) it shows a Page Unresponsive pop-up many times and I can understand, chrome browser trying to use a lot of memory and result is Page Unresponsive pop-up. is there any way to disable or not show this pop-up or any solution for this issue?
Thanks in advance.
I am attaching below working Ts file code.
code:
onFileChange(evt: any) {
const target: DataTransfer = (evt.target) as DataTransfer;
const selectedFile = evt.target.files[0];
const reader: FileReader = new FileReader();
reader.readAsBinaryString(selectedFile);
reader.onload = (e: any) => {
const bstr: string = e.target.result;
const wbk: XLSX.WorkBook = XLSX.read(bstr, {type: 'binary'});
wbk.SheetNames.forEach(sheet =>{
setTimeout(()=>{}, 250); //I am trying to use timeout to refresh the flow but not working
const data1 = XLSX.utils.sheet_to_json(wbk.Sheets[sheet]);
console.log(data1);
})
}
};

How to print the raw devtools request sent by Puppeteer?

I see that Puppeteer used devtools protocol. I want to see what requests are sent by Puppeteer.
https://github.com/puppeteer/puppeteer
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
How can I modify the above simple program to print the devtools requests sent by Puppeteer?
Edit
As the code is in Nodejs, I added the tag nodejs because the solution may be in Nodejs instead of Puppeteer.
Edit
Fiddler is mentioned as relevant. So I add this tag as well.
You could use chrome-protocol-proxy it captures all the CDP messagee. There are few extra steps involved here.
Run google chrome in debug mode
start chrome-protocol-proxy
Start puppeteer using puppeteer.connect()
Run following commads, you may have to change them accordingly
google-chrome-stable --remote-debugging-port=9222 --headless # run chrome
chrome-protocol-proxy # to display CDP messages
Remove this line from your code
const browser = await puppeteer.launch();
Add this line
const browser = await puppeteer.connect({"browserURL":"localhost:9223"});
Instead of browserURL you can give browserWSEndpoint which you will get by cURL on localhost:9223/json/version
If you want to go more into detail of CDP and puppeteer you might want to look at Gettig Started with CDP

Handle alerts in selenium webdriver for nodejs

I am running a simple webserver in nodejs. On the server side i want to check if the user was successful in getting an alert box in the UI. Could be (confirm , prompt etc) . The payload is in the URL. To check this i create a URL and pass it to selenium to check if it creates an alert box. However, all my attempts to handle the alert are failing with an exception. Heres my code
/* global */
const webdriver = require('selenium-webdriver')
const chrome = require('selenium-webdriver/chrome')
var options = new chrome.Options();
options.addArguments('headless');
var path = require('chromedriver').path;
let driver = new webdriver.Builder().
withCapabilities({'browserName': 'chrome', 'alertBehavior': 'IGNORE'}).
setChromeOptions(options).
build();
/* do bunch of stuff */
function checkXSS(payload) {
console.log('checking payload')
var url = 'http://<url>?payload=' + payload
driver.get(url). //exception thrown here itself.
driver.switchTo().alert().then(function() {
driver.switchTo().alert().accept();},
function(){});
}
And i get the below exception
UnexpectedAlertOpenError: unexpected alert open: {Alert text : XSS}
I tried other ways too that were suggested on stackoverflow. Such as using driver.get.then(_, =>), alert.dismiss() etc however all of them still throw the same exception. What am i missing here?

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})

Navigating to another URL during webdriver task

I am trying to log into a website as an admin and then navigate to another page (a portal) which requires this admin login beforehand to display data. I don't think I can access the cookies because of an issue accessing https cookies issue I read up on earlier (correct me if I'm wrong).
So my current solution is to enter the url as soon as the login process is complete and then continue with other tasks. Could you please advise on the methods/functions I can use to do this? If there are better ways to do this, I'd also be happy to hear about those!
var webdriver = require("selenium-webdriver");
var By = require("selenium-webdriver").By;
var until = require("selenium-webdriver").until;
var assert = require("chai").assert;
var filename = "img";
var fs = require('fs');
var err = "error caught!";
var testName = "get_login_cookies";
var driver = new webdriver.Builder()
.forBrowser('chrome')
.build();
describe('email register', function () {
this.timeout(25000);
before(function(done) {
driver.navigate().to('https://www.perlego.com/#');
driver.manage().deleteAllCookies;
driver.manage().window().maximize()
.then(() => done())
});
it('logs in with admin user and gets cookies', (done) => {
driver.findElement(By.name('email')).sendKeys("user#example.com");
driver.findElement(By.css('#password')).sendKeys("examplePassword");
driver.findElement(By.css('.login-button')).click();
// some code here to navigate to other page via url
// runs remainder of tests
});
after(function(done) {
driver.quit()
.then(() => done())
});
});
So I found that it was as simple as running the driver.navigate() method where I wanted to go to a new page:
driver.navigate().to('https://www.somesite.com/#');
Because of the cookie settings on the site, I was unable to access them with the webdriver, so I had to enter the password each time.
I was tripped up by waiting for ajax calls on the page when trying to select elements, this method helped:
driver.manage().timeouts().implicitlyWait(3000);
Hope this helps someone out there!

Resources