How to get browser console logs when using Browser library in Robotframework - selenium

I'm using Robotframework and Browser library to automate some tasks on the web. I used to use Selenium, and with selenium there is a way to get the logs, for example in the case of a failure:
driver = webdriver.Remote()
logs = driver.get_log('browser')
I've been struggling to find a way to do the same exact thing using Playwright's Browser library. Is it possible?

Certainly. You can use the page.on('console') event to log what appears in the DevTools console. Here's an example of using debug library to do so.
Make sure to export DEBUG=playwright:console or you won't see anything.
Here's how to do it in JS:
const playwright = require('playwright');
const debugConsole = require('debug')('playwright:console');
(async () => {
const browser = await playwright.chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
await page.on('console', (msg) => {
if (msg && msg.text) {
if (typeof msg.text === 'function') {
debugConsole('PAGE LOG:', msg.text());
} else {
debugConsole('PAGE LOG:', msg.text);
}
} else {
debugConsole('PAGE LOG:', msg);
}
});
await page.goto('https://example.com', { waitUntil: 'networkidle' });
})();
And in python:
from playwright.sync_api import sync_playwright
def print_args(msg):
for arg in msg.args:
print(arg.json_value())
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.on("console", print_args)
page.goto("https://abrahamjuliot.github.io/creepjs/", wait_until="networkidle")
page.wait_for_timeout(5000)
browser.close()
If you are looking for more system-level stuff, there is also a dumpio launch parameter that you can set, which will cause Playwright to provide verbose logs on the actual launch of browser executable.

Related

Running Testcafe tests in sequence with html reports

This is not a question. I just want to share my solution for running Testcafe tests in sequence with HTML reports.
Running tests in parallel on different browsers was not a solution for me. I have to wait for tests on one env to finish, then to run on the next env.
It took me a while to figure this out, but it works for me.
If someone has better solution, please inform me.
Just add this code (with your specific custom settings) into a runner file. i.e. runner.js
and run it with node runner.js command.
The solution:
const createTestCafe = require('testcafe');
const fs = require('fs');
const browsers = [
'chrome',
'firefox'
];
let stream = null;
const runTest = async browser => {
console.log('----------------- starting tests on ' + browser);
await createTestCafe('localhost', 1337, 1338)
.then(tc => {
testcafe = tc;
const runner = testcafe.createRunner();
return runner
.src([
"./smokeTests/someTests.js"
])
.browsers(browser)
.reporter('html', stream)
.run();
})
.then(async failedCount => {
console.log('Tests failed: ' + failedCount);
await testcafe.close();
return;
});
}
const runAllBrowsers = async () => {
for (const browser of browsers) {
stream = fs.createWriteStream('./testResults' +'/report_' + browser + '.html');
await runTest(browser);
await testcafe.close();
}
}
runAllBrowsers();
I used the original idea from https://github.com/DevExpress/testcafe/issues/2495.
I'd like to thank nabrahamson for the original idea!
Thank you for sharing this solution with everyone.
You might want to contribute your sample to the testcafe-examples repo as well.

Playwright webkit can't run WebAssembly

I'm trying to run a webpage that calls a .wasm file in playwright webkit
const { webkit } = require('playwright');
(async () => {
const browser = await webkit.launch();
const page = await browser.newPage();
page.on("pageerror", err => {
console.error(err.message)
})
await page.goto('https://wasmbyexample.dev/examples/hello-world/demo/rust/');
})();
However, I get the following page-error:
Unhandled Promise Rejection: ReferenceError: Can't find variable: WebAssembly
Seems that the WebAssembly object within the browser is not even initialized.
Any idea why this is happening?
If it matters, I'm on windows.

Is it possible to send data from client (browser) to puppeteer?

I have been created a server side render by phantomjs before like this.
client side
// when all client ajax request and page render finished
window.callPhantom('page.done')
// when page not found
window.callPhantom('page.fail')
server side
page.onCallback = function(status) {
// when page render finished
if(status == 'page.done') {
// start render
}
// when page not found
else {
// response 404 page not found
}
}
And I wanna change from phantomjs to chrome puppeteer now.
How can I to pass data from the client side (browser) to server(puppeteer) after all client ajax request is finished (like phantomjs callPhantom).
Is it possible do that by using chrome puppeteer?
I had face the same problem as you, this is the solution what I got:
You can use the function page.exposeFunction.
It's going to bind a function into the page window, so you can just evaluate that function in the client side to do something in the Node side.
There's an example in the documentation.
I hope this can helps you.
Use page.evaluate(pageFunction, ...args) to pass data to the page. This example passes a selector string to the page for evaluation:
(async() => {
const puppeteer = require('puppeteer')
const browser = await puppeteer.launch()
const page = await browser.newPage()
page.on('console', msg => {
for (let i = 0; i < msg.args().length; ++i)
console.log(`${i}: ${msg.args()[i]}`);
});
await page.goto('https://google.com/')
await page.evaluate(selector => {
const el = document.querySelector(selector);
console.log(el.src)
}, 'img#hplogo');
await browser.close()
})();

Upload a file with puppeteer in Jest

I am using Jest and have puppeteer set up as in this repository, which is linked to from the Jest documentation.
I am trying to write some automated smoke tests on a WordPress website using puppeteer. One of the tests attempts to upload an image to the WordPress Media Library.
This is the test:
it('Create test media', async () => {
// go to Media > Add New
await page.goto(`${env.WP_HOME}/wp/wp-admin/media-new.php`)
const display = await page.evaluate(() => {
const el = document.querySelector('#html-upload-ui')
return window.getComputedStyle(el).display
})
if (display !== 'block') {
// ensure we use "built-in uploader" as it has `input[type=file]`
await page.click('.upload-flash-bypass > a')
}
const input = await page.$('#async-upload')
await input.uploadFile(testMedia.path)
})
The file input field's value is populated as expected (I know this because if I save out a screenshot after the call to uploadFile it shows the path of the file in the input), and the form is submitted, however when I go to view the media library there are no items.
I have tried the following amendments to the uploadFile part of the test, to no avail:
// 1. attempt to give time for the upload to complete
await input.uploadFile(testMedia.path)
await page.waitFor(5000)
// 2. attempt to wait until there is no network activity
await Promise.all([
input.uploadFile(testMedia.path),
page.waitForNavigation({waitUntil: 'networkidle0'})
])
// 3. attempt to submit form manually (programmatic)
input.uploadFile(testMedia.path)
page.evaluate(() => document.querySelector('#file-form').submit())
await page.waitFor(5000) // or w/ `waitForNavigation()`
// 4. attempt to submit form manually (by interaction)
input.uploadFile(testMedia.path)
page.click('#html-upload')
await page.waitFor(5000) // or w/ `waitForNavigation()`
The problem is that file uploading doesn't work when connecting to a Browser instance via WebSocket as in jest-puppeteer-example. (GitHub issue here: #2120.)
So instead of doing that just use puppeteer.launch() directly when setting up your test suite (instead of via the custom "Jest Node environment"):
let browser
, page
beforeAll(async () => {
// get a page via puppeteer
browser = await puppeteer.launch({headless: false})
page = await browser.newPage()
})
afterAll(async () => {
await browser.close()
})
You also then have to manually submit the form on the page, as in my experience uploadFile() doesn't do this. So in your case, for the WordPress Media Library single file upload form, the test would become:
it('Create test media', async () => {
// go to Media > Add New
await page.goto(`${env.WP_HOME}/wp/wp-admin/media-new.php`)
const display = await page.evaluate(() => {
const el = document.querySelector('#html-upload-ui')
return window.getComputedStyle(el).display
})
if (display !== 'block') {
// ensure we use the built-in uploader as it has an `input[type=file]`
await page.click('.upload-flash-bypass > a')
}
const input = await page.$('#async-upload')
await input.uploadFile(testMedia.path)
// now manually submit the form and wait for network activity to stop
await page.click('#html-upload')
await page.waitForNavigation({waitUntil: 'networkidle0'})
})

How to test an Electron app with selenium webdriver

I have read the documentation and I have followed the tutorial step by step and I only have managed to run the app.
Documentation: http://electron.atom.io/docs/tutorial/using-selenium-and-webdriver/
The connection with chromedriver I cannot make it work, when I launch the test and try click a simple button I get this:
Error: ChromeDriver did not start within 5000ms at Error (native)
at node_modules/spectron/lib/chrome-driver.js:58:25 at
Request._callback (node_modules/spectron/lib/chrome-driver.js:116:45)
at Request.self.callback
(node_modules/spectron/node_modules/request/request.js:200:22) at
Request.
(node_modules/spectron/node_modules/request/request.js:1067:10) at
IncomingMessage.
(node_modules/spectron/node_modules/request/request.js:988:12) at
endReadableNT (_stream_readable.js:913:12) at _combinedTickCallback
(internal/process/next_tick.js:74:11) at process._tickCallback
(internal/process/next_tick.js:98:9)
My code:
"use strict";
require("co-mocha");
var Application = require('spectron').Application;
var assert = require('assert');
const webdriver = require('selenium-webdriver');
const driver = new webdriver.Builder()
.usingServer('http://127.0.0.1:9515')
.withCapabilities({
chromeOptions: {
binary: "./appPath/app"
}
})
.forBrowser('electron')
.build();
describe('Application launch', function () {
this.timeout(100000);
var app;
beforeEach(function () {
app = new Application({
path: "./appPath/app"
});
return app.start();
});
afterEach(function () {
if (app && app.isRunning()) {
return app.stop();
}
});
it('click a button', function* () {
yield driver.sleep(5000);
yield driver.findElement(webdriver.By.css(".classSelector")).click();
});
});
Thanks and sorry for my English.
I recommend you to use Spectron. which is a less painful way of testing your electron app. in my opinion perfect combination is using it with Ava test framework, which allows the concurrently test.
async & await is also another big win. which allows you to have so clean test cases.
and also if you have a test which needs to happen serial, you can use test.serial
test.serial('login as new user', async t => {
let app = t.context.app
app = await loginNewUser(app)
await util.screenshotCreateOrCompare(app, t, 'new-user-mission-view-empty')
})
test.serial('Can Navigate to Preference Page', async t => {
let app = t.context.app
await app.client.click('[data-test="preference-button"]')
await util.screenshotCreateOrCompare(app, t, 'new-user-preference-page-empty')
})
and just for reference; my helper test cases.
test.before(async t => {
app = util.createApp()
app = await util.waitForLoad(app, t)
})
test.beforeEach(async t => {
t.context.app = app
})
test.afterEach(async t => {
console.log('test complete')
})
// CleanUp
test.after.always(async t => {
// This runs after each test and other test hooks, even if they
failed
await app.client.localStorage('DELETE', 'user')
console.log('delete all files')
const clean = await exec('rm -rf /tmp/DesktopTest')
await clean.stdout.on('data', data => {
console.log(util.format('clean', data))
})
await app.client.close()
await app.stop()
})
util function,
// Returns a promise that resolves to a Spectron Application once the app has loaded.
// Takes a Ava test. Makes some basic assertions to verify that the app loaded correctly.
function createApp (t) {
return new Application({
path: path.join(__dirname, '..', 'node_modules', '.bin',
'electron' + (process.platform === 'win32' ? '.cmd' : '')),
// args: ['-r', path.join(__dirname, 'mocks.js'), path.join(__dirname, '..')],
env: {NODE_ENV: 'test'},
waitTimeout: 10e3
})
}
First off, Spectron (which is a wrapper for WebdriverIO) and WebdriverJS (which is part of Selenium-Webdriver) are two different frameworks, you only need to use one of them for your tests.
If you are using WebdriverJS, then you need to run ./node_modules/.bin/chromedriver in this step: http://electron.atom.io/docs/tutorial/using-selenium-and-webdriver/#start-chromedriver
I could get ChromeDriver working by adding a proxy exception in my terminal.
export {no_proxy,NO_PROXY}="127.0.0.1"