- Ember.js 指南
- 入门指南 - 介绍
- 入门指南 - 应用规划
- 入门指南 - 创建静态页面
- 入门指南 - 获取Ember.js和相应依赖
- 入门指南 - 添加第一个路由与模板
- 入门指南 - 建立模型
- 入门指南 - 使用静态数据
- 入门指南 - 显示模型数据
- 入门指南 - 显示模型的完成状态
- 入门指南 - 创建新的模型实例
- 入门指南 - 标记模型为完成或未完成
- 入门指南 - 显示未完成待办事项的数量
- 入门指南 - 切换显示和编辑状态
- 入门指南 - 接受修改
- 入门指南 - 删除模型
- 入门指南 - 添加子路由
- 入门指南 - 显示未完成待办事项
- 入门指南 - 显示已完成待办事项
- 入门指南 - 显示所有待办事项
- 入门指南 - 添加移除所有已完成待办事项的按钮
- 入门指南 - 提示所有待办事项已完成
- 入门指南 - 切换已完成和未完成待办事项
- 入门指南 - 更换FixtureAdapter
- 获取 Ember - 获取Ember
- 概念 - 核心概念
- 概念 - 命名惯例
- 对象模型 - 类与实例
- 对象模型 - 计算属性
- 对象模型 - 计算属性和带@each的集合数据
- 对象模型 - 观察器
- 对象模型 - 绑定
- 对象模型 - 重新打开类和实例
- 对象模型 - 绑定,观察器,计算属性:如何选择?
- 应用 - 介绍
- 模板 - 应用模板
- 模板 - Handlebars基础
- 模板 - 条件表达式
- 模板 - 显示项目列表
- 模板 - 切换作用域
- 模板 - 绑定元素属性
- 模板 - 绑定元素类名称
- 模板 - 链接
- 模板 - 操作
- 模板 - 输入助手
- 模板 - 开发助手
- 模板 - 用助手来渲染
- 模板 - 编写助手方法
- 路由 - 介绍
- 路由 - 定义路由
- 路由 - 生成的对象
- 路由 - 指定路由的模型
- 路由 - 设置控制器
- 路由 - 渲染模板
- 路由 - 重定向
- 路由 - 指定地址API
- 路由 - 查询参数
- 路由 - 异步路由
- 路由 - 加载中/错误子状态
- 路由 - 阻止和重试过渡
- 组件 - 介绍
- 组件 - 定义组件
- 组件 - 传递属性
- 组件 - 包裹内容
- 组件 - 自定义组件元素
- 组件 - 使用Action处理用户交互
- 组件 - 从组件发送操作给应用
- 控制器 - 介绍
- 控制器 - 代表单一模型
- 控制器 - 代表多模型
- 控制器 - 管理控制器间的依赖
- 模型 - 介绍
- 模型 - 定义模型
- 模型 - 创建和删除记录
- 模型 - 将记录推入仓库
- 模型 - 持久化记录
- 模型 - 查询记录
- 模型 - 使用记录
- 模型 - 使用Fixture
- 模型 - 连接HTTP服务器
- 模型 - 处理元数据
- 模型 - 自定义适配器
- 模型 - 常见问题
- 视图 - 介绍
- 视图 - 定义视图
- 视图 - 处理事件
- 视图 - 在模板中插入视图
- 视图 - 为视图添加布局
- 视图 - 自定义视图元素
- 视图 - 内置视图
- 视图 - 手动管理视图层级
- 枚举 - 介绍
- 测试 - 介绍
- 测试 - 集成测试
- 测试 - 测试助手
- 测试 - 测试用户交互
- 测试 - 单元测试
- 测试 - 单元测试基础
- 测试 - 测试组件
- 测试 - 测试控制器
- 测试 - 测试路由
- 测试 - 测试模型
- 测试 - 自动化测试
- 配置Ember.js - 禁用基本类型扩展
- 配置Ember.js - 嵌入式应用
- 配置Ember.js - 特性标识
- Cookbook - 简介
- Cookbook - 用户界面与交互
- Cookbook - 事件处理和数据绑定
- Cookbook - 助手与组件
- Cookbook - 使用对象
- 理解Ember.js - 视图层
- 理解Ember.js - 管理异步
- 理解Ember.js - 模板自动更新
- 理解Ember.js - 调试
- 理解Ember.js - 运行循环
测试 - 测试组件
英文原文:http://emberjs.com/guides/testing/testing-components/
单元测试方案和计算属性与之前单元测试基础中说明的相同,因为Ember.Component
集成自Ember.Object
。
设置
在测试组件之前,需要确定测试应用的div
已经加到测试的html文件中:
1 2 | <!-- as of time writing, ID attribute needs to be named exactly ember-testing --> <div id="ember-testing"></div> |
此外还需要通知Ember
使用这个元素来重新渲染应用。
1 | App.rootElement = '#ember-testing' |
组件可以使用moduleForComponent
助手来进行测试。下面是一个简单的Ember
控件:
1 2 3 4 5 6 7 | App.PrettyColorComponent = Ember.Component.extend({ classNames: ['pretty-color'], attributeBindings: ['style'], style: function() { return 'color: ' + this.get('name') + ';'; }.property('name') }); |
其对应的Handlebars
模板:
1 | Pretty Color: {{name}} |
对这个控件进行单元测试可以使用moduleForComponent
助手。助手将通过名称来查找这个组件(pretty-color)和其模板(如果存在)。
1 | moduleForComponent('pretty-color'); |
现在每个测试有了一个subject()
函数,该函数是组件工厂的create
方法的一个别名。
下面是测试改变组件的颜色后,看看HTML是否重新渲染了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | test('changing colors', function(){ // this.subject() is available because we used moduleForComponent var component = this.subject(); // we wrap this with Ember.run because it is an async function Ember.run(function(){ component.set('name','red'); }); // first call to $() renders the component. equal(this.$().attr('style'), 'color: red;'); // another async function, so we need to wrap it with Ember.run Ember.run(function(){ component.set('name', 'green'); }); equal(this.$().attr('style'), 'color: green;'); }); |
另外一个可能的测试是检查组件的模板是否被正确地渲染了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | test('template is rendered with the color name', function(){ // this.subject() is available because we used moduleForComponent var component = this.subject(); // first call to $() renders the component. equal($.trim(this.$().text()), 'Pretty Color:'); // we wrap this with Ember.run because it is an async function Ember.run(function(){ component.set('name', 'green'); }); equal($.trim(this.$().text()), 'Pretty Color: green'); }); |
在线示例
与DOM中的组件交互
Ember组件可以方便的用来创建有力的、交互的、自包含的自定义HTML元素。正因为此,不仅测试组件自身的方法很重要,测试用户与组件的交互也一样的重要。
下面看一个非常简单的组件,该组件只是在被点击时设置自己的标题:
1 2 3 4 5 6 7 8 9 | App.MyFooComponent = Em.Component.extend({ title:'Hello World', actions:{ updateTitle: function(){ this.set('title', 'Hello Ember World'); } } }); |
下面将使用集成测试助手来与渲染的组件进行交互。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | moduleForComponent('my-foo', 'MyFooComponent'); test('clicking link updates the title', function() { var component = this.subject(); // append the component to the DOM this.append(); // assert default state equal(find('h2').text(), 'Hello World'); // perform click action click('button'); andThen(function() { // wait for async helpers to complete equal(find('h2').text(), 'Hello Ember World'); }); }); |
在线示例
具有内置布局的组件
一些组件并不适用一个分离的模板。模板可以通过布局属性嵌入在组件代码中。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | App.MyFooComponent = Ember.Component.extend({ // layout supercedes template when rendered layout: Ember.Handlebars.compile( "<h2>I'm a little {{noun}}</h2><br/>" + "<button {{action 'clickFoo'}}>Click Me</button>" ), noun: 'teapot', actions:{ changeName: function(){ this.set('noun', 'embereño'); } } }); |
在本例中,也将对于组件的交互进行测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | moduleForComponent('my-foo', 'MyFooComponent'); test('clicking link updates the title', function() { var component = this.subject(); // append the component to the DOM this.append(); // assert default state equal(find('h2').text(), "I'm a little teapot"); // perform click action click('button'); andThen(function() { // wait for async helpers to complete equal(find('h2').text(), "I'm a little embereño"); }); }); |
在线示例
程序化组件交互
另外一种测试组件的方法是通过直接调用组件函数来取代与DOM进行交互。这里采用与之前相同的例子作为测试的对象,不同的是通过编码直接进行测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | moduleForComponent('my-foo', 'MyFooComponent'); test('clicking link updates the title', function() { var component = this.subject(); // append the component to the DOM, returns DOM instance var $component = this.append(); // assert default state equal($component.find('h2').text(), "I'm a little teapot"); // send action programmatically Em.run(function(){ component.send('changeName'); }); equal($component.find('h2').text(), "I'm a little embereño"); }); |
在线示例
组件中sendAction
验证
组件经常使用sendAction
,这是与Ember应用交互的一种方式。下面是一个简单的组件,当一个按钮被点击时,发送internalAction
操作:
1 2 3 4 5 6 7 8 9 | App.MyFooComponent = Ember.Component.extend({ layout:Ember.Handlebars.compile("<button {{action 'doSomething'}}></button>"), actions:{ doSomething: function(){ this.sendAction('internalAction'); } } }); |
在测试中,将创建一个僵尸对象,用来接收组件发送的操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | moduleForComponent('my-foo', 'MyFooComponent'); test('trigger external action when button is clicked', function() { // tell our test to expect 1 assertion expect(1); // component instance var component = this.subject(); // component dom instance var $component = this.append(); var targetObject = { externalAction: function(){ // we have the assertion here which will be // called when the action is triggered ok(true, 'external Action was called!'); } }; // setup a fake external action to be called when // button is clicked component.set('internalAction', 'externalAction'); // set the targetObject to our dummy object (this // is where sendAction will send it's action to) component.set('targetObject', targetObject); // click the button click('button'); }); |
在线示例
使用其他组件的组件
有时候将组件拆分为父子组件更容易维护,下面是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | App.MyAlbumComponent = Ember.Component.extend({ tagName: 'section', layout: Ember.Handlebars.compile( "<section>" + " <h3>{{title}}</h3>" + " {{yield}}" + "</section>" ), titleBinding: ['title'] }); App.MyKittenComponent = Ember.Component.extend({ tagName: 'img', attributeBindings: ['width', 'height', 'src'], src: function() { return 'http://placekitten.com/' + this.get('width') + '/' + this.get('height'); }.property('width', 'height') }); |
使用这个组件可能如下面代码所示:
1 2 3 4 5 | {{#my-album title="Cats"}} {{my-kitten width="200" height="300"}} {{my-kitten width="100" height="100"}} {{my-kitten width="50" height="50"}} {{/my-album}} |
通过needs
回调来测试这些包含子组件的组件非常容易。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | moduleForComponent('my-album', 'MyAlbumComponent', { needs: ['component:my-kitten'] }); test('renders kittens', function() { expect(2); // component instance var component = this.subject({ template: Ember.Handlebars.compile( '{{#my-album title="Cats"}}' + ' {{my-kitten width="200" height="300"}}' + ' {{my-kitten width="100" height="100"}}' + ' {{my-kitten width="50" height="50"}}' + '{{/my-album}}' ) }); // append component to the dom var $component = this.append(); // perform assertions equal($component.find('h3:contains("Cats")').length, 1); equal($component.find('img').length, 3); }); |
在线示例
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论