How to handle Negative test cases in playwright - playwright

Say example for Login case, how to handle p/w / username error msg thrown properly on providing invalid input. As a newbie, I need to look into examples. Kindly share
const { webkit } = require("playwright");
(async () => {
const browser = await webkit.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.goto("https://stackoverflow.com/users/login");
await page.click("button.s-btn__google");
await page.fill('input[type="email"]', process.env.GOOGLE_USER);
await page.click("#identifierNext");
await page.fill('input[type="password"]', process.env.GOOGLE_PWD);
await page.click("#passwordNext");
await browser.close();
})();

Related

Using ipcRenderer with contextBridge

I want use contextBridge in my preload.js in electron. Every work as usual when when i send data from the ipcrender-to-ipcmain, but problem arises when i send response from ipcmain-to-ipcrenderer. I have gone through some of there solutions here but i still get the same results.
This is my mainjs code
ipcMain.on('users:load', async function () {
const users = await User.getAll();
win.webContents.send('users:get', users);
});
(async function () {
try {
const rows = await User.getAll();
console.log(rows.length);
win.webContents.send('users:total', rows.length);
} catch (error) {
return console.log(error);
}
})();
This is my preload.js
contextBridge.exposeInMainWorld('UserApi', {
loginuser: (user) => ipcRenderer.invoke('user:login', user),
totalusers: () =>
ipcRenderer.on('user:total', (e, res) => {
return res;
}),
loadUsers: () => {
ipcRenderer.send('users:load', () => {
ipcRenderer.on('users:get', (e, users) => {
return users;
});
});
},
});
In my preload.js ipcRenderer.invoke works perfectly but ipcRenderer.on does not. Any help will be appreciated.

Error while using getVideoDurationInSeconds function from the “get-video-duration” library

I’m trying to create a video player using electronjs. I couldn’t get the video duration directly using node.js so I had to use a library called “get-video-duration”.
But whenever I’m trying to use the getVideoDurationInSeconds() function, It’s throwing an error.
Here Is The Error:
(node:12468) UnhandledPromiseRejectionWarning: Error: No duration
found!
at D:\Projects\Electronjs\video-player\node_modules\get-video-duration\dist\commonjs\index.js:83:27
at step (D:\Projects\Electronjs\video-playerr\node_modules\get-video-duration\dist\commonjs\index.js:33:23)
at Object.next (D:\Projects\Electronjs\video-player\node_modules\get-video-duration\dist\commonjs\index.js:14:53)
at fulfilled (D:\Projects\Electronjs\video-player\node_modules\get-video-duration\dist\commonjs\index.js:5:58)
at processTicksAndRejections (node:internal/process/task_queues:96:5) (Use electron --trace-warnings ... to show where the warning was created) (node:12468) UnhandledPromiseRejectionWarning: Unhandled promise
rejection. This error originated either by throwing inside of an async
function without a catch block, or by rejecting a promise which was
not handled with .catch(). To terminate the node process on unhandled
promise rejection, use the CLI flag --unhandled-rejections=strict
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode).
(rejection id: 1)
Here Is The Code:
const { app, BrowserWindow, ipcMain, dialog } = require("electron");
const { getVideoDurationInSeconds } = require("get-video-duration");
const path = require("path");
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
mainWindow.loadFile(path.join(__dirname, "index.html"));
mainWindow.webContents.openDevTools();
};
app.on("ready", createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
ipcMain.on("select-file", async (e, i) => {
const { filePaths } = await dialog.showOpenDialog();
let duration;
getVideoDurationInSeconds(filePaths[0]).then((Duration) => {
duration = Duration;
});
e.reply("select-file-reply", {
url: filePaths,
duration: duration,
});
});

Puppeteer in Electron: Error: Passed function is not well-serializable

Trying to come up with a GUI for Puppeteer project.
I thought about using Electron, but run into error:
Error: Passed function is not well-serializable!
when running Puppeteer functions like:
await page.waitForSelector('.modal', { visible: true });
I found a proper way to serialize when dealing with page.evaluate() but how to proceed in case of page.waitForSelector()?
Is there a work around for Puppeter's API functions to be properly serialized when required?
EDIT
I decided to rewrite
await page.waitForSelector('.modal', { visible: true });
using page.evaluate, here is the code:
// first recreate waitForSelector
const awaitSelector = async (selector) => {
return await new Promise(resolve => {
const selectorInterval = setInterval(() => {
if ($(selector).is(':visible')) {
console.log(`${selector} visible`);
resolve();
clearInterval(selectorInterval);
};
}, 1000);
});
}
and later call that function using page.evaluate():
// remember to pass over selector's name, in this case it is ".modal"
await page.evaluate('(' + awaitSelector.toString() + ')(".modal");');
Firstly context:
Generally you can not run puppeteer from browser environment, it works solely in nodejs. Electron provides 2 processes renderer and main. Whenever you want to use node you have to do it in main one.
About communication between both procesess you can read in docs, there are many ways of handling it. From what I know the best practice is to declare it in preload and use ipc bridge. Other solutions violate contextIsolation rule.
I was w wandering aound from one problem to another: like not serializable function, require not defined and many others.
Finally I rewrote everything from scratch and it works here's my solution:
main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
const { ipcMain } = require('electron');
const puppeteer = require("puppeteer");
function createWindow() {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
contextIsolation: true,
},
})
ipcMain.handle('ping', async () => {
await checkPup()
})
async function checkPup() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
page
.waitForSelector('h1', { visible: true })
.then(() => {
console.log('got it')
});
const [button] = await page.$x("//button[contains(., 'Create account')]");
if (button) {
console.log('button: ', button)
await button.click();
await page.screenshot({ path: 'tinder.png' });
const [button] = await page.$x("//button[contains(., 'Create account')]");
if (button) {
console.log('button: ', button)
await button.click();
await page.screenshot({ path: 'tinder.png' });
}
}
await browser.close();
}
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// Attach listener in the main process with the given ID
ipcMain.on('request-mainprocess-action', (event, arg) => {
// Displays the object sent from the renderer process:
//{
// message: "Hi",
// someData: "Let's go"
//}
console.log(
arg
);
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
preload.js
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
const { contextBridge, ipcRenderer } = require('electron')
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})
contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
ping: () => ipcRenderer.invoke('ping'),
// we can also expose variables, not just functions
})
renderer.js
const information = document.getElementById('info')
const btn = document.getElementById('btn')
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`
btn.addEventListener('click', () => {
console.log('habad!!!!!')
func()
})
const func = async () => {
const response = await window.versions.ping()
information.innerText = response;
console.log(response) // prints out 'pong'
}
Sorry for a little bit of a mess I hope it will help someone maybe finding solutions to some other problems

Dust.js and helmet - not rendering HTML

I have a Dust.js template and want to use it as async mode (so stream), to load my stuff.
It works very well, but when I add use(helmet()) it does not show as html anymore, just as plain text
I tried using dust.stream, tried hoffman, tried adaro. nothing works, the second helmet is introduced, it does not work.
hoffman
hoffman = require('hoffman'),
express = require('express'),
helmet = require('helmet'),
request = require('request');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'dust');
app.engine('dust', hoffman.__express());
app.use(helmet());
// This is the important part-- it adds res.stream()
app.use(hoffman.stream);
app.get('/', function (req, res) {
res.stream("hello", {
"async": function(chunk, context, bodies, params) {
return chunk.map(function(chunk) {
// Introducting an artificial delay to make streaming more apparent
setTimeout(function() {
request('http://www.dustjs.com/')
.on('data', chunk.write.bind(chunk))
.on('end', chunk.end.bind(chunk));
}, 3000);
});
}
});
});
const port = process.env.PORT | 3007;
app.listen(port, function () {
console.log(`Visit http://localhost:${port} to see streaming!`);
});
Dust.stream:
var fs = require('fs'),
path = require('path'),
express = require('express'),
request = require('request'),
helmet = require('helmet'),
dust = require('dustjs-linkedin');
dust.config.whitespace = true;
dust.config.cache = false;
// Define a custom `onLoad` function to tell Dust how to load templates
dust.onLoad = function(tmpl, cb) {
fs.readFile(path.join('./views', path.relative('/', path.resolve('/', tmpl + '.dust'))),
{ encoding: 'utf8' }, cb);
};
var app = express();
app.use(helmet());
app.get('/streaming', function(req, res) {
dust.stream('hello', {
"async": request('http://www.dustjs.com/')
}).pipe(res)
.on('end', function() {
console.log('Done streaming!');
});
});
app.get('/rendering', function(req, res) {
dust.render('hello', {
"async": request('http://www.dustjs.com/')
}, function(err, out) {
res.send(out);
console.log('Done rendering!');
});
});
const port = process.env.PORT | 3002;
app.listen(port, function () {
console.log(`Visit http://localhost:${port} to see streaming!`);
});
When not using helmet, the html is rendered, when adding helmet, no rendering is done, and I see the html page as text
Ok, so dust does a nice job with async.
The bit I was missing was:
res.setHeader('Content-Type', 'text/html; charset=utf-8');
and now it works with helmet!

cannot read property 'request' of undefined in electron

When I try to use net.request, it returns an error "cannot read property 'request' of undefined in electron".
This is my code for main.js
const electron = require('electron');
const {app, Menu} = electron;
const {BrowserWindow} = require('electron');
var mainWindow = null;
app.on('ready', function(){
mainWindow = new BrowserWindow({
width: 500,
height: 300
});
mainWindow.loadURL('file://' + __dirname + '/index.html');
mainWindow.openDevTools();
mainWindow.setMenu(null);
mainWindow.on('closed', function () {
mainWindow = null;
});
const {net} = require('electron');
const request = net.request('https://github.com');
request.on('response', (response) => {
console.log('STATUS: ${response.statusCode}')
console.log('HEADERS: ${JSON.stringify(response.headers)}');
response.on('data', (chunk) => {
console.log('BODY: ${chunk}');
});
response.on('end', () => {
console.log('No more data in response.');
});
});
request.end();
});
I couldn’t find what went wrong. Can any suggest a solution for this? any help will be appreciated
It doesn't throw me error on 1.4.5
[Highlight of comment:]
Also, based on the release notes, net api is available only from 1.4.5 on https://github.com/electron/electron/releases/tag/v1.4.5

Resources