rosshinkley / nightmare-upload

34 stars 7 forks source link

Call "change" event after upload #1

Closed masiulis closed 8 years ago

masiulis commented 8 years ago

First of all, thank you so much for this plugin.

However, we are using onChange listener and upload does not trigger it. My quick hack was to add an ugly eval in the action function:

function(selector, pathsToUpload, done) {

        // Added code
        eval(`var evalfn = function() {
          var element = document.querySelector('${selector}');
          var event = document.createEvent('HTMLEvents');
          event.initEvent('change', true, true);
          element.dispatchEvent(event);
          }`);
        this.evaluate_now(evalfn, done);
        // /Added code

        if(!Array.isArray(pathsToUpload)){
          pathsToUpload = [pathsToUpload];
        }
        this.child.call('upload', selector, pathsToUpload, (err, stuff) => {
          done(err, stuff);
        });
      })

Maybe there is a better way and maybe plugin itself could be updated to call onChange?

rosshinkley commented 8 years ago

First of all, thank you so much for this plugin.

No problem, trying to help. :)

However, we are using onChange listener and upload does not trigger it. My quick hack was to add an ugly eval in the action function:

Hm, I don't think your source there is going to do what you intend. Specifically, this.evaluate_now(evalfn, done); will end the upload action call when the event is finished being dispatched, and the later done call inside of .child.call() will cause problems. Or, potentially vice-cersa. You're (unintentionally) propping up a race condition.

Setting that aside, .upload() doesn't actually trigger the upload, it simply sets the file(s) in the input. Judging from what you've written, I'd bet that the act of changing the file input triggers the upload - am I close to being on the same page? With that in mind, my other thought would be that you could try to move the evaluate_now function out to an .evaluate() action after .upload() as off the cuff, they should be functionally equivalent:

var selector = '#my_file_upload';
nightmare
  .goto(myUploadUrl)
  .upload(selector, 'some_file.txt')
  .evaluate((selector)=>{
      var element = document.querySelector('${selector}');
      var event = document.createEvent('HTMLEvents');
      event.initEvent('change', true, true);
      element.dispatchEvent(event);
  }, selector)
  ...

This will set the file to be uploaded and then trip the change event, which I think is what you're after. Thoughts?

masiulis commented 8 years ago

Strangely the problem is not where I thought it was. onchange is actually called, but it fails to execute a fetch function and just rejects fetch with "TypeError: Failed to fetch". Without devTools it looked like onchange was never called. Also, fetch works when clicking upload manually in the electron window. I am closing this issue, because it does not seem to be the actual problem.