Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with new native event test helpers in Ember 2.5.1 #13540

Closed
chrism opened this issue May 21, 2016 · 9 comments
Closed

Issue with new native event test helpers in Ember 2.5.1 #13540

chrism opened this issue May 21, 2016 · 9 comments

Comments

@chrism
Copy link

chrism commented May 21, 2016

Prior to upgrading to 2.5 my acceptance tests worked for mocking file uploads by using jQuery events on my component. eg

Working in 2.4.3

file-chooser.hbs

{{input type="file" id=name}}
<label for={{name}} >{{label}}</label>

file-chooser.js

import Ember from 'ember';

const {
  run: {
    bind
  }
} = Ember;

export default Ember.Component.extend({
  label: 'choose a file',

  didInsertElement() {
    this.$().on('change', bind(this,'filesSelected'));
  },

  willDestroyElement() {
    this.$().off('change', bind(this,'filesSelected'));   
  },

  filesSelected(event) {
    const files = event.target.files;
    if (files.length === 0) {
      Ember.Logger.log('you must add a file');
    } else if (files.length > 0) {
      this.sendAction('action', files);
    }
  }
});

My custom test helper which allowed me to successfully add a file via uploadFile('#file-chooser', ['test text'], {});

/* global Blob */

import Ember from 'ember';

function createFile(content = ['test'], options = {}) {
  const {
    name,
    type
  } = options;

  const file = new Blob(content, {type : type ? type : 'text/plain'});
  file.name = name ? name : 'test.txt';

  return file;
}


export default Ember.Test.registerAsyncHelper('uploadFile', function(app, selector, content, options) {
  const file = createFile(content, options);

  return triggerEvent(
    selector,
    'change',
    { target: { files: [file] } }
  );
});

Unfortunately this approach no longer seems to work in 2.5.1 so I have tried updating the component to use native events now instead, but this still is no longer working in acceptance tests

Not Working in 2.5.1

file-chooser.hbs

{{input type="file" id=name change=(action "chosenFiles")}}
<label for={{name}} >{{label}}</label>

file-chooser.js

import Ember from 'ember';

export default Ember.Component.extend({
  label: 'choose a file',

  actions: {
    chosenFiles(event) {
      const files = event.target.files;
      if (files.length === 0) {
        Ember.Logger.log('you must add a file');
      } else if (files.length > 0) {
        this.sendAction('action', files);
      }
    }
  }
});

With the same test helper.

This approach works fine in the browser outside of tests (as did the jQuery version). But the test shows an empty FileList array for event.target.files now.

I notice from the release notes that this has been a change in Ember 2.5.1

Ember's acceptance test helpers, such as click(), have previously used jQuery event triggers. In 2.5 this behavior has been altered to trigger native events via dispatchEvent. This change is expected to be completely backwards compatible and was uncontroversial during the six week beta cycle. It allows the triggering of non-jQuery event listeners in acceptance tests.

Is this a regression, or have I misunderstood how to create a file chooser mockable in an acceptance test?

@chrism
Copy link
Author

chrism commented May 22, 2016

To follow up on this here are some Ember Twiddles I have made showing the failing tests as very simple use cases.

Working both in Ember 2.4.3 acceptance tests and in browser example

File Chooser Tests - Ember 2.4.5

Working only in browser for both jQuery and native events in Ember 2.5.1

File Chooser Tests - Ember 2.5.1

File Chooser Tests Native Events - Ember 2.5.1

@rwjblue
Copy link
Member

rwjblue commented May 22, 2016

@cibernox - Would you mind taking a look?

@cibernox
Copy link
Contributor

@rwjblue Checking it. If the regression appeared recently, I think that this PR might have been involved.

@cibernox
Copy link
Contributor

cibernox commented May 22, 2016

I stand corrected, this appeared in 2.5.0. That PR is clear.

@cibernox
Copy link
Contributor

cibernox commented May 22, 2016

Ok @chrism , after some digging, I have bad news and a workaround.

One difference between native events and jquery events, is that in native events, the target property is ReadOnly. That means that even if you pass target: { whatever } as an option, it is going to be ignored and the target is going to be the element where the dispatchEvent is called on.

I tried to append the file to the input for real using input.files[0] = file but it is ReadOnly too. I tried to create a new FileList object but it doesn't have a constructor.

Basically, the entire web platform conspires to prevent mocking of file inputs. I guess that it's because of security concerns.
I honestly don't see any way of mocking this without changes in application code. However the workaround is very small.

The solution I've found changing application code a little bit is this:

https://github.com/cibernox/__simulate_file_upload_example/blob/master/app/templates/components/file-chooser.hbs#L1
https://github.com/cibernox/__simulate_file_upload_example/blob/master/app/components/file-chooser.js#L9
https://github.com/cibernox/__simulate_file_upload_example/blob/master/tests/helpers/utils/upload-file.js#L24

@chrism
Copy link
Author

chrism commented May 22, 2016

Hi @cibernox — firstly a massive thank you for looking into this.

As I already have one or two places in my application code where I’ve had to do something similar a work around like this isn’t such a big deal.

For me the main issue was knowing where to look for advice on this as it doesn’t quite fall in any of the obvious places.

On this hopefully I might be able to help — I'm going to update my Ember Twiddles with working versions following your format and write a blog post on how to write acceptance tests for file uploads. Once I have, if you don’t mind, I’d appreciate you casting your eye over it to make sure I am giving sound advice.

Once again thanks for your help on this, it’s very much appreciated.

@chrism chrism closed this as completed May 22, 2016
@rwjblue
Copy link
Member

rwjblue commented May 22, 2016

For me the main issue was knowing where to look for advice on this as it doesn’t quite fall in any of the obvious places.

Yes, I agree this was a bit of a difficult one to diagnose.

I'm going to update my Ember Twiddles with working versions following your format and write a blog post on how to write acceptance tests for file uploads.

Sounds great, thank you!

@cibernox
Copy link
Contributor

@chrism sure, just ping me in slack whenever you want me to take a look.

@chrism
Copy link
Author

chrism commented May 23, 2016

@cibernox i'm on slack if you want to reply there but thought i'd post the URL here too for others.

https://medium.com/@chrisdmasters/acceptance-testing-file-uploads-in-ember-2-5-1c9c8dbe5368#.581bwe6iw

thanks again for your help

kevinansfield added a commit to kevinansfield/Ghost-Admin that referenced this issue May 27, 2016
no issue
- override `x-file-input` in `gh-file-input` to look for a custom property on the change event if we are in testing mode (this is necessary because Ember 2.5+ use native rather than jQuery events so `target.files` is readonly, see emberjs/ember.js#13540)
- migrate unit tests for the uploader components to the integration tests
- add skipped acceptance tests for the subscribers CSV import now that it's possible to simulate file uploads
kevinansfield added a commit to kevinansfield/Ghost-Admin that referenced this issue May 27, 2016
no issue
- override `x-file-input` in `gh-file-input` to look for a custom property on the change event if we are in testing mode (this is necessary because Ember 2.5+ use native rather than jQuery events so `target.files` is readonly, see emberjs/ember.js#13540)
- migrate unit tests for the uploader components to the integration tests
- add skipped acceptance tests for the subscribers CSV import now that it's possible to simulate file uploads
kevinansfield added a commit to kevinansfield/Ghost-Admin that referenced this issue May 27, 2016
no issue
- override `x-file-input` in `gh-file-input` to look for a custom property on the change event if we are in testing mode (this is necessary because Ember 2.5+ use native rather than jQuery events so `target.files` is readonly, see emberjs/ember.js#13540)
- migrate unit tests for the uploader components to the integration tests
- add skipped acceptance tests for the subscribers CSV import now that it's possible to simulate file uploads
carlbennettnz added a commit to outtherenz/portal-toolkit that referenced this issue Feb 28, 2017
carlbennettnz added a commit to outtherenz/portal-toolkit that referenced this issue Feb 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants