Skip to content

Integration Test Helpers are undefined in Component Test #88

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

Closed
stravid opened this issue Sep 4, 2014 · 10 comments
Closed

Integration Test Helpers are undefined in Component Test #88

stravid opened this issue Sep 4, 2014 · 10 comments

Comments

@stravid
Copy link

stravid commented Sep 4, 2014

I'm writing a tutorial about creating Ember Addons / Components. Since it is a datepicker component I want to test various user interactions on the component.

These tests fail because the helpers click etc. are not defined. I'm following the official Ember.js guide and it fails. I'm not sure if this is a problem on my end or something is broken?

Related SO question: http://stackoverflow.com/questions/25657787/acceptance-testing-a-ember-datepicker-component-with-ember-cli

@stravid
Copy link
Author

stravid commented Sep 4, 2014

I made some progress, following test setup + tests is working. I'm not sure if this is the way it is supposed to be or if it is just a workaround?

The teardownPikaday method is originally responsible for cleaning up the component when willDestroyElement is fired. Once #85 is merged I think it will work without calling it explicitly by hand.

import { test, moduleForComponent } from 'ember-qunit';
import startApp from '../../helpers/start-app';
import Ember from 'ember';

var App;

moduleForComponent('datepicker-input', 'DatepickerInputComponent', {
  setup: function() {
    App = startApp();
  },
  teardown: function() {
    Ember.run(App, 'destroy');
  }
});

test('is an input tag', function() {
  equal('INPUT', this.$().prop('tagName'));

  this.subject().teardownPikaday();
});

test('clicking the input opens the pikaday dialog', function() {
  this.append();

  ok($('.pika-single').hasClass('is-hidden'));

  click('input');

  andThen(function() {
    ok(!$('.pika-single').hasClass('is-hidden'));
  });

  this.subject().teardownPikaday();
});

@mharris717
Copy link

I had the same issue and the same solution. importing startApp and creating it in setup/teardown worked for me.

@rwjblue
Copy link
Member

rwjblue commented Oct 17, 2014

Why not just trigger the jQuery click directly (which is essentially what the click integration test helper does)?

Something like:

moduleForComponent('datepicker-input');

test('clicking the input opens the pikaday dialog', function() {
  var component = this.subject();

  this.append();

  ok(component.$('.pika-single').hasClass('is-hidden'));

  component.$('input').click();

  ok(!component.$('.pika-single').hasClass('is-hidden'));

  component.teardownPikaday();
});

@rwjblue
Copy link
Member

rwjblue commented Oct 17, 2014

The integration test helpers are wonderful, but they do not belong in unit tests IMHO.

@rwjblue rwjblue closed this as completed Oct 17, 2014
@mharris717
Copy link

That's seems fair to me. Ok to do some light DOM testing in component unit tests, but if you want to do heavy user interaction, make an integration test for the component.

@sukima
Copy link

sukima commented Jul 24, 2015

I don't think this should be closed. The intent is not that there is a bug in ember (or cli) but that the documentation is wrong and misleading. Specifically:

Unit testing methods and computed properties follows previous patterns shown in Unit Testing Basics because Ember.Component extends Ember.Object.

The first paragraph sets the reader's expectation that testing components are unit tests.

Further more, the first reference to integration is:

Ember Components are a great way to create powerful, interactive, self-contained custom HTML elements. Because of this, it is important to test the component's methods and the user's interaction with the component.
[...]
We would use Integration Test Helpers to interact with the rendered component and test its behavior

This gives the reader the impression that although this is a unit test you can cross contaminate methods from integration helpers. The confusion for the error reported by the original poster is most likely a byproduct of not including startApp(). This is a huge departure from the expectation that testing components are a unit test domain. The documentation establishes this assumption through it's prose.

This is further reinforced by the fact that the code samples never reference startApp(). Specifically this code sample has several problems causing a knowledgeable reader to shout WTF!? and possibly (╯°□°)╯︵┻━┻ in extreme situations:

moduleForComponent('my-foo', 'MyFooComponent');
// ERROR! -----------------------------------^
// Will crash with "unable to read property 'needs' of undefined"
// This is because moduleForComponent with two paramaters requires a third
// object (for needs, beforeEach, afterEach, etc.) and probubly an assumption
// that the user will call setupApp() because this is somehow a integration
// test even though the docs claim it is a unit test.

test('clicking link updates the title', function() {
  // WTF?! where is my assert? ------------------^

  var component = this.subject();

  // append the component to the DOM
  this.append();
  // ^- But wait the above example said "first call to $() renders the
  // component." Which do I use?!
  // Also aren't we missing assert.expect() ?!

  // assert default state
  equal(find('h2').text(), 'Hello World');
  // ^- What happened to assert.equal?! So confused please help!

  // perform click action
  click('button');
  // ^-- NO! Crash again! Why? Oh why? ლ(ಠ益ಠლ)

  andThen(function() { // wait for async helpers to complete
    equal(find('h2').text(), 'Hello Ember World');
    //     ^-- How does this differ from this.$() ?
  });
});

The point being that it not fair to end the topic when the documentation hasn't been updated / fixed.

Finally, setupApp() is an expensive task and to test a component and it's expectation of it's DOM usage requiring an entire app initialization seems heavy handed. Either the test suite should allow the user to inject helpers without starting up a full app instance. Or update the docs to explicit explain the difference and circumstances for using click(...).andThen(...) vs this.$(...).click(); assert.ok(...).

EDIT: Just found the guides repo so I should put my 💵 where my mouth is and work on a Pull Request.

@abepetrillo
Copy link

Just a note for noobs like me who end up here, adding this to the test imports the helpers for "integration" tests:

moduleForComponent('my-component', 'myComponent', {
  integration: true
});

@rstudner
Copy link

rstudner commented Nov 20, 2016

I'm having this problem right now in v2.9.1

I have:
tests/helpers/assert-trimmed-text.js (and i've tried assertTrimmedText.js)
tests/helpers/start-app.js with:
import './assert-trimmed-text';
(and tried import './assertTrimmedText'; as above etc)

in ANY component test, if I do assertTrimmedText(stuff) I get told:
http://localhost:7357/assets/test-support.js:6956:22: Can't find variable: assertTrimmedText

@e00dan
Copy link
Contributor

e00dan commented Jan 15, 2018

I have the same problem as @rstudner.

@rwjblue
Copy link
Member

rwjblue commented Jan 15, 2018

Please open a new issue with steps to reproduce. 😝

Commenting on an issue closed for over a year is pretty unlikely to work out...

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

7 participants