ember-modal-dialog
ember-modal-dialog copied to clipboard
Acceptance tests with ember-tether
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.
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 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?
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.
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...
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 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
Awesome! Thanks for the quick answer.
+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.
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!
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.
I believe setting renderInPlace
to true
in test environments is the best workaround for this issue, currently.
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 That sounds much better! Could you PR the README with a new section for Testing, and add your snippet?