起步

我们在 github 上放有一个关于起步的示例工程。

安装

快速尝鲜 San Test Utils 的办法就是克隆我们的 demo 仓库再加上基本的设置和依赖安装。

$ git clone https://github.com/ecomfe/san-test-utils.git
$ cd docs/demo/start
$ npm install

你会发现该工程包含了一个简单的组件 counter.js

// counter.js

import san from 'san';

export default san.defineComponent({
    template: `<div>
        <span class="count">{{count}}</span>
        <button on-click="increment">Increment</button>
    </div>`,

    initData() {
        return {
            count: 0
        }
    },

    increment() {
        let count = this.data.get('count');
        this.data.set('count', ++count);
    }
})

挂载组件

San Test Utils 通过将它们隔离挂载,然后模拟必要的输入 (data、用户事件) 和对输出 (渲染结果、触发的自定义事件) 的断言来测试 San 组件。

被挂载的组件会返回到一个 包裹器 内,而包裹器会暴露很多封装、遍历和查询其内部的 San 组件实例的便捷的方法。

你可以通过 attach 方法来创建包裹器。让我们创建一个名叫 test.js 的文件:

// test.js

// 从测试实用工具集中导入 `attach()` 方法
// 同时导入你要测试的组件
import {attach} from 'san-test-utils';
import counter from './counter';

// 现在挂载组件,你便得到了这个包裹器
const wrapper = attach(Counter);

// 你可以通过 `wrapper.vm` 访问实际的 San 实例
const vm = wrapper.vm;

// 我们对 San Test Utils 的探索也由此开始
console.log(wrapper);

测试组件渲染出来的 HTML

现在我们已经有了这个包裹器,我们能做的第一件事就是确认该组件渲染出来的 HTML 符合预期。

import {attach} from 'san-test-utils';
import counter from './counter';

describe('Counter', () => {
    // 现在挂载组件,你便得到了这个包裹器
    const wrapper = attach(counter);

    it('renders the correct markup', () => {
        expect(wrapper.html()).toContain('<span class="count">0</span>');
    });

    // 也便于检查已存在的元素
    it('has a button', () => {
        expect(wrapper.contains('button')).toBe(true);
    });
});

现在运行 npm test 进行测试。你应该看得到测试通过。

模拟用户交互

当用户点击按钮的时候,我们的计数器应该递增。为了模拟这一行为,我们首先需要通过 wrapper.find() 定位该按钮,此方法返回一个该按钮元素的包裹器。然后我们能够通过对该按钮包裹器调用 .trigger() 来模拟点击。

it('button click should increment the count', () => {
    expect(wrapper.vm.data.get('count')).toBe(0);
    const button = wrapper.find('button');
    button.trigger('click');
    expect(wrapper.vm.data.get('count')).toBe(1);
});

关于异步

San 会异步的将未生效的 DOM 更新批量应用,以避免因数据反复突变而导致的无谓的重渲染。这也是为什么在实践过程中我们经常在触发状态改变后用 San.nextTick 来等待 San 把实际的 DOM 更新做完的原因。

在上面的例子中,当按钮被点击时,count会被同步+1,但对应的 DOM 实际并没有更新,如果想测试对应 DOM 是否正常渲染,可以使用如下写法:

it('button click should increment the count', done => {
    expect(wrapper.vm.data.get('count')).toBe(0);
    const button = wrapper.find('button');
    button.trigger('click');
    expect(wrapper.vm.data.get('count')).toBe(1);
    san.nextTick(() => {
        expect(wrapper.html()).toContain('<span class="count">1</span>');
        done();
    });
});

下一步是什么