Puppeteer : Unable to play video - youtube

I can't play Youtube videos with puppeteer. It looks like chromium does not support video playback. What should I do ?
Here's my code :
const puppeteer = require('/root/node_modules/puppeteer/');
(async function main() {
try {
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox']
})
const page = await browser.newPage();
await page.goto('https://www.youtube.com/watch?v=WjOGhNDX51M');
await page.waitFor(8000);
await page.screenshot({
path: '/var/www/html/test/example.png'
});
await browser.close()
} catch (e) {
console.log("our error", e);
}
})();
Thank you!

The chromium that is shipped with puppeteer does not have the codecs required for licensing and size reasons.
You can hook pupeteer to a "real" chrome instance like this :
const browser = await puppeteer.launch({
executablePath: '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome',
headless:false,
defaultViewport:null,
devtools: true,
//args: ['--window-size=1920,1170','--window-position=0,0']
args: ["--window-size=1920,1080", "--window-position=1921,0"]
})
Note the executablePath option.
Your path may vary.
HTH

Related

How can I set up localStorage keys with storageState

I'm trying to set up localStorage when a user registers,
but it only generates the file with no key, values.
If I run npx playwright codegen --save-storage=formsData.json
works fine and generates the key,values but the generated code is very different
and I don't see how localStorage is created.
What I'm doing wrong, or not doing ?
This is my test code:
const { test, expect } = require('#playwright/test');
const { buildUser } = require('./utils/generateUser');
test.describe('Register Form', () => {
test('displays register form and can register user', async ({ browser }) => {
const user = await buildUser();
const page = await browser.newPage();
await page.goto('http://localhost:3000/register');
await expect(page).toHaveURL('http://localhost:3000/register');
const firstNameInput = page.locator('[placeholder="Nombre"]');
const lastNameInput = page.locator('[placeholder="Apellidos"]');
const emailInput = page.locator('[placeholder="Email"]');
const passwordInput = page.locator('[placeholder="Contraseña"]');
const repeatPasswordInput = page.locator('[placeholder="Repite la contraseña"]');
const registerButton = page.locator('text=Adelante');
const termsCheckbox = page.locator('input[type="checkbox"]').first();
const privacyCheckbox = page.locator('input[type="checkbox"]').last();
const modalWindow = page.locator('.styles__ContentWrapper-n48cq5-0');
const modalButton = page.locator('text=Aceptar');
await expect(firstNameInput).toBeEmpty();
await expect(lastNameInput).toBeEmpty();
await expect(emailInput).toBeEmpty();
await expect(passwordInput).toBeEmpty();
await expect(repeatPasswordInput).toBeEmpty();
await expect(registerButton).toBeDisabled();
await expect(termsCheckbox).not.toBeChecked();
await expect(privacyCheckbox).not.toBeChecked();
await expect(modalWindow).toBeHidden();
await firstNameInput.fill(user.nombre);
await lastNameInput.fill(user.apellido);
await emailInput.fill(user.email);
await passwordInput.fill('12341234');
await repeatPasswordInput.fill('12341234');
await termsCheckbox.check();
await privacyCheckbox.click();
await expect(modalWindow).toBeVisible();
await page.press(':nth-match(input[type="checkbox"], 2)', 'Tab');
await page.press('text=info#coinscrap.com', 'Tab');
await await modalButton.click();
await expect(registerButton).toBeEnabled();
await registerButton.click();
await page.context().storageState({ path: 'formsData.json' });
await browser.close();
});
});
This is what playwright codegen does:
const { test, expect } = require('#playwright/test');
test('test', async ({ page }) => {
// Go to http://localhost:3000/register
await page.goto('http://localhost:3000/register');
// Click [placeholder="Nombre"]
await page.click('[placeholder="Nombre"]');
// Fill [placeholder="Nombre"]
await page.fill('[placeholder="Nombre"]', 'Pascale');
// Click [placeholder="Apellidos"]
await page.click('[placeholder="Apellidos"]');
// Fill [placeholder="Apellidos"]
await page.fill('[placeholder="Apellidos"]', 'Gusikowski');
// Click [placeholder="Email"]
await page.click('[placeholder="Email"]');
// Fill [placeholder="Email"]
await page.fill('[placeholder="Email"]', 'Pascale_Gusikowski86#gmail.com');
// Click [placeholder="Contraseña"]
await page.click('[placeholder="Contraseña"]');
// Fill [placeholder="Contraseña"]
await page.fill('[placeholder="Contraseña"]', '12341234');
// Click [placeholder="Repite la contraseña"]
await page.click('[placeholder="Repite la contraseña"]');
// Fill [placeholder="Repite la contraseña"]
await page.fill('[placeholder="Repite la contraseña"]', '12341234');
// Check input[type="checkbox"]
await page.check('input[type="checkbox"]');
// Click text=1.1 -Decisiones automatizadas, perfiles y lógica aplicada Los datos recogidos me
await page.click('text=1.1 -Decisiones automatizadas, perfiles y lógica aplicada Los datos recogidos me');
// Press End
await page.press('text=You need to enable JavaScript to run this app. Crea una cuenta​​​​​ AdelanteHe l', 'End');
// Click text=Aceptar
await page.click('text=Aceptar');
// Click text=Adelante
await Promise.all([
page.waitForNavigation(/*{ url: 'http://localhost:3000/internal/banks/start' }*/),
page.click('text=Adelante')
]);
});
There's no code where localStorage is created.
I need to do it programmatically.
I've also tried with:
const localStorage = await page.evaluate(() => JSON.stringify(window.localStorage));
fs.writeFileSync('formsData.json', localStorage);
It generates the file but didn't generate keys, values.
localStorage (DOMStorage) is unrelated to the form you submit. When you submit the form, a POST request is typically issued to the server, sending on this data to the backend. It looks like your page has additional JavaScript code that stores these values into localStorage at some point. Your localStorage does not have these values at the time you save it, so you should figure out how to trigger this code on your page and how to wait for it. You can open DevTools and evaluate "localStorage" in console or pick it in the Application tab to see when and why these values make their way into the local storage.

capture screen with electron when rendering a web site

I have an electron application that loads a web page on the internet.
one of the sites main features is the ability to capture screen, it uses the
navigator.mediaDevices.getDisplayMedia({video: true});
but obviously, the electron will through the Permission denied because there will be no 'selecting window to capture' popped up to grant any permission to it.
I already check out some articles and saw desktopCapture
the problem is, this is happening and running through the web page javascript not my application's code so I don't know how to affect it.
so what should I do to make capturing the screen works in this situation?
You can override navigator.mediaDevices.getDisplayMedia to call Electron's desktopCapturer API like shown below. This implementation assumes you have contextIsolation enabled which is the default behaviour in Electron >= 12
// preload.js
const { desktopCapturer, contextBridge } = require("electron");
const { readFileSync } = require("fs");
const { join } = require("path");
// inject renderer.js into the web page
window.addEventListener("DOMContentLoaded", () => {
const rendererScript = document.createElement("script");
rendererScript.text = readFileSync(join(__dirname, "renderer.js"), "utf8");
document.body.appendChild(rendererScript);
});
contextBridge.exposeInMainWorld("myCustomGetDisplayMedia", async () => {
const sources = await desktopCapturer.getSources({
types: ["window", "screen"],
});
// you should create some kind of UI to prompt the user
// to select the correct source like Google Chrome does
const selectedSource = sources[0]; // this is just for testing purposes
return selectedSource;
});
// renderer.js
navigator.mediaDevices.getDisplayMedia = async () => {
const selectedSource = await globalThis.myCustomGetDisplayMedia();
// create MediaStream
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: "desktop",
chromeMediaSourceId: selectedSource.id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720,
},
},
});
return stream;
};
Now when this API is called, a stream will be returned to the caller as expected
navigator.mediaDevices.getDisplayMedia({video: true});
I have created a GitHub repo that has a working implementation of this solution

Data sharing between Safari and standalone iPhone 12 iOS 14.3

I tried to share data between Safari browser and standalone PWA on iPhone12 with iOS 14.3.
The information, that this should work are here: https://firt.dev/ios-14/
I#ve tried this: https://www.netguru.com/codestories/how-to-share-session-cookie-or-state-between-pwa-in-standalone-mode-and-safari-on-ios
Without success.
Are there any suggestions to running this? Or is it not possible ...
This is the code
const CACHE_NAME = "auth";
const TOKEN_KEY = "token";
const FAKE_TOKEN = "sRKWQu6hCJgR25lslcf5s12FFVau0ugi";
// Cache Storage was designed for caching
// network requests with service workers,
// mainly to make PWAs work offline.
// You can give it any value you want in this case.
const FAKE_ENDPOINT = "/fake-endpoint";
const saveToken = async (token: string) => {
try {
const cache = await caches.open(CACHE_NAME);
const responseBody = JSON.stringify({
[TOKEN_KEY]: token
});
const response = new Response(responseBody);
await cache.put(FAKE_ENDPOINT, response);
console.log("Token saved! 🎉");
} catch (error) {
// It's up to you how you resolve the error
console.log("saveToken error:", { error });
}
};
const getToken = async () => {
try {
const cache = await caches.open(CACHE_NAME);
const response = await cache.match(FAKE_ENDPOINT);
if (!response) {
return null;
}
const responseBody = await response.json();
return responseBody[TOKEN_KEY];
} catch (error) {
// Gotta catch 'em all
console.log("getToken error:", { error });
}
};
const displayCachedToken = async () => {
const cachedToken = await getToken();
console.log({ cachedToken });
};
// Uncomment the line below to save the fake token
// saveToken(FAKE_TOKEN);
displayCachedToken();
Without success means no result, i've tried to set data in safari and get them in standalone pwa

Puppeteer-in-electron: Is it possible to open headless browser in puppeteer electron

Is it possible to open headless browser in puppeteer electron?
I am opening the window like this:
const browser = await pie.connect(app, puppeteer);
const page = await pie.getPage(browser, win);
import { app, BrowserWindow } from 'electron'
const pie = require('puppeteer-in-electron')
const puppeteer = require('puppeteer-core')
const browser = await pie.connect(app, puppeteer)
const window = new BrowserWindow({ show: false })
page = await pie.getPage(browser, window)
// ...the rest of the code
Seems it's the only way other than modifying puppeteer-in-electron code

Getting value of input element in Playwright

How do I return the value of elem so that I can verify that it is in fact 1?
const elem = await page.$('input#my-input')
await elem.fill('1')
inputValue method has been added in Playwright v1.13.0
await page.inputValue('input#my-input');
Locator:
await page.locator('input#my-input').inputValue();
It returns input.value for the selected <input> or <textarea> element. Throws for non-input elements. Read more.
The easiest way is to use $eval. Here you see a small example:
const playwright = require("playwright");
(async () => {
const browser = await playwright.chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
await page.setContent(`<input id="foo"/>`);
await page.type("#foo", "New value")
console.log(await page.$eval("#foo", el => el.value))
await page.screenshot({ path: `example.png` });
await browser.close();
})();
From version 1.19 (and probably lower versions) Element Handler is not recomended.
Instead of it use Locator.
page.locator(selector).innerText()
in your case with assertion it will be
expect(page.locator("input#my-input").innerText().includes("1")).toBeTruthy()
Read more on:
https://playwright.dev/docs/api/class-elementhandle#element-handle-fill

Resources