博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Dojo 如何测试 widget
阅读量:7117 次
发布时间:2019-06-28

本文共 6540 字,大约阅读时间需要 21 分钟。

测试

commit 84e254725f41d60f624ab5ad38fe82e15b6348a2

用于测试和断言 Dojo 部件期望的虚拟 DOM 和行为的简单 API。

Features

  • 简单、熟悉和少量的 API
  • 重点测试 Dojo 虚拟 DOM 结构
  • 默认不需要 DOM
  • 全面支持函数式编程和 tsx 声明

harness

当使用 @dojo/framework/testing 时,harness 是最重要的 API,主要用于设置每一个测试并提供一个执行虚拟 DOM 断言和交互的上下文。目的在于当更新 propertieschildren 和失效部件时,镜像部件的核心行为,并且不需要任何特殊或自定义逻辑。

API

harness(renderFunction: () => WNode, customComparators?: CustomComparator[]): Harness;
  • renderFunction: 返回被测部件 WNode 的函数
  • customComparators: 一组自定义比较器的描述符。每个描述符提供一个比较器函数,用于比较通过 selectorproperty 定位的 properties

harness 函数返回的 Harness 对象提供了与被测部件交互的精简 API:

Harness

  • : 对被测部件完整的渲染结果执行断言
  • : 对被测部件的一部分渲染结果执行断言
  • : 用于在被测部件的节点上触发函数
  • : 根据提供的索引返回对应的渲染器

使用 @dojo/framework/widget-core 中的 w() 函数设置一个待测试的部件简单且眼熟:

class MyWidget extends WidgetBase<{ foo: string }> {    protected render() {        const { foo } = this.properties;        return v('div', { foo }, this.children);    }}const h = harness(() => w(MyWidget, { foo: 'bar' }, ['child']));

如下所示,harness 函数也支持 tsx 语法。README 文档中其余示例使用编程式的 w() API,在 unit tests 中可查看更多 tsx 示例。

const h = harness(() => 
child
);

renderFunction 是延迟执行的,所以可在断言之间包含额外的逻辑来操作部件的 propertieschildren

let foo = 'bar';const h = harness(() => {    return w(MyWidget, { foo }, [ 'child' ]));};h.expect(/** assertion that includes bar **/);// update the property that is passed to the widgetfoo = 'foo';h.expect(/** assertion that includes foo **/)

Custom Comparators

在某些情况下,我们在测试期间无法得知属性的确切值,所以需要使用自定义比较描述符。

描述符中有一个定位要检查的虚拟节点的 selector,一个应用自定义比较的属性名和一个接收实际值并返回一个 boolean 类型断言结果的比较器函数。

const compareId = {    selector: '*', // all nodes    property: 'id',    comparator: (value: any) => typeof value === 'string' // checks the property value is a string};const h = harness(() => w(MyWidget, {}), [compareId]);

对于所有的断言,返回的 harness API 将只对 id 属性使用 comparator 进行测试,而不是标准的相等测试。

selectors

harness API 支持 CSS style 选择器概念,来定位要断言和操作的虚拟 DOM 中的节点。查看 以了解更多信息。

除了标准 API 之外还提供:

  • 支持将定位节点 key 属性简写为 @ 符号
  • 当使用标准的 . 来定位样式类时,使用 classes 属性而不是 class 属性

harness.expect

测试中最常见的需求是断言部件的 render 函数的输出结构。expect 接收一个返回被测部件期望的渲染结果的函数作为参数。

API

expect(expectedRenderFunction: () => DNode | DNode[], actualRenderFunction?: () => DNode | DNode[]);
  • expectedRenderFunction: 返回查询节点期望的 DNode 结构的函数
  • actualRenderFunction: 一个可选函数,返回被断言的实际 DNode 结构
h.expect(() =>    v('div', { key: 'foo' }, [w(Widget, { key: 'child-widget' }), 'text node', v('span', { classes: ['class'] })]));

expect 也可以接收第二个可选参数,返回要断言的渲染结果的函数。

h.expect(() => v('div', { key: 'foo' }), () => v('div', { key: 'foo' }));

如果实际的渲染输出和期望的渲染输出不同,就会抛出一个异常,并使用结构化的可视方法,用 (A) (实际值)和 (E) (期望值)指出所有不同点。

断言的错误输出示例:

v("div", {    "classes": [        "root",(A)     "other"(E)     "another"    ],    "onclick": "function"}, [    v("span", {        "classes": "span",        "id": "random-id",        "key": "label",        "onclick": "function",        "style": "width: 100px"    }, [        "hello 0"    ])    w(ChildWidget, {        "id": "random-id",        "key": "widget"    })    w("registry-item", {        "id": true,        "key": "registry"    })])

harness.expectPartial

expectPartial 根据 断言部件的部分渲染输出。

API

expectPartial(selector: string, expectedRenderFunction: () => DNode | DNode[]);
  • selector: 用于查找目标节点的选择器
  • expectedRenderFunction: 返回查询节点期望的 DNode 结构的函数
  • actualRenderFunction: 一个可选函数,返回被断言的实际 DNode 结构

示例:

h.expectPartial('@child-widget', () => w(Widget, { key: 'child-widget' }));

harness.trigger

harness.trigger()selector 定位的节点上调用 name 指定的函数。

interface FunctionalSelector {    (node: VNode | WNode): undefined | Function;}trigger(selector: string, functionSelector: string | FunctionalSelector, ...args: any[]): any;
  • selector: 用于查找目标节点的选择器
  • functionSelector: 要么是从节点的属性中找到的被调用的函数名,或者是从节点的属性中返回一个函数的函数选择器
  • args: 为定位到的函数传入的参数

如果有返回结果,则返回的是被触发函数的结果。

用法示例:

// calls the `onclick` function on the first node with a key of `foo`h.trigger('@foo', 'onclick');
// calls the `customFunction` function on the first node with a key of `bar` with an argument of `100`// and receives the result of the triggered functionconst result = h.trigger('@bar', 'customFunction', 100);

functionalSelector 返回部件属性中的函数。函数也会被触发,与使用普通字符串 functionSelector 的方式相同。

用法示例:

假定有如下 VDOM 树结构,

v(Toolbar, {    key: 'toolbar',    buttons: [        {            icon: 'save',            onClick: () => this._onSave()        },        {            icon: 'cancel',            onClick: () => this._onCancel()        }    ]});

并且你想触发 save 按钮的 onClick 函数。

h.trigger('@buttons', (renderResult: DNode
) => { return renderResult.properties.buttons[0].onClick;});

harness.getRender

harness.getRender() 返回索引指定的渲染器,如果没有提供索引则返回最后一个渲染器。

getRender(index?: number);
  • index: 要返回的渲染器的索引

用法示例:

// Returns the result of the last renderconst render = h.getRender();
// Returns the result of the render for the index providedh.getRender(1);

Assertion Templates

断言模板(assertion template)允许你构建一个传入 h.expect() 的期望渲染函数。断言模板背后的思想来自经常要断言整个渲染输出,并需要修改断言的某些部分。

要使用断言模板,首先需要导入模块:

import assertionTemplate from '@dojo/framework/testing/assertionTemplate';

然后,在你的测试中,你可以编写一个基本断言,它是部件的默认渲染状态:

假定有以下部件:

class NumberWidget extends WidgetBase<{ num?: number }> {    protected render() {        const { num } = this.properties;        const message = num === undefined ? 'no number passed' : `the number ${num}`;        return v('div', [v('span', [message])]);    }}

基本断言如下所示:

const baseAssertion = assertionTemplate(() => {    return v('div', [        v('span', { '~key': 'message' }, [ 'no number passed' ]);    ]);});

在测试中这样写:

it('should render no number passed when no number is passed as a property', () => {    const h = harness(() => w(NumberWidget, {}));    h.expect(baseAssertion);});

现在我们看看,为 NumberWidget 部件传入 num 属性后,如何测试数据结果:

it('should render the number when a number is passed as a property', () => {    const numberAssertion = baseAssertion.setChildren('~message', ['the number 5']);    const h = harness(() => w(NumberWidget, { num: 5 }));    h.expect(numberAssertion);});

这里,我们使用 baseAssertion 的 setChildren() api,然后我们使用特殊的 ~ 选择器来定位 key 值为 ~message 的节点。~key 属性(使用 tsx 的模板中是 assertion-key)是断言模板的一个特殊属性,在断言时会被删除,因此在匹配渲染结构时不会显示出来。此功能允许你修饰断言模板,以便能简单的选择节点,而不需要扩展实际的部件渲染函数。一旦我们获取到 message 节点,我们就可以将其子节点设置为期望的 the number 5,然后在 h.expect 中使用生成的模板。需要注意的是,断言模板在设置值时总是返回一个新的断言模板,这可以确保你不会意外修改现有模板(可能导致其他测试失败),并允许你基于新模板,增量逐层构建出新的模板。

断言模板具有以下 API:

setChildren(selector: string, children: DNode[], type?: 'prepend' | 'replace' | 'append'): AssertionTemplateResult;setProperty(selector: string, property: string, value: any): AssertionTemplateResult;getChildren(selector: string): DNode[];getProperty(selector: string, property: string): any;

转载地址:http://ukbel.baihongyu.com/

你可能感兴趣的文章
HTML,CSS,font-family:中文字体的英文名称 (宋体 微软雅黑)
查看>>
观察者模式
查看>>
iOS应用内语言切换功能
查看>>
如何写好一个UITableView
查看>>
上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?...
查看>>
NET Core-TagHelper实现分页标签
查看>>
Cesium原理篇:6 Renderer模块(1: Buffer)
查看>>
defered,promise回顾
查看>>
svn提交时出现很多乱文件怎么解决
查看>>
std::unique_lock<std::mutex> or std::lock_guard<std::mutex> C++11 区别
查看>>
SQL - ROW_NUMBER,Rank 添加序号列
查看>>
常见排序算法总结与实现(冒泡、插入、选择、希尔、堆排序、归并、快排)
查看>>
python3.x 和 python2.x关于 urllib的用法
查看>>
在pycharm中进行nosetests并输出测试报告
查看>>
树莓派:设置与软件安装
查看>>
JQuery日记_5.14 Sizzle选择器(七)
查看>>
debian8上安装pyspider - pyspider中文文档 - pyspider中文网
查看>>
【WaaCaa】一款开源科学作图/数据可视化工具 —— 诞生篇
查看>>
idea,eclipse创建多模块项目
查看>>
Tomcat中常见线程说明
查看>>