简体   繁体   中英

In an Ember route unit test how do I stub setupController and then test a routes method

I have a route with no controller file explicitly created. My route looks something like:

import Ember from 'ember';
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
import vibrate from '../utils/utility-vibrate';

export default Ember.Route.extend(ApplicationRouteMixin, {
  setupController: function(controller, model) {
    this._super(controller, model);

    controller.set('session', Ember.inject.service('session'));

    controller.set('leftSidebarWidgets', []);
    controller.set('rightSidebarWidgets', []);
    controller.set('unpricedOrders', []);
    controller.set('loadingUnpricedOrders', {value: true});
  },
  deleteRecordValidation: function(modelName) {
    if (!modelName) {
      return true;
    }

    if (modelName === 'orderItem') {
      let rightHandWidgets = this.controller.get('rightSidebarWidgets');

      if (rightHandWidgets.any(w => Ember.get(w, 'name') === 'widgets/add-update-order-item')) {
        let orderItemDiv = Ember.$('.widgets\\/add-update-order-item');
        vibrate(orderItemDiv);

        return false;
      }
    }

    return true;
  }
  ...
});

I then have a unit test:

import { moduleFor, test } from 'ember-qunit';

moduleFor('route:application', 'Unit | Route | application', {
  needs: ['service:session']
});

test('delete record validation returns false if order item delete and update order item widget open', function(assert) {
  assert.expect(1);

  let route = this.subject();

  route.controller.get('rightSidebarWidgets').insertAt(0, {
    name: 'widgets/add-update-order-item'
  });

  assert.notOk(route.deleteRecordValidation('orderItem'));
});

I'm trying to add something to the controller to test a particular scenario - the issue is the test falls over with Cannot read property 'get' of undefined as route.controller is null. Do I need to stub setup controller or something else to get the 'controller' in place? If so how?

You don't actually need to stub the setupController function. That's not run in your unit test unless you explicitly tell it to. But you do need to mock the controller itself.

First, in your test file, create a mock controller:

let controller = Ember.Object.create();

If you want to add fields to this mock object, you can either add them on creation:

let controller = Ember.Object.create({
  someKey: someValue
});

Or add them in later:

controller.set('someKey', someValue);

You can now pass this mock controller to your setupController function for testing:

route.setupController(controller, model);

And you can assign it to your route for testing your deleteRecordValidation function:

let route = this.subject({
  controller: controller
});

Or:

let route = this.subject();
route.controller = controller;

At that point, you just need to add whatever fields to the mock controller that it uses in the method you're testing. You can override most things that aren't associations.

As always, it's better to mock anything external to what you're testing in a unit test, so this is preferable to importing the actual controller.

I changed the deleteRecordValidation function to use this.controllerFor('application') instead of this.controller. And also updated the unit test to be:

moduleFor('route:application', 'Unit | Route | application', {
  needs: ['service:session', 'controller:application']
});

test('delete record validation returns false if order item delete and update order item widget open', function(assert) {
  assert.expect(1);

  let route = this.subject();
  let controller = route.controllerFor('application');

  controller.set('rightSidebarWidgets', [{
    name: 'widgets/add-update-order-item'
  }]);

  assert.notOk(route.deleteRecordValidation('orderItem'));
});

So the key thing was to change to controllerFor('application') and to also add the needs for controller:application . Note that the service:session one is there because I use Ember Simple Auth.

Interestingly, I also had to ember g controller application and leave the default one in place. Without this the test failed with Attempting to register an unknown factory: 'controller:application' . I've posted on Ember CLI's issue page to see if this step should be required ( https://github.com/ember-cli/ember-cli/issues/5217 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM