3

I've got a hidden file input field like this:

<input type="file" id="fileToUpload-1827" multiple="" onchange="angular.element(this).scope().setFiles(this)" data-upload-id="1827" class="hidden-uploader">

I'd like to be able to upload files to this. The normal way to do this in protractor would be to do:

ptor.findElement(protractor.By.css('.file-upload-form input')).sendKeys('/path/to/file')

But because the input element isn't visible, I get an error.

I tried:

  ptor.driver.executeScript("return $('.file-upload-form input')[0].removeClass('hidden-uploader');").then(function () {
    ptor.findElement(protractor.By.css('.file-upload-form input')).sendKeys('hello');
  })

But got the error

UnknownError: $(...)[0].removeClass is not a function

It seems ridiculous to have to use executeScript to make an element visible so that I can upload a file, is there a better way? If not, how do I unhide the element?

The full html for the input form is:

<form class="file-upload-form ng-scope ng-pristine ng-valid" ng-if="ajaxUploadSupported">
<strong>Drag files here to upload</strong> or

<label for="fileToUpload-1953">
  <div class="btn btn-info select-file-btn">
    Click to Select
  </div>
</label>

<div>
      <input type="file" id="fileToUpload-1953" multiple="" onchange="angular.element(this).scope().setFiles(this)" data-upload-id="1953" class="hidden-uploader">
</div>
</form>
Mosam Mehta
  • 1,658
  • 6
  • 25
  • 34
user2355213
  • 447
  • 4
  • 13
  • 1
    Well what would a user have to do to access that file upload control? – Arran Feb 10 '14 at 19:23
  • They would click on a browse button that would bring up a box to choose the file from their filesystem. Or they would drag and drop a file from their computer onto a drop target. Neither of these is possible in selenium because selenium can't interact with the OS. According to [this answer](http://stackoverflow.com/questions/16896685/how-to-upload-files-using-selenium-webdriver-in-java), sendKeys() is the way to do it. – user2355213 Feb 11 '14 at 09:01
  • The element is hidden, so what element do users interact with? – Arran Feb 11 '14 at 09:14
  • They interact with a button. I've added the html for the form to my question above. The user can click the button with the text 'Click to select' and that launches the filesystem browse box. The hidden element is the input box, not the button. – user2355213 Feb 11 '14 at 09:51
  • 1
    @Arran (and further visitors wondering about this). Hiding the input field and showing a label instead is a hack commonly used to circumvent the default style/text of the input file dialog. See e.g. this questionhttp://stackoverflow.com/questions/13685070/alter-input-type-file-label-content – dirkk Dec 19 '14 at 11:30
  • @dirkk we all know that, but this was not a good question by any stretch when it was first asked and had no code *whatsoever* in it when it was first asked. Since code was then added it was clear to see what kind of page it is. – Arran Dec 19 '14 at 14:11
  • @Arran _"We all know that"_ is a *very* bold statement. I highly doubt that everyone knows that. I left this comment here for further readers as clarification, if they happen to stumble onto the same problem (as I did) – dirkk Dec 19 '14 at 14:19
  • @dirkk rather, we all *realised* that when the OP gave us code. You have assumed (incorrectly) that no one knew the answer to this question, but rather, the question was so dire that all people could do is ask for more details and move on. A quick google search will also lead you to very similar issues with Selenium. – Arran Dec 19 '14 at 14:31
  • @Arran I never assumed that and I also didn't care if you or anyone knew the answer to this question. I feel like you feel personally criticized here, which was never my intention nor did I do that. I saw this questions and read the answers and comments and _as it currently stands_ you comment was rather unanswer. So I did answer it for completeness and so others can benefit from it. I really don't see any problem with that and don't really get what this discussion is all about. – dirkk Dec 19 '14 at 14:49
  • @dirkk for me, it's more that you've made an assumption about people's understanding of a question that is dire! – Arran Dec 19 '14 at 15:12
  • @Arran As I said (and as a closing statement for me), I never made such an assumption, I never intended to make such an assumption nor did I imply it in any way. – dirkk Dec 19 '14 at 15:50
  • @dirkk I accept your apology. – Arran Dec 19 '14 at 15:51

2 Answers2

5

The only way I could find to do this in the end was to use javascript to make the input element visible.

So I have a function unhideFileInputs:

  var unhideFileInputs = function () {
    var makeInputVisible = function () {
      $('input[type="file"]').removeClass('hidden-uploader');
    };

    ptor.driver.executeScript(makeInputVisible);
  }

This contains the function 'makeInputVisible' which is executed in the browser when I call ptor.driver.executeScript(makeInputVisible). Because I know my page contains jQuery I can use the jQuery removeClass method to unhide my file input element.

To see more on how to execute javascript in the browser using webdriver, see the answer to this question (although the answer uses executeAsyncScript rather than executeScript).

Community
  • 1
  • 1
user2355213
  • 447
  • 4
  • 13
0

To add on user2355213s answer for the more current releases of protractor. ptor is obsolote and instead browser should be used. Also, executeScript() expects a string as parameter. So I ended up using

browser.executeScript('$(\'input[type="file"]\').attr("style", "");');

as my visibility setting was directly applied to the element. Of course, you can also use

browser.executeScript('$(\'input[type="file"]\').removeClass("hidden-uploader");');

depending on your HTML/CSS.

dirkk
  • 6,160
  • 5
  • 33
  • 51