如何在ember.js中单元测试视图? [英] How to unit test views in ember.js?

查看:90
本文介绍了如何在ember.js中单元测试视图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在学习Ember.js。我们做所有的开发TDD,并希望Ember.js也不例外。我们在构建Backbone.js应用程序测试驱动方面有经验,因此我们熟悉使用Jasmine或Mocha / Chai测试前端代码。



当了解如何测试视图,当视图使用的模板具有 #linkTo 语句时遇到问题。不幸的是,我们无法找到良好的测试示例和实践。这个要点是我们的追求,以获得如何正确地单元测试ember应用程序。



当查看测试在Ember.js源代码中的linkTo,我们注意到它包含一个完整的布线ember应用程序支持 #linkTo 。这是否意味着我们在测试模板时无法存储此行为?



如何使用模板渲染为ember视图创建测试?



以下是一个要点,我们的测试和一个模板,将使测试通过,以及一个将使其失败的模板。



view_spec.js.coffee

 #这个测试是用摩卡/柴,
#使用chai-jquery和chai更改扩展

描述'TodoItemsView', - >

beforeEach - >
testSerializer = DS.JSONSerializer.create
primaryKey: - > 'id'

TestAdapter = DS.Adapter.extend
serializer:testSerializer
TestStore = DS.Store.extend
revision:11
适配器:TestAdapter .create()

TodoItem = DS.Model.extend
标题:DS.attr('string')

store = TestStore.create()
@todoItem = store.createRecord TodoItem
标题:'做某事'

@controller = Em.ArrayController.create
content:[]

@view = Em.View.create
templateName:'working_template'
控制器:@controller

@ controller.pushObject @todoItem

afterEach - >
@ view.destroy()
@ controller.destroy()
@ todoItem.destroy()

描述todos的数量, - >

beforeEach - >
#$('#konacha')是在每个测试之间清理的div
Em.run => @ view.appendTo'#konacha'

它被显示为', - >
$('#konacha .todos-count')。should.have.text'1个事情要做'

它是活的', - >
expect(=> $('#konacha .todos-count')。text())。to.change.from('1 thing to do')。('2 things to do')。 when =>
Em.run =>
extraTodoItem = store.createRecord TodoItem,
标题:'Moar todo'
@ controller.pushObject extraTodoItem

broken_template.handlebars

 < div class =todos -count>< span class =todos> {{length}}< / span>事情要做< / div> 

{{#linkToindex}}首页{{/ linkTo}}



; span class =todos> {{length}}< / span>事情要做< / div>


解决方案

我们的解决方案基本上是加载整个应用程序,但尽可能隔离我们的考试科目。例如,

  describe('FooView',function(){
beforeEach(function(){
this.foo = Ember.Object.create();
this.subject = App.FooView.create({foo:this.foo});
this.subject.append();

$ b afterEach(function(){
this.subject&& this.subject.remove();
});

它(渲染foo的最爱食物,function(){
this.foo.set('favoriteFood','ramen');
Em.run.sync();
expect(this.subject。$()。text()).toMatch(/ ramen /);
});
});

也就是说,路由器和其他全局变量都可用,所以不完整隔离,但是我们可以很容易地发送双精度来更接近被测对象的东西。



如果你真的想隔离路由器, linkTo 帮助器查找为 controller.router ,所以你可以做

  this.router = {
generate:jasmine.createSpy(...)
};

this.subject = App.FooView.create({
controller:{router:this.router},
foo:this.foo
});


We are in the process of learning Ember.js. We do all our development TDD, and want Ember.js to be no exception. We have experience building Backbone.js apps test-driven, so we are familiar with testing front-end code using Jasmine or Mocha/Chai.

When figuring out how to test views, we ran into a problem when the template for the view uses has a #linkTo statement. Unfortunately we are unable to find good test examples and practices. This gist is our quest to get answers how to decently unit-test ember applications.

When looking at the test for linkTo in Ember.js source code, we noticed it contains a full wiring of an ember app to support #linkTo. Does this mean we cannot stub this behaviour when testing a template?

How do you create tests for ember views using template renders?

Here is a gist with our test and a template that will make the test pass, and a template that will make it fail.

view_spec.js.coffee

# This test is made with Mocha / Chai,
# With the chai-jquery and chai-changes extensions

describe 'TodoItemsView', ->

  beforeEach ->
    testSerializer = DS.JSONSerializer.create
      primaryKey: -> 'id'

    TestAdapter = DS.Adapter.extend
      serializer: testSerializer
    TestStore = DS.Store.extend
      revision: 11
      adapter: TestAdapter.create()

    TodoItem = DS.Model.extend
      title: DS.attr('string')

    store = TestStore.create()
    @todoItem = store.createRecord TodoItem
      title: 'Do something'

    @controller = Em.ArrayController.create
      content: []

    @view = Em.View.create
      templateName: 'working_template'
      controller: @controller

    @controller.pushObject @todoItem

  afterEach ->
    @view.destroy()
    @controller.destroy()
    @todoItem.destroy()

  describe 'amount of todos', ->

    beforeEach ->
      # $('#konacha') is a div that gets cleaned between each test
      Em.run => @view.appendTo '#konacha'

    it 'is shown', ->
      $('#konacha .todos-count').should.have.text '1 things to do'

    it 'is livebound', ->
      expect(=> $('#konacha .todos-count').text()).to.change.from('1 things to do').to('2 things to do').when =>
        Em.run =>
          extraTodoItem = store.createRecord TodoItem,
            title: 'Moar todo'
          @controller.pushObject extraTodoItem

broken_template.handlebars

<div class="todos-count"><span class="todos">{{length}}</span> things to do</div>

{{#linkTo "index"}}Home{{/linkTo}}

working_template.handlebars

<div class="todos-count"><span class="todos">{{length}}</span> things to do</div>

解决方案

Our solution has been to essentially load the whole application, but isolate our test subjects as much as possible. For example,

describe('FooView', function() {
  beforeEach(function() {
    this.foo = Ember.Object.create();
    this.subject = App.FooView.create({ foo: this.foo });
    this.subject.append();
  });

  afterEach(function() {
    this.subject && this.subject.remove();
  });

  it("renders the foo's favoriteFood", function() {
    this.foo.set('favoriteFood', 'ramen');
    Em.run.sync();
    expect( this.subject.$().text() ).toMatch( /ramen/ );
  });
});

That is, the router and other globals are available, so it's not complete isolation, but we can easily send in doubles for things closer to the object under test.

If you really want to isolate the router, the linkTo helper looks it up as controller.router, so you could do

this.router = {
  generate: jasmine.createSpy(...)
};

this.subject = App.FooView.create({
  controller: { router: this.router },
  foo: this.foo
});

这篇关于如何在ember.js中单元测试视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆