I use selenium in javascript along with jest to do some end-to-end testing of an application. Eventually those tests runs in headless mode on Azure Pipelines
To help debugging, I would like to have a video record in case a test fails. I could not find any package which would work with jest and selenium.
I already managed to upload a screenshot in case of failure so I have takeScreenshot working.
For the video, I wanted to try to take a picture every second before "compiling" it with ffpmeg but I have a memory issue.
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
Am I on the right track?
public async startRecording() {
this.recording = true;
let count = 1;
let interval;
while (this.recording) {
interval = setInterval(async () => {
await this.takeScreenshot(`test_${count}`);
count += 1;
}, 1000);
}
clearInterval(interval);
}
public stopRecording() {
this.recording = false;
}
Related
I have a create-react-app that reads and writes local files using File System Access API. When run in a browser (Chrome or Edge that support it), both reading and writing files work fine.
When the app is run in Electron, reading works but writing fails due to: Uncaught (in promise) DOMException: The request is not allowed by the user agent or the platform in the current context.
I am using the latest Electron (12.0.1) which uses the same Chromium (89.0.4389.82) as the one in my Chrome browser.
Below is the relevant code. The console log after requestPermission call shows true and granted in the browser and true and denied in Electron.
I tried disabling webSecurity when creating BrowserWindow, disabling sandbox with appendSwitch but nothing helped.
Is there a way to give Chromium in Electron more permissions?
If not, I am willing to handle file writing differently when in Electron. In that case, what to write in place of TODO in the code? Note that because it is a create-react-app, the fs module is not available.
export async function chooseAndReadFile() {
const fileHandle = await window.showOpenFilePicker().then((handles) => handles[0])
const file = await fileHandle.getFile()
const contents = await file.text()
return contents
}
export async function chooseAndWriteToFile(contents: string) {
const fileHandle = await window.showSaveFilePicker()
const descriptor: FileSystemHandlePermissionDescriptor = {
writable: true,
mode: "readwrite"
}
const permissionState = await fileHandle.requestPermission(descriptor)
console.log(window.isSecureContext)
console.log(permissionState)
const writable = await fileHandle.createWritable()
await writable.write(contents)
await writable.close()
}
let isElectron = require("is-electron")
export async function chooseAndWriteToFileUniversal(contents: string) {
if (isElectron()) {
// TODO: Do what???
} else {
chooseAndWriteToFile(contents)
}
}
Answering my own question, I finally used a solution with HTML download attribute, nicely described here. When this technique is used in Electron, it presents a file save dialog which is exactly what I want. When used in a browser, this technique just downloads the file without a prompt, so I will continue using File System Access API for browser environments.
Here is the code that handles downloading when running in Electron.
function download(filename: string, contents: string) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(contents));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
let isElectron = require("is-electron");
export async function chooseAndWriteToFileUniversal(contents: string) {
if (isElectron()) {
download("data.txt", contents)
} else {
chooseAndWriteToFile(contents) // See the original question for implementation of this function
}
}
Still, would be nice to know why/how is Chromium in Electron more restricted than in a normal Chrome or Edge browser, and if it can be changed.
I am trying to write UI automation scripts to perform the automated testing of a vs code extension. After reading tutorials about spectron/ vs code test, I found that they both need source code to perform tests. I am trying to perform from a QA side and hence I have the extension installed on my vs code but now I need to perform automation.
I am able to launch vs code and open the extension using selenium-webdriver but cannot access the elements that are loaded under vs code web view. VS code hides the web element for the extension and hence selenium-webdriver cannot find the elements.
{ describe, it, after, before } require('mocha');
// const Config = require('../../config/config.json');
const webdriver = require('selenium-webdriver'),
By = webdriver.By
const assert = require('chai').assert
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
try{
describe('Launch VS Code', function(){
this.timeout(20000);
let driver= new webdriver.Builder()
// The "9515" is the port opened by chrome driver.
.usingServer('http://localhost:9515')
.withCapabilities({
chromeOptions: {
// Here is the path to your Electron binary"
binary: 'path to vs code'
}
})
.forBrowser('electron')
.build();
it('open extension', async function(){
await driver.findElement(By.xpath(".//div[contains(#aria-label,'View')]")).click()
await driver.findElement(By.xpath("//*[text()='Command Palette...']")).click()
await driver.findElement(By.className('input')).sendKeys('extensionname')
await driver.findElement(By.xpath("//*[contains(text(),'extensionname')]")).click()
await sleep(5000)
await driver.findElement(By.xpath("//*[contains(#title,'extension title')]")).click()
var title =await driver.getTitle()
assert.equal(title,'extensiontitle')
await sleep(5000)
await driver.switchTo().frame(driver.findElement(By.tagName('iframe')))
await driver.getPageSource().then(function(tmptext){
console.log(tmptext.includes('extension web element'))
})
});
})
}
catch(ex){
console.log(ex)
}
the code should be able to find the web driver and complete the test.
I have a Stripe integration in a React web front-end. My payment component attempts to run…
componentDidLoad() {
if ( window.hasOwnProperty('Stripe') ) {
this.setState({stripe: window.stripe(config.stripeKey)})
}
}
This sporadically fails as sometimes the React app will boot and get the component loaded before window.stripe exists. I’m currently resolving this with…
componentDidLoad() {
this.watchStripe = setInterval( () => {
if (!props.stripe && isBrowser && window.Stripe) {
this.setState({stripe: window.stripe(config.stripeKey)})
clearInterval(this.watchStripe)
}
}, 100)
}
Is there a more elegant solution to this, something that doesn't require an interval timer?
If you read the Advanced integrations section they suggest doing
componentDidMount() {
if (window.Stripe) {
this.setState({stripe: window.Stripe('pk_test_12345')});
} else {
document.querySelector('#stripe-js').addEventListener('load', () => {
// Create Stripe instance once Stripe.js loads
this.setState({stripe: window.Stripe('pk_test_12345')});
});
}
}
This adds an event listener for the load event on the script element that loads Stripe and sets the state when it is available (so no continuous polling with setInterval,setTimeout is needed)
I am using cucumber-js to run tests with selenium-webdriver.
I want to add a screenshot capture of the browser when any step times out.
I am using global timeout for all the steps as:
this.setDefaultTimeout(3 * 60 * 1000);
in my hooks file.
How do I register to the global timeout event (if such even exists)?
Selenium Webdriver js do provide function to get screenshot, you just need to use it in After, which is similar to #AfterClass tag in TestNG
The After scenario will execute after every scenario in Feature and check the result of the Scenario, it it is FAILED it will take the screenshot.
The reason for failure can be anything, like a bug, or DEFAULT_TIMEOUT
You need to add this in your world.js
this.After(function (scenario) {
if (scenario.isFailed()) {
// take a screenshot
// driver.takeScreenshot() is defined in webDriver.js
return driver.takeScreenshot()
.then(function (screenShot) {
scenario.attach(new Buffer(screenShot, 'base64'), 'image/png');
return driver.close()
.then(function () {
return driver.quit();
});
});
}
else {
return driver.close()
.then(function () {
return driver.quit();
});
}
});
I have built a sencha application using Sencha cmd.
I have integrated it to windows phone using cordova.
Now, when launching the app, after splash screen, a white screen comes and stays for ever.
I trying putting an alert in the launch function (in app.js where view is created) and found out that the launch function does not fire.
What could be the reason of this behaviour?
I found the cause of the issue that I was facing. The sencha app is using a store with SQL proxy. But since SQL proxy is not supported on Windows phone (but supported on other platforms viz. iOS, Android), so the launch function was not getting called.
I had a similar problem with a JSON proxy and I had to modify the following lines of code in cordovalib/XHRHelper.cs file.
var funk = function () {
window.__onXHRLocalCallback = function (responseCode, responseText) {
alias.status = responseCode;
if (responseCode == '200') {
alias.responseText = responseText;
try {
JSON.parse(responseText);
} catch (e) {
Object.defineProperty(alias, 'responseXML', {
get: function () {
return new DOMParser().parseFromString(this.responseText, 'text/xml');
}
});
}
Object.defineProperty(alias, 'responseJSON', {
get: function () {
return new DOMParser().parseFromString(this.responseText, 'text/json');
}
});
}else {
alias.onerror && alias.onerror(responseCode);
}