在EmberJS中对组件进行单元测试的正确方法

时间:2014-02-27 09:46:07

标签: unit-testing ember.js

我正在尝试在我的Ember应用程序单元测试中测试一个组件,直到现在一切都很好,除了我处于断言需要渲染模板的位置。

这样做通常可以打电话给

var comp = App.SomeNamedComponent.create();
var comp.appendTo(App.rootElement);

但是虽然这确实创建了组件的基本元素,但它不会呈现其模板。经过一些研究后,我最终发现组件上没有设置templateNametemplate属性。所以我决定自己设置templateName,但后来抱怨A Component must have a parent view in order to yield.

然后我决定使用该组件在模板中创建另一个自定义视图,但后来我无法访问该组件的实例......

我需要访问实例来进行断言,我需要渲染它的模板,因为某些属性是根据模板中某些元素的css计算的。

1 个答案:

答案 0 :(得分:20)

这就是我通常在不需要容器时测试组件的方式(特别是当以编程方式向组件提供模板和布局时):

Ember.testing = true;

MyAwesomeComponent = Ember.Component.extend();

function createComponent(componentName, factory, options) {
  if (typeof options.template === 'string') {
    options.template = Ember.Handlebars.compile(options.template);
  }

  if (typeof options.layout === 'string') {
    options.layout = Ember.Handlebars.compile(options.layout);
  }

  if (options.template && !options.layout) {
    options.layout = options.template;
    delete options.template;
  }

  var component = factory.create(options);

  Ember.run(function(){
    component.appendTo('#qunit-fixture');
  });

  return component;
}

module('component testing sample');

test('a component with template', function(){
  var options = {layout: 'woot woot{{fullName}}'};

  var component = createComponent('my-awesome', MyAwesomeComponent, options);

  equal(component.$().text(), 'woot woot');
});

test('a component with custom options and a template', function(){
  var options = {
    fullName: 'Robert Jackson',
    layout: '{{fullName}}'
  };

  var component = createComponent('my-awesome', MyAwesomeComponent, options);

  equal(component.$().text(), 'Robert Jackson');
});

查看示例JSBin


如果您需要/希望能够查找模板,您可以使用以下内容(创建一个隔离的容器):

Ember.testing = true;

MyAwesomeComponent = Ember.Component.extend();

function isolatedContainer() {
  var container = new Ember.Container();

  container.optionsForType('component', { singleton: false });
  container.optionsForType('view', { singleton: false });
  container.optionsForType('template', { instantiate: false });
  container.optionsForType('helper', { instantiate: false });

  return container;
}

function createComponent(componentName, factory, options) {
  var fullName = 'component:' + componentName,
      templateFullName = 'template:components/' + componentName;

  container.register(fullName, factory);

  if (container.has(templateFullName)) {
    container.injection(fullName, 'layout', templateFullName);
  }

  var Component = container.lookupFactory(fullName),
      component = Component.create(options);

  Ember.run(function(){
    component.appendTo('#qunit-fixture');
  });

  return component;
}

function registerTemplate(name, template){
  if (typeof template !== 'function') {
    template = Ember.Handlebars.compile(template);
  }

  container.register('template:' + name, template);
}

var container;

module('component testing sample', {
  setup: function(){
    container = isolatedContainer();
  },
  teardown: function(){
    Ember.run(container, 'destroy');
  }
});

test('a component with template', function(){
  registerTemplate('components/my-awesome', 'woot woot{{fullName}}');

  var component = createComponent('my-awesome', MyAwesomeComponent);

  equal(component.$().text(), 'woot woot');
});

test('a component with custom options and a template', function(){
  registerTemplate('components/my-awesome', '{{fullName}}');

  var component = createComponent('my-awesome', MyAwesomeComponent, {fullName: 'Robert Jackson'});

  equal(component.$().text(), 'Robert Jackson');
});

JSBin容器版本。