Skip to content

Commit

Permalink
Merge pull request #821 from Tencent/test/notice-bar/unit
Browse files Browse the repository at this point in the history
test: add unit test for notice-bar
  • Loading branch information
LeeJim committed Aug 31, 2022
2 parents 7c0134f + f86e502 commit 72cd86a
Show file tree
Hide file tree
Showing 6 changed files with 359 additions and 13 deletions.
2 changes: 2 additions & 0 deletions src/notice-bar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ spline: message
isComponent: true
---

<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-94%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-94%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-88%25-blue" /></span>
## 引入

全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
Expand Down Expand Up @@ -51,6 +52,7 @@ isComponent: true

| 名称 | 类型 | 默认值 | 说明 | 必传 |
| ---- | ---- | ------ | ---- | -- |
external-classes | Array | - | 组件类名,分别用于设置 组件外层元素、文本内容、前缀图标、右侧额外信息、后缀图标 等元素类名。`['t-class', 't-class-content', 't-class-prefix-icon', 't-class-extra', 't-class-suffix-icon']` | N
| content | String / Slot | - | 文本内容 | N |
| extra | String / Slot | - | 右侧额外信息| N |
| marquee | Boolean / Object | false | 跑马灯效果。speed 指速度控制;loop 指循环播放次数,值为 -1 表示循环播放,值为 0 表示不循环播放;delay 表示延迟多久开始播放。TS 类型:`boolean | DrawMarquee` `interface DrawMarquee { speed?: number; loop?: number; delay?: number }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/notice-bar/type.ts) | N |
Expand Down
47 changes: 47 additions & 0 deletions src/notice-bar/__test__/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`notice-bar props : marquee 1`] = `
<main>
<t-notice-bar
class="base"
>
<wx-view
class="t-notice-bar t-notice-bar--info t-class"
>
<wx-view
class="t-notice-bar__prefix-icon t-class-prefix-icon"
bind:tap="clickPrefixIcon"
>
<t-icon>
<wx-label
class="t-class t-icon t-icon-error-circle-filled t-icon-base"
style=";;"
bind:tap="onTap"
/>
</t-icon>
</wx-view>
<wx-view
class="t-notice-bar__content-wrap"
bind:tap="clickContent"
>
<wx-view
animation=""
class="t-notice-bar__content t-class-content "
>
<wx-view>
提示文字描述提示文字描述提示文字描述提示文字描述文
</wx-view>
</wx-view>
</wx-view>
<wx-view
class="t-notice-bar__extra t-class-extra"
bind:tap="clickExtra"
/>
<wx-view
class="t-notice-bar__suffix-icon t-class-suffix-icon"
bind:tap="clickSuffixIcon"
/>
</wx-view>
</t-notice-bar>
</main>
`;
297 changes: 297 additions & 0 deletions src/notice-bar/__test__/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
import simulate from 'miniprogram-simulate';
import path from 'path';
import similateApi from 'miniprogram-simulate/src/api';
import * as Util from '../../common/utils';

// simulate提供一些基本的api,如getSystemInfoSync, createAnimation, 如果涉及到复杂的链式调用需要自行 mock
global.wx = {
...similateApi,
};

const mockGetAnimationFrame = jest.spyOn(Util, 'getAnimationFrame');
const mockGetRect = jest.spyOn(Util, 'getRect');

// 设置每次调用函数的值
mockGetAnimationFrame.mockImplementation((cb) => {
return cb();
});

// 调用函数第1次的返回值 nodeRect
mockGetRect.mockImplementationOnce(() => {
return {
width: 350,
};
});
// 调用函数第2次的返回值 warpID
mockGetRect.mockImplementationOnce(() => {
return {
width: 313,
};
});

describe('notice-bar', () => {
const noticeBar = simulate.load(path.resolve(__dirname, `../notice-bar`), 't-notice-bar', {
less: true,
rootPath: path.resolve(__dirname, '../..'),
});
jest.resetModules();
const icon = simulate.load(path.resolve(__dirname, `../../icon/icon`), 't-icon', {
less: true,
rootPath: path.resolve(__dirname, '../..'),
});

describe('props', () => {
it(': visible', () => {
const id = simulate.load({
template: `<t-notice-bar
class="base"
visible="{{visible}}"></t-notice-bar>`,
data: {
visible: true,
},
usingComponents: {
't-notice-bar': noticeBar,
},
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
expect(comp.querySelector('.base >>> .t-notice-bar')).toBeDefined();

comp.setData({
visible: false,
});
expect(comp.querySelector('.base >>> .t-notice-bar')).not.toBeDefined();

comp.detach();
});

it(': theme', () => {
const id = simulate.load({
template: `<t-notice-bar
class="base"
visible="{{visible}}"
theme="{{theme}}"
></t-notice-bar>`,
data: {
visible: true,
theme: 'info',
},
usingComponents: {
't-notice-bar': noticeBar,
},
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
const $component = comp.querySelector('.base >>> .t-notice-bar');
expect($component.dom.getAttribute('class').includes('t-notice-bar--info')).toBeTruthy();

comp.setData({
theme: 'success',
});
expect($component.dom.getAttribute('class').includes('t-notice-bar--success')).toBeTruthy();
});

it(': content', () => {
const id = simulate.load({
template: `<t-notice-bar
class="base"
visible="{{visible}}"
content="{{content}}"></t-notice-bar>`,
data: {
visible: true,
content: 'notice-bar content',
},
usingComponents: {
't-notice-bar': noticeBar,
},
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
const $noticeBar = comp.querySelector('.base');
const $content = comp.querySelector('.base >>> .t-notice-bar__content');

expect($content.dom.textContent.trim()).toBe($noticeBar.instance.data.content);
});

it(': extra', () => {
const id = simulate.load({
template: `<t-notice-bar
class="base"
visible="{{visible}}"
extra="{{extra}}"></t-notice-bar>`,
data: {
visible: true,
extra: 'notice-bar extra',
},
usingComponents: {
't-notice-bar': noticeBar,
},
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
const $noticeBar = comp.querySelector('.base');
const $extra = comp.querySelector('.base >>> .t-notice-bar__extra');

expect($extra.dom.textContent.trim()).toBe($noticeBar.instance.data.extra);
});

it(': prefix-icon', () => {
const id = simulate.load({
template: `<t-notice-bar
class="base"
visible="{{visible}}"
prefixIcon="{{prefixIcon}}"></t-notice-bar>`,
data: {
visible: true,
prefixIcon: 'null',
},
usingComponents: {
't-notice-bar': noticeBar,
},
});

const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
const $prefixIcon = comp.querySelector('.base >>> .t-notice-bar__prefix-icon');
expect($prefixIcon.dom.innerHTML).toBe('');

comp.setData({
prefixIcon: 'add',
});

const iconId = simulate.load({
template: `<t-icon name="{{name}}"></t-icon>`,
data: {
name: 'add',
},
usingComponents: {
't-icon': icon,
},
});
const iconComp = simulate.render(iconId);
expect($prefixIcon.dom.innerHTML).toContain(iconComp.dom.innerHTML);
});

const delay = 7100;
it(
': marquee',
async () => {
const id = simulate.load({
template: `<t-notice-bar
class="base"
visible="{{visible}}"
marquee="{{marquee}}"
content="{{content}}"
></t-notice-bar>`,
data: {
visible: true,
content: '提示文字描述提示文字描述提示文字描述提示文字描述文',
// marquee: true,
marquee: {
speed: 80,
loop: -1,
delay: 0,
},
},
usingComponents: {
't-notice-bar': noticeBar,
},
});

const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
await simulate.sleep(delay); // 等待 delay 后再继续后续代码的执行

expect(comp.toJSON()).toMatchSnapshot();
const $instance = comp.querySelector('.base');
const $content = comp.querySelector('.base >>> .t-notice-bar__content');
expect($content.dom.textContent.trim()).toBe($instance.data.content);

// TODO: marquee 需要支持 Object && Boolean, 单测环境中,marquee值会固定为默认值 false
// marquee = false, content内容开启超出换行
expect($content.dom.getAttribute('class')).not.toContain('t-notice-bar__content-wrapable');
// const componentInstance = simulate.render(noticeBar).instance;
// expect(componentInstance.data.marquee).toEqual(comp.instance.data.marquee);
},
delay,
);
});

describe('slots', () => {
it(': content', () => {
const text = 'content 内容';
const id = simulate.load({
template: `<t-notice-bar
class="base"
visible="{{visible}}"
>
<text slot="content">{{text}}</text>
</t-notice-bar>`,
data: {
visible: true,
text,
},
usingComponents: {
't-notice-bar': noticeBar,
},
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
const $content = comp.querySelector('.base >>> .t-notice-bar__content');
expect($content.dom.textContent).toBe(text);
});
});

describe('event', () => {
let triggerName = null;
const click = jest.fn((e) => {
const { trigger } = e.detail;
triggerName = trigger;
});

it(': click', async () => {
const id = simulate.load({
template: `<t-notice-bar
class="base
visible="{{visible}}"
suffixIcon="chevron-right"
extra="详情"
content="提示文字描述提示文字描述提示文字描述"
bind:click="click"
></t-notice-bar>`,
data: {
visible: true,
},
methods: {
click,
},
usingComponents: {
't-notice-bar': noticeBar,
},
});
const comp = simulate.render(id);
comp.attach(document.createElement('parent-wrapper'));
const $prefixIcon = comp.querySelector('.base >>> .t-notice-bar__prefix-icon');
const $content = comp.querySelector('.base >>> .t-notice-bar__content');
const $extra = comp.querySelector('.base >>> .t-notice-bar__extra');
const $suffixIcon = comp.querySelector('.base >>> .t-notice-bar__suffix-icon');
$prefixIcon.dispatchEvent('tap');
await simulate.sleep(0);
expect(triggerName).toBe('prefix-icon');
expect(click).toHaveBeenCalledTimes(1);
$content.dispatchEvent('tap');
await simulate.sleep(0);
expect(triggerName).toBe('content');
expect(click).toHaveBeenCalledTimes(2);
$extra.dispatchEvent('tap');
await simulate.sleep(0);
expect(triggerName).toBe('extra');
expect(click).toHaveBeenCalledTimes(3);

$suffixIcon.dispatchEvent('tap');
await simulate.sleep(0);
expect(triggerName).toBe('suffix-icon');
expect(click).toHaveBeenCalledTimes(4);
});
});
});
Loading

0 comments on commit 72cd86a

Please sign in to comment.