Request for help with testing setup


#1

Hello all,

I’ve been struggling for countless hours getting testing setup for our ember app. We’ve put it off for too long (nearly at production now) and we are finding we really need the integration tests. I’ve read countless articles, watched a handful of videos, dug through jsbins, gists, other apps, you name it I’ve looked at it.

We setup our project using generator ember and yeoman and we had issues with the built in mocha/chai so we decided to go with Qunit and testem. I’ve managed after a few hours to get it setup so I can run grunt testem and grunt will run testem under a ci environment. It works fine if I have a static test that doesn’t do anything, but once it starts to do something I run into Uncaught Error: Assertion Failed: You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an run. Ok well I’ll wrap the test code in this, wrong I was there. After googling and coming up with mostly useless (and potentially outdated) articles I decided to take to the emberjs channel on freenode. The only response I got was switch to ember-cli. This wasn’t helpful as the project lead is not interested in switching as there is no reason why the testing in there should work and not in our project. I then found this which says to wrap pretty much everything in Ember.run(function(){}); After spending a few hours doing that to the entire app not only did it not work but it broke the app in the process. which has only added to the frustration.

Can someone please help me get this setup? Testing you application shouldn’t be this hard.

Useful snippets:

test.js

/* global describe, it */
/* jshint ignore: start */

// put app in qunit-fixture
App.rootElement = '#qunit-fixture';

// turn on testing mode
App.setupForTesting();
App.injectTestHelpers();

module("Testing the homepage", {
    setup: function () {
        App.reset();
        App.injectTestHelpers();
    }
});

test("Can login", function () {
    expect(1);

        visit("/login");
        fillIn("#email", 'email@email.com');
        fillIn('#password', 'test');
        fillIn('#organization', 'test');
        click('button');

    andThen(function(){
        equal(currentURL(), '/', 'Moved to homepage');
    });

});

/* jshint ignore: end */

test index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Web App Testing</title>
    <link rel="stylesheet" href="../app/bower_components/qunit/qunit/qunit.css">

    <link rel="icon" type="../app/images/png" href="images/logo_mini.png" />
</head>

<body>
    <div id="qunit"></div>
    <div id="qunit-fixture"></div>

    <script src="../app/bower_components/jquery/jquery.js"></script>
    <script src="../app/bower_components/handlebars/handlebars.runtime.js"></script>
    <!-- Bootstrap 3.1.1 -->
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/affix.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/alert.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/dropdown.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/tooltip.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/modal.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/transition.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/button.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/popover.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/carousel.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/scrollspy.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/collapse.js'></script>
    <script src='../app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/tab.js'></script>
    <!-- End Bootstrap 3.1.1 -->
    <script src="../app/bower_components/momentjs/min/moment.min.js"></script>
    <script src="../app/bower_components/d3/d3.min.js"></script>
    <script src="../app/bower_components/nvd3/nv.d3.min.js"></script>
    <script type="text/javascript" src="../app/bower_components/ember/ember.js"></script>
    <script src="../app/bower_components/ember-data/ember-data.js"></script>
    <script src="../app/bower_components/magnific-popup/dist/jquery.magnific-popup.min.js"></script>
    <script src="../app/bower_components/blueimp-md5/js/md5.min.js"></script>
    <script src="../app/bower_components/bootstrap-tour/build/js/bootstrap-tour.js"></script>
    <script src="../app/bower_components/ember-nvd3/build/ember-nvd3.js"></script>
    <script src="../app/bower_components/jsSHA/src/sha.js"></script>
    <script src="../app/bower_components/ember-data.model-fragments/dist/ember-data.model-fragments.js"></script>
    <script src="../app/bower_components/pdfjs-bower/dist/pdf.js"></script>
    <!-- PDFJS -->
    <script src="../app/bower_components/pdfjs-bower/dist/compatibility.js"></script>
    <!-- PDFJS -->
    <script src="../app/bower_components/c3/c3.min.js"></script>
    <!-- C3 -->
    <script src="../app/bower_components/ember-c3/build/lib.js"></script>
    <!-- Ember-C3 -->
    <script src="../app/bower_components/pikaday/pikaday.js"></script>
    <!-- Pikaday -->
    <script src="../app/bower_components/ember-pikaday/build/lib.js"></script>
    <!-- Ember-Pikaday -->
    <script src="../app/bower_components/cubism/cubism.v1.js"></script>
    <!-- Cubism -->
    <script src="../app/bower_components/select2/select2.js"></script>
    <!-- Select2 -->
    <script src="../app/bower_components/ember-select2/build/lib.js"></script>
    <!-- Ember Select2 -->
    <script src="../app/bower_components/bowser/src/bowser.js"></script>
    <!-- Bowser -->
    <script src="../app/bower_components/favico.js/favico.js"></script>
    <!-- Favico.js -->

    <script type="text/javascript" src="../app/bower_components/qunit/qunit/qunit.js"></script>
    <script type="text/javascript" src="../app/bower_components/ember-qunit/dist/globals/main.js"></script>

    <script type="text/javascript" src="../.tmp/scripts/combined-scripts.js"></script>
    <script type="text/javascript" src="../.tmp/scripts/compiled-templates.js"></script>

    <script type="text/javascript" src="spec/test.js"></script>
</body>

</html>

testem.json

{
    "framework": "qunit",
    "test_page": "test/index.html",
    "launch_in_dev": ["PhantomJS","Chrome"],
    "launch_in_ci": ["PhantomJS"]
}

gruntfile.json

// load testem
    grunt.loadNpmTasks('grunt-contrib-testem');

...

testem: {
            environment1: {
                // List of files to attach
                src: [
                    'app/bower_components/**/*.js',
                    '.tmp/scripts/*.js',
                    'test/spec/*.js'
                ],
                // Options that will be passed to Testem
                options: {
                    parallel: 8,
                    launch_in_ci: ['PhantomJS', 'Chrome'],
                    launch_in_dev: ['PhantomJS', 'Chrome']
                }
            }
        },

#2

Hello there,

I don’t see where you are wrapping your test code inside: Ember.Run

You should use Ember.Run inside your unit test for example:

test("Can login", function () {
	expect(1);
	Ember.run(function(){
		visit("/login");
		fillIn("#email", 'email@email.com');
		fillIn('#password', 'test');
		fillIn('#organization', 'test');
		click('button');

		andThen(function(){
			equal(currentURL(), '/', 'Moved to homepage');
		});
	});
});

Also, I think you will need to set: Ember.testing = true; inside your setup function

module("Testing the homepage", {
	setup: function () {
		Ember.testing = true;
		App.reset();
		App.injectTestHelpers();
	}
});

This will disable ember’s run loop and provide maximum control for your tests.


#3

Hello,

I didn’t have my test code inside Ember.run as I had tried that already and had been trying other things.

I tried what you said however I still run into the same error. I don’t think I need to explicitly turn on testing mode either as in the original error it says it was on

Error: Assertion Failed: You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an run.

Any other thoughts / suggestions?

Thanks :slight_smile:


#4

@Frozenfire I’m running into the same issue… Did you manage to solve this? Thanks


#5

Ok, so I just figured this out.

This controller code would have asynchronous side-effects

Ember.$.post(url, {}).then(
  ((response)->
    // success
  ),
  ((error)->
    // failure
  )
)

You gotta wrap this up in a promise instead

promise = new Ember.RSVP.Promise((resolve, reject) ->
  request = Ember.$.post(url, {})

  request.always(->
    if request.status == 201 
      resolve(request)
    else
      reject(request)
  )
)

promise.then(
  ((response)->
    // success
  ),
  ((error)->
    // failure
  )
)

#6

Awesome work! I no longer work for that company and am on to a new project. Will forward this info though!