File Upload Testing in Nightwatch.js - selenium

I'd like to reopen the question posed here and here about testing file uploading within Nightwatch.js which uses selenium.
Both links have the recommended solution of setting the value of the file input element as the url. In my use case, I've been unable to get this to work. Even setting the value tag manually, outside of nightwatch, of the input where type="file", does not change the url. I've tried this on Chrome, Firefox, and IE10, within the dev tools.
An alternative solution I've looked at was trying to emulate the entire file upload process keystrokes. This would follow the path of clicking the file upload button, typing the path, and typing enter. This would be done through the .click and .key methods. However, you lose focus of the actual file upload window, which delays the keystrokes until that window is closed. Other developers have seemed to be able to fix this solution directly in selenium using the .findElement and .sendKeys methods in java, but I could not figure out how to do this within javascript and nightwatch itself.
Any ideas?
// My test
module.exports = {
"Standard File Upload" : function (browser) {
browser
.url("http://localhost:3000")
.waitForElementVisible('body', 1000)
.waitForElementVisible('input[type="file"]', 1000)
.setValue('input[type="file"]','http://localhost:3000/testfile.txt')
.click('#submit')
.pause(1000)
.assert.containsText('h3', 'File Uploaded Successfully')
.end();
}
};
// http://localhost:3000/testfile.txt was tested manually in the file upload window and worked successfully
<!-- My input tag -->
<input id="fileUpload" type="file" name="textfile"/>

There were two seperate issues with my setValue() method implementation.
Using the --verbose tag in the nightwatch command led me to an issue
where it was not actually finding the input tag during the
setValue(), however it was during the waitForElementVisible().
Changing input[type="file"] to input#fileUpload solved this
issue.
Secondly, the following ways of describing the path were not working...
'textfile.txt'
'http://localhost:3000/testfile.txt' (Will work if typed manually into file upload window)
What did work was using require('path').resolve(__dirname + '/testfile.txt')
Take a look here to see the discussion that led to the fix. Thanks goes out to richard-flosi.
The working code:
module.exports = {
"Standard File Upload" : function (browser) {
browser
.url("http://localhost:3000")
.waitForElementVisible('body', 1000)
.waitForElementVisible('input#fileUpload', 1000)
.pause(1000)
.setValue('input#fileUpload', require('path').resolve(__dirname + '/testfile.txt')) // Works
// .setValue('input#fileUpload', "testfile.txt") // Will not work
// .setValue('input#fileUpload', "http://localhost:3000/testfile.txt") // Will not work
// .setValue('input[type="file"]', require('path').resolve(__dirname + '/testfile.txt')) // Will not work
.click('#submit')
.pause(1000)
.assert.containsText('h3', 'File Uploaded Successfully')
.end();
}
};

I'm not sure why you're having these issues, maybe check to see if you are using the latest version of selenium server and nightwatch. This code works for me 100% in Chrome, Safari, Firefox, IE7/8/9/10/11 (not tested in IE6 but assume it as well).
driver.setValue('input#fileUpload', __dirname + '\\testfile.txt')

In my case, I had an additional problem because the file I was trying to upload was too high up in my directory structure.
As soon as I moved the file to the same level (or in a subdirectory of) the actual test files, things worked.
From a script living in my page-objects folder:
// No dice:
var fullPath = require('path').resolve(__dirname + '/../../somefile.pdf');
// Works:
var fullPath = require('path').resolve(__dirname + '/../somefile.pdf');
this.setValue('input#fileUpload', fullPath);

Related

Playwright upload file on non-input element

So I'm currently trying to automate uploading a profile photo on an Electron App using Playwright and I'm running into issues with 'filechooser' event.
await windowA.click('data-testid');
const [fileChooser] = await Promise.all([
windowA.waitForEvent('filechooser'),
// windowA.locator('text=Edit').click(),
windowA.waitForTimeout(3000),
windowA.locator(selector).click(),
]);
The element used to upload a photo isn't an input type so I'm using
await fileChooser.setFiles(
[filepath],
{ timeout: 1000 }
);
The issue is trying to get playwright to select an image from the input dialog box that pops up and it just won't select any files. I've also been trying to get playwright to select an image in my fixtures folder, which is in a relative path to the test, but haven't had success in either case.
The error that Playwright is displaying is
page.waitForEvent: Timeout while waiting for event "filechooser"
waiting for event "filechooser"
Any know what the issue is?
My slippers told me that if you are using the window.showOpenFilePicker() to get a file from the user, you won't get the filechooser event at all. This is because internally, the showOpenFilePicker is not triggering an event as it is still a WIP.
More infos can be found there but I don't think there is a workaround for now
https://githubmemory.com/repo/microsoft/playwright/issues/8850
Pupetter has actually the same issue: https://github.com/puppeteer/puppeteer/issues/5210`
One fix would be to not use the showOpenFilePicker() at all, but instead rely on the <input> element to gather the file. This is a bit more cumbersome for the dev but is more supported and should trigger the 'filechooser' event.
Another fix could be to add a function you can override when running in test move for it to not even need to open the file chooser. Something like
getFileFromPicker() => {
if(!isRunningInTest) {
// do the showOpenFilePicker logic as usual in the app and the user will need to choose a file from it
} else {
// provide synchronously a buffer to use as file content, and so do not even show the picker to the testing user.
}

SAPUI5 Fileuploader upload not triggered if file to upload is set via setValue

In SAPUI5 I am using fileuploader to to upload file to gateway service.
Functionality works if I select file using by pressing "Browse" button, however if I set file path using using setValue() and after that call upload() function, file upload is not triggered. There are no errors in the browser.
This is the same behavior if I press upload button, but file path is not set. I suspect that there something additional that I need to set, but I have no idea what is that. Below is the code
UI
<u:FileUploader id="fileUploader"
tooltip="Select file to upload"
width="415px"
icon="sap-icon://add-document"
uploadOnChange="false"
sendXHR="true"
uploadUrl="/sap/opu/odata/sap/ZUPLOAD_DOC_SRV/Upload_DocSet"
useMultipart="false"
uploadStart="onUploadStart"
uploadComplete="handleUploadComplete"
sameFilenameAllowed="true"
change="onChange"/>
Controller
var oFileUploader = this.byId("fileUploader");
oFileUploader.removeAllHeaderParameters(oCustomerHeaderToken);
oFileUploader.setValue("C:\\TEMP\\test.txt");
oCustomerHeaderToken = new sap.ui.unified.FileUploaderParameter({
name: "x-csrf-token",
value: oFileUploader.getModel().getSecurityToken()
});
oFileUploader.addHeaderParameter(oCustomerHeaderToken);
var oSlug = new sap.ui.unified.FileUploaderParameter({
name: "slug",
value: slugTemp
});
oFileUploader.addHeaderParameter(oSlug);
oFileUploader.upload();
Can someone help me with this?
For security reasons this is not allowed in JavaScript by Browsers. This has nothing to do with UI5, it is a general security measure.
If it was allowed a script could access ALL your files by generating random paths, read them and upload them to ANY server.
In some browsers it's possible to access a sandboxed environment but it's unlikely that this will help you.
Accessing the complete hard drive is impossible (at the moment).

How to prevent selenium from opening new firefox windows?

I am running Selenium Firefox Webdriver on Python for webscraping and when I am going around diferent pages, some of those have some mechanism that open new windows, something in the way of this:
$(function(){
window.open(url, windowName[, windowFeatures]);
});
And it is some kind of malicious webpage that keeps opening random pages on new windows and after some minutes my PC runs out of memory and crashes.
So want I want is to load some feature on the webdriver so it doesn't allow pages to open new windows.
I have tryed not to load JS but this feature is no longer working I guess.
Also, if you know some option or preference to ignore script tags I would like to know it.
Thanks in advice.
Try loading a JS file just in your tests which overwrites the window.open function. Something like:
(function(){
window.open = function() { return false; }
})();
Notice this is an immediatly invoked function exectution.

WinJS css file from local storage

Follow up to this question:
apply downloaded CSS on windows 8 metroUI app
So, yes, Windows says "for security reasons, you cannot navigate to HTML you have downloaded to this location and you cannot run any executable or potentially executable code, such as script or CSS. It is intended for media such as images or videos and the like."
But I really, really want to use that css file from my local storage. Shouldn't I be able to use the execUnsafeLocalFunction method to bypass this restriction like this?:
MSApp.execUnsafeLocalFunction(function () {
el["href"] = "ms-appdata:///local/style.css"
});
It still throws "An app can’t load remote web content in the local context."
I also tried just reading the file with localFolder.getFileAsync and readText, but nothing seems to help. Is there really no way to work around this?
I think I found a way to get the CSS to load.
I tested the code below by adding a css file that sets the body background to red in the local storage folder.
The code reads the contents of the file, creates a style tag in the head and adds the content of the css file to the style.
var url = new Windows.Foundation.Uri(filename);
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(url).then(function (file) {
Windows.Storage.FileIO.readTextAsync(file).then(function(text) {
var style = document.createElement("style");
style.innerText = text;
document.getElementsByTagName("head")[0].appendChild(style);
});
});

NodeWebkit testing using grunt?

Right now i have grunt setup to watch for file changes and feed them to mocha, and mocha runs the tests. The problem is when modules include something like "nw.gui" the test case cannot find them. Is there any way to get around that, some way that i can include it?
//indexeddb.spec.js
var assert = require("assert");
var IndexedDB = require("../scripts/indexeddb");
db = new IndexedDB();
console.log(db);
describe('IndexedDB', function(){
describe('initialize', function(){
it('Should throw an error when the paramaters are null', function(){
expect(db.initialize()).to.throwError();
});
});
});
//indexeddb.js
module.exports = exports = function(){
var indexedDB = require("nw.gui").Window.get().window.indexedDB;
var _ = require("../bower_components/underscore/underscore.js")
this.initialize = function(databaseName,version,schema) {
}
}
Should i do this differently? I did think about running the tests in a gui window in webkit, but that would require that i include all the spec file's on the page and reload the page every time i wanted to run the test. With grunt and watch i was trying to get it to run the test for each file when i edited either the spec or the src file.
I will also need to test the html/js/backbone pages that i open in a webkit window.
Thanks for any insight.
Code example at https://github.com/varunvairavan/node-webkit-unit-testing
Found a way to run test's on node webkit, with a watch to reload the page on file changes.
I was going through this post https://github.com/visionmedia/mocha/issues/960 when i found a link to https://github.com/BenoitZugmeyer/chwitt/tree/5f9bc6c0b8c0328f1dc06a554e9fdd3a969c36ae/tests
The way it works is, create a new node webkit app in your test directory, it then includes all the files in that directory that end with .spec.js and runs the tests in them. It also does a page reload on file changes in the source/test folder.
I had my files in sub directories in the test folder so i used the walk function from node.js fs.readdir recursive directory search to find all the files ending with ".spec.js".