I am using foreach to run the test for multiple users.
I can access the variable from foreach inside of beforeAll, but does not work inside of test
the following line does not get the value as expected, i verified i have value for that column in the .csv
await page.locator('#searchByCode').fill(${user.Code}); // Does not Work , get undefined
import fs from 'fs';
import path from 'path';
import { test, expect, Page } from '#playwright/test';
import { parse } from 'csv-parse/sync'; //requires https://www.npmjs.com/package/csv-parse
const users = parse(fs.readFileSync(path.join(__dirname, '../users.csv')), {
columns: true,
skip_empty_lines: true
});
//Want test inside of describe to run in serial mode
test.describe.configure({ mode: 'serial' });
test.use({ viewport: { width: 600, height: 900 } }); //Affects all Tests
let page: Page;
users.forEach(user => {
console.log(user.Email);
test.describe(`Login for user ${user.Email}`, () => {
test.beforeAll(async ({ browser }) => {
// Create page once and sign in.
page = await browser.newPage();
await page.goto('https://XXXXXXX.com');
await page.fill("#logInEmail",`${user.Email}`); **//This one works**
//find password text(#loginInPassword) and enter password
await page.fill('#loginInPassword', `${user.Password}`); **//This one works**
await Promise.all([
page.waitForNavigation(/*{ url: 'https://getinline.net/' }*/),
page.locator('#loginSignIn').click()
]);
});
test.afterAll(async () => {
await page.close();
});
test('SearchBusinessByCode', async ({ browser }, testInfo) => {
await page.locator('#searchByCode').fill(`${user.Password}`); **// Does not Work , get undefined**
await page.locator('button', { hasText: 'Search' }).click();
});
});
}); //forEach
Related
I try to write E2E test with playwright but something is wrong.
When I was initialize the test, test passed but actually, block did not go inside the bracket.
It also passes the test when I enter the wrong selector.
The code is below:
import { _electron as electron } from 'playwright';
import { test, expect, ElectronApplication, Page, BrowserContext, Locator } from '#playwright/test';
test.describe('Add Connection', async() => {
let electronApp: ElectronApplication;
let firstWindow: Page;
let context: BrowserContext;
test.beforeAll(async() => {
electronApp = await electron.launch({ args: ['.']} );
const appPath = await electronApp.evaluate(async({ app }) => {
return app.getAppPath();
});
console.log(appPath);
});
test('Try Connection', () => {
electronApp.on('window', async(page) => {
await page.getByTestId('settings').click({delay: 1000});
await page.getByTestId('connection').click({delay: 1000});
});
});
test.afterAll(async() => {
await electronApp.close();
});
});
I haven't seen enough documentation about E2E testing on Electron. How can we write a test where we can go to different pages by clicking on the buttons?
I solved this problem. The inside of 'Try Connection' test doesn't work because electronApp.on() is a callback function.
To write ElectronJS & Playwright test I choose these steps:
I got a Page object (firstWindow) after that I clicked on the buttons and went to the place I wanted to test.
The final code:
import { _electron as electron } from 'playwright';
import { test, expect, ElectronApplication, Page } from '#playwright/test';
test.describe('Add Connection', async() => {
let electronApp: ElectronApplication;
let firstWindow: Page;
test.beforeAll(async() => {
electronApp = await electron.launch({ args: ['.']} );
firstWindow = await electronApp.firstWindow();
});
test('Try Connection', async() => {
await firstWindow.title();
await firstWindow.click('xpath=//*[#id="sidemenu-container"]/a[3]', {delay: 1500});
await firstWindow.click('xpath=//*[#id="***"]/app-settings/div/div[1]/button[1]', {delay: 1500});
await firstWindow.click('xpath=//*[#id="***"]', {delay: 1500});
await firstWindow.getByPlaceholder('***').fill('emir connection');
await firstWindow.locator('#***').selectOption({label: '***'});
await firstWindow.click('xpath=//*[#id="***"]', {delay: 2000});
// for the wait, (fake click)
await firstWindow.click('xpath=//*[#id="***"]', {delay: 7000});
});
test.afterAll(async() => {
await electronApp.close();
});
});
I want to send parallel POST requests in puppeteer. I have to change the payload with every request (URL remains the same).
I tried using puppeteer cluster, but how do I change payload with every request when I queue the same request?
Using normal puppeteer
(async() => {
const browser = await puppeteer.launch({
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-web-security",
],
executablePath: 'C:/Program Files/..',
headless: false,
});
for(const id of Ids) {
const page = await browser.newPage();
await page.setDefaultNavigationTimeout(60000);
await page.evaluateOnNewDocument(() => {
// Some code
})
await page.setRequestInterception(true);
// Request intercept handler... will be triggered with
// each page.goto() statement
page.on('request', interceptedRequest => {
// Here, is where you change the request method and
// add your post data
var data = {
'method': 'POST',
'postData': JSON.stringify({
....
"similarMaterialId": `${id}`,
}),
'headers': {
.....
},
};
// Request modified... finish sending!
interceptedRequest.continue(data);
});
const response = await page.goto('https://.../getProductInfo');
const responseBody = await response.json();
try {
let title = responseBody.description;
let price = responseBody.price;
fs.appendFile('temp.tsv', `${title}\t${price}\n`, function (err) {
if (err) throw err;
})
}
catch {
console.log(id)
}
await page.close();
}
console.log("Code ended!!")
await browser.close();
})();
I want to create many pages in parallel on a single browser.
I'm trying to screenshot a website using puppeteer, and on slow sites I receive a TimeoutError.
In this case, I'd like to get the screenshot of the current page state - is this possible? if so, how?
Code sample:
const puppeteer = require('puppeteer');
let url = "http://...";
let timeout = 30000;
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page
.goto(url, {waitUntil: 'load', timeout: timeout}).then(async () => {
await page
.screenshot({path: 'example.png'})
.catch(error => console.error(error));
})
.catch(error => {
if (error.name === "TimeoutError") {
// -----> calling await page.screenshot({path: 'example.png'}) gets stuck
} else {
console.error(error);
}
});
await browser.close();
})();
Don't use browser.close when using puppeteer in development, as this may cause the browser closed and puppeteer crashed.
const puppeteer = require('puppeteer')
let url = "https://www.tokopedia.com"
let filename = 'timeout.png'
let timeoutNum = 30000
;(async () => {
const browser = await puppeteer.launch({
headless: false
});
const [page] = await browser.pages ()
page.setViewport ({ width: 1366, height: 768 })
try {
await page.goto(url, {waitUntil: 'networkidle0', timeout: timeoutNum}).then(async () => {
await page.screenshot({ path: 'example.png', fullPage: true })
})
} catch (error) {
if (error.name === "TimeoutError") {
console.log (error.name)
console.log (`Screenshot saved as ${filename}`)
await page.screenshot({ path: filename, fullPage: true })
} else {
console.log (error)
}
}
})()
I want to test my Electron application but I feel this is harder than I expected!
Just a simple thing as using the open file dialog seems impossible from what I've seen when I looked around a while!
Is it at all possible, or can I mock this behavior somehow?
My application adds the selected files to a file list and shows some result in a grid. If I can't open files I wont get the grid and can't test if it behaves as expected.
How should I approach this issue if I can't use the file dialog?
This is my test setup:
import { Application } from "spectron";
import { expect } from "chai";
describe("Application", function() {
this.timeout(10000);
let app: Application;
let browser: any;
before(async () => {
app = new Application({
path: electronPath,
args: [appPath],
});
await app.start();
browser = app.client;
await browser.waitUntilWindowLoaded();
});
after(() => {
await app.stop();
});
it("Starts application", async () => {
const count = await browser.getWindowCount();
expect(count).to.equal(1);
});
it("should add files", async function() {
await browser.click("#block-container > div.button-row > div:nth-child(1) > button:nth-child(1)");
// ???
});
});
And this is the addFiles method:
public addFiles() {
const selectedFiles: string[] = this.electronService.remote.dialog.showOpenDialogSync({
title: "Add files",
properties: ["openFile", "multiSelections"]
});
...
}
I'm trying to implement OAuth2 authentication in Angular 2 ( Electron ) application.
I achieve that on the way with a popup that is called after user click on 'Sign In' button.
In popup user types their credentials and allows the access and on confirm code is returned and I'm able to catch redirect request which I can't do without popup.
Here is implementation that works:
return Observable.create((observer: Observer<any>) => {
let authWindow = new electron.remote.BrowserWindow({ show: false, webPreferences: {
nodeIntegration: false
} });
authWindow.maximize();
const authUrl = AUTHORIZATION_WITH_PROOF_KEY_URL
+ `?client_id=${CLIENT_ID}&response_type=code&scope=api_search&`
+ `redirect_uri=${REDIRECT_URL}&code_challenge=${challenge}&code_challenge_method=S256`;
if (this.clearStorage) {
authWindow.webContents.session.clearStorageData({}, () => {
this.clearStorage = false;
authWindow.loadURL(authUrl);
authWindow.show();
});
} else {
authWindow.loadURL(authUrl);
authWindow.show();
}
authWindow.webContents.on('did-get-redirect-request', (event, oldUrl, newUrl) => {
const code = this.getCode(newUrl, authWindow);
if (!code) {
this.clearStorage = true;
return;
}
this.requestToken({
grant_type: 'authorization_code',
code: code,
code_verifier: verifier,
redirect_uri: REDIRECT_URL
})
.subscribe((response: { access_token: string, refresh_token: string }) => {
observer.next(response);
});
});
// Reset the authWindow on close
authWindow.on('close', () => {
authWindow = null;
});
});
and as you can see in above code I'm creating new BrowserWindow with:
new electron.remote.BrowserWindow({ show: false, webPreferences: {
nodeIntegration: false
} });
and with that approach I'm able to catch up redirect request with a block of code that starts with:
authWindow.webContents.on('did-get-redirect-request', (event, oldUrl, newUrl) => {
....
}
but I'm not able to solve this without popup ( modal ).
Here is my attempt:
return Observable.create((observer: Observer<any>) => {
let authWindow = electron.remote.getCurrentWindow();
const authUrl = AUTHORIZATION_WITH_PROOF_KEY_URL
+ `?client_id=${CLIENT_ID}&response_type=code&scope=api_search&`
+ `redirect_uri=${REDIRECT_URL}&code_challenge=${challenge}&code_challenge_method=S256`;
if (this.clearStorage) {
authWindow.webContents.session.clearStorageData({}, () => {
this.clearStorage = false;
authWindow.loadURL(authUrl);
});
} else {
authWindow.loadURL(authUrl);
}
authWindow.webContents.on('did-get-redirect-request', (event, oldUrl, newUrl) => {
debugger;
// this is not called, I'm not able to catch up redirect request
});
// Reset the authWindow on close
authWindow.on('close', () => {
authWindow = null;
});
});
With my approach I get login screen from remote URL in a current window, but the problem is that I'm not able to catch redirect request with ('did-get-redirect-request') event.
I also tried with 'will-navigate' and many others.
Although I don't have a direct answer I thought I'd point you to Google's AppAuth-JS libraries, which cover OAuth based usage for Electron Apps.
My company have used AppAuth libraries for the mobile case and they worked very well for us, so that we wrote less security code ourselves and avoided vulnerabilities.
There is also an Electron Code Sample.