ember-modal-dialog icon indicating copy to clipboard operation
ember-modal-dialog copied to clipboard

Acceptance tests with ember-tether

Open john-griffin opened this issue 9 years ago • 13 comments

I would like to clarify what the best practices are around acceptance tests with ember-tether.

When I write a basic ember-modal-dialog acceptance test that launches a modal, makes an assertion and closes it works fine and as expected. When I switch over to using ember-tether the same test fails because it can't find the content inside the modal. Is there a recommended way support ember-tether based modals in acceptance tests?

I tried switching the modalRootElementId in the test environment but that does not seem to work.

john-griffin avatar Jun 24 '15 15:06 john-griffin

The problem you're encountering is that Tether / ember-tether appends items to the body element. But Ember acceptance testing expects the app to be contained wholly within the test container, so click helpers and the like don't work.

We've worked around this in out apps by creating helpers that are not scoped. e.g.

function unscopedClick(app, selector, context) {
  var $el = $(selector, context);
  Ember.run($el, 'mousedown');

  focus($el);

  Ember.run($el, 'mouseup');
  Ember.run($el, 'click');

  return app.testHelpers.wait();
}

function unscopedFillIn(app, selector, contextOrText, text) {
  var $el, context;
  if (typeof text === 'undefined') {
    text = contextOrText;
  } else {
    context = contextOrText;
  }
  $el = $(selector, context);
  focus($el);
  Ember.run(function() {
    $el.val(text).change();
  });
  return app.testHelpers.wait();
}
Ember.Test.registerAsyncHelper('unscopedClick', unscopedClick);
Ember.Test.registerAsyncHelper('unscopedFillIn', unscopedFillIn);

I'm not sure if this qualifies as a "recommended" approach. I wish there was a better solution, but I don't have one yet.

lukemelia avatar Jun 30 '15 21:06 lukemelia

@lukemelia thanks for the detailed explanation.

Based on this example I implemented helpers that are successfully filling out forms and clicking buttons inside a Tether based modal. However the tests fail to complete because it seems like the actions aren't bubbling correctly. Is this due to the event delegation caveat mentioned here?

john-griffin avatar Jun 30 '15 23:06 john-griffin

I can see now this is a deeply rooted issue in Ember event dispatching https://github.com/yapplabs/ember-tether/issues/3.

An alternative approach would be to disable ember-tether when running tests but keep it enabled in other environments. Is there a good way of doing this? Digging through the source it seems to be auto detected so I can't find an obvious way to switch it off in test mode.

john-griffin avatar Jul 01 '15 03:07 john-griffin

This is definitely not a recommended approach, as it would special case your test environment state and could therefore mask real bugs. But the ember-modal-dialog test suite does have a set of tests that cover non-ember-tether environments by stubbing hasEmberTether to false:

  • https://github.com/yapplabs/ember-modal-dialog/blob/b91d7641f39d2c849a0d1df050df7b448d76b2ab/tests/acceptance/modal-dialogs-without-tether-test.js#L12-L27
  • https://github.com/yapplabs/ember-modal-dialog/blob/b91d7641f39d2c849a0d1df050df7b448d76b2ab/tests/helpers/container.js

As you can see, it uses several private apis, doesn't work for 1.10 and prior, etc. So...

Use At Your Own Risk

chrislopresto avatar Jul 01 '15 20:07 chrislopresto

We are currently dealing with the same issue. We wanted to use ember-tether for something else than modals and now our existing tests are broken. A good solution for us would be an option to tell ember-modal-dialog to not use tether even though it is available.

gzurbach avatar Jul 06 '15 17:07 gzurbach

@gzurbach It's not directly documented, but you can specify useEmberTether=false to fall back to the positioned-container-based positioning.

{{#modal-dialog useEmberTether=false}}
I am a modal that will never use ember-tether.
{{/modal-dialog}}

https://github.com/yapplabs/ember-modal-dialog/blob/b91d7641f39d2c849a0d1df050df7b448d76b2ab/addon/components/modal-dialog.js#L22

chrislopresto avatar Jul 06 '15 23:07 chrislopresto

Awesome! Thanks for the quick answer.

gzurbach avatar Jul 06 '15 23:07 gzurbach

+1. Would love to see a good solution for this... the unscopedClick test helper seems like it would be the least hacky way to implement acceptance tests, but I wasn't able to get it to work properly.

harlio avatar Nov 24 '15 15:11 harlio

If you are using tether-dialog and want to disable it during tests while this issue is unresolved, you can set the renderInPlace property to true during tests.

Please fix this!

Gaurav0 avatar Dec 07 '15 18:12 Gaurav0

If I understand correctly, there are two problems in testing environments where the body tag is not the Ember rootElement. Getting the test helpers to interact with an ember-tether dialog box, and getting the actions to propagate correctly from the ember-tether dialog box. The first problem has a couple work arounds, but I don't see anything on here that worked for me for the second problem with the actions. Here's my work-around in case anyone finds it helpful (this is using Ember 1.13):

{{#component (if Ember.testing "modal-dialog" "tether-dialog")
    attachment="top right"
    clickOutsideToClose=false
    hasOverlay=false
    offset= "-10px -10px"
    target=".submit-search__submit-btn"
    targetAttachment="bottom right"}}
    {{!-- dialog template here --}}
{{/component}}

So during the tests it just uses "modal-dialog" which doesn't look right but works. The tether-dialog specific properties are just ignored. And then you can use the regular test helpers. I know its not a good idea to make the code different between the production environment and the testing environment, but in this case I figured you can go for either less-than-ideal acceptance tests or no acceptance tests at all of the "actions up" part of a component dependent on ember-tether.

RustyToms avatar Feb 22 '16 18:02 RustyToms

I believe setting renderInPlace to true in test environments is the best workaround for this issue, currently.

samselikoff avatar Sep 01 '16 18:09 samselikoff

If you're doing acceptance testing the https://github.com/emberjs/rfcs/pull/268 way, you can bypass renderInPlace which always felt a little dirty with this in your environment:

if (environment === 'test') {
  ENV.APP.rootElement = '#ember-testing';
  ENV['ember-tether'] = {
    bodyElementId: 'ember-testing'
  };
}

and in your acceptance tests, ensure you're importing the appropriate test selectors

import { click } from '@ember/test-helpers'

Perhaps we can now close this issue?

axsuul avatar Feb 26 '18 20:02 axsuul

@axsuul That sounds much better! Could you PR the README with a new section for Testing, and add your snippet?

samselikoff avatar Jun 24 '18 23:06 samselikoff