2013-02-15 19 views
14

Chúng tôi đang trong quá trình học Ember.js. Chúng tôi làm tất cả TDD phát triển của mình và muốn Ember.js không phải là ngoại lệ. Chúng tôi có kinh nghiệm xây dựng các ứng dụng Backbone.js dựa trên thử nghiệm, vì vậy chúng tôi đã quen thuộc với việc kiểm tra mã front-end bằng cách sử dụng Jasmine hoặc Mocha/Chai.Làm cách nào để xem các đơn vị kiểm tra trong ember.js?

Khi tìm hiểu cách kiểm tra chế độ xem, chúng tôi gặp sự cố khi mẫu cho chế độ xem sử dụng có tuyên bố #linkTo. Rất tiếc, chúng tôi không thể tìm thấy các ví dụ và thực tiễn kiểm tra tốt. Gist này là nhiệm vụ của chúng tôi để có được câu trả lời làm thế nào để decently đơn vị kiểm tra các ứng dụng ember.

Khi nhìn vào test for linkTo in Ember.js source code, chúng tôi nhận thấy nó chứa toàn bộ hệ thống dây điện của ứng dụng ember để hỗ trợ #linkTo. Điều này có nghĩa là chúng tôi không thể đưa ra hành vi này khi thử nghiệm một mẫu?

Làm cách nào để bạn tạo thử nghiệm cho chế độ xem ember bằng cách sử dụng trình tạo mẫu?

Dưới đây là a gist với thử nghiệm của chúng tôi và mẫu sẽ thực hiện kiểm tra và mẫu sẽ không thực hiện được.

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> 
+1

Về cơ bản, bạn sẽ gặp khó khăn khi phân tách nội dung. Ember muốn toàn bộ ứng dụng của bạn chạy. Đây không phải là câu trả lời, nhưng nói chung tôi thích kiểm tra tích hợp hơn (xem [video này] (http://www.youtube.com/watch?v=heK78M6Ql9Q)) qua các bài kiểm tra đơn vị. Tôi đã thấy mọi người cố gắng thử nghiệm các quan điểm một mình, và ngay cả khi nó hoạt động, nó không có vẻ như là một chiến lược tốt. Xem http://www.slideshare.net/jo_liss/testing-ember-apps/27 để biết một số lý do đằng sau đó. –

Trả lời

9

Giải pháp của chúng tôi về cơ bản là tải toàn bộ ứng dụng, nhưng cô lập các đối tượng thử nghiệm của chúng tôi càng nhiều càng tốt. Ví dụ,

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/); 
    }); 
}); 

Đó là, các bộ định tuyến và globals khác có sẵn, vì vậy nó không hoàn toàn tách biệt , nhưng chúng ta có thể dễ dàng gửi ở nội dung đôi cho những thứ gần gũi hơn với các đối tượng được kiểm tra.

Nếu bạn thực sự muốn để cô lập các router, các linkTo helper trông nó lên như controller.router, vì vậy bạn có thể làm

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

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

Một cách để bạn có thể xử lý này là để tạo ra một stub cho các helper linkto và sau đó sử dụng nó trong một khối trước. Điều đó sẽ bỏ qua tất cả các yêu cầu bổ sung của liên kết thực (ví dụ: định tuyến) và cho phép bạn tập trung vào nội dung của chế độ xem. Dưới đây là cách tôi đang thực hiện:

// Test helpers 
TEST.stubLinkToHelper = function() { 
    if (!TEST.originalLinkToHelper) { 
     TEST.originalLinkToHelper = Ember.Handlebars.helpers['link-to']; 
    } 
    Ember.Handlebars.helpers['link-to'] = function(route) { 
     var options = [].slice.call(arguments, -1)[0]; 
     return Ember.Handlebars.helpers.view.call(this, Em.View.extend({ 
      tagName: 'a', 
      attributeBindings: ['href'], 
      href: route 
     }), options); 
    }; 
}; 

TEST.restoreLinkToHelper = function() { 
    Ember.Handlebars.helpers['link-to'] = TEST.originalLinkToHelper; 
    TEST.originalLinkToHelper = null; 
}; 

// Foo test 
describe('FooView', function() { 
    before(function() { 
     TEST.stubLinkToHelper(); 
    }); 

    after(function() { 
     TEST.restoreLinkToHelper(); 
    }); 

    it('renders the favoriteFood', function() { 
     var view = App.FooView.create({ 
      context: { 
       foo: { 
        favoriteFood: 'ramen' 
       } 
      } 
     }); 

     Em.run(function() { 
      view.createElement(); 
     }); 

     expect(view.$().text()).to.contain('ramen'); 
    }); 
}); 
Các vấn đề liên quan