Skip to content

Commit

Permalink
Merge pull request #492 from TabSpace/develop
Browse files Browse the repository at this point in the history
test(tree): tree 组件添加 filter 属性的测试
  • Loading branch information
chaishi authored Mar 18, 2022
2 parents 0a0f253 + 88eec17 commit 7f15b35
Show file tree
Hide file tree
Showing 9 changed files with 459 additions and 376 deletions.
17 changes: 13 additions & 4 deletions examples/tree/demos/filter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,19 @@ export default {
methods: {
onInput(state) {
console.info('onInput:', state);
this.filterByText = (node) => {
const rs = node.data.label.indexOf(this.filterText) >= 0;
return rs;
};
if (this.filterText) {
// 存在过滤文案,才启用过滤
this.filterByText = (node) => {
const rs = node.data.label.indexOf(this.filterText) >= 0;
// 命中的节点会强制展示
// 命中节点的路径节点会锁定展示
// 未命中的节点会隐藏
return rs;
};
} else {
// 过滤文案为空,则还原 tree 为无过滤状态
this.filterByText = null;
}
},
},
};
Expand Down
32 changes: 19 additions & 13 deletions src/tree/td-tree.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// import Vue, { VNode, VueConstructor, CreateElement } from 'vue';
import { VNode } from 'vue';
import upperFirst from 'lodash/upperFirst';
import pick from 'lodash/pick';
Expand Down Expand Up @@ -120,19 +119,31 @@ export default mixins(getConfigReceiverMixins<TypeTreeInstance, TreeConfig>('tre
const { store } = this;
const nodesMap = this.getNodesMap();
const allNodes = store.getNodes();
const curNodesMap = new Map();
this.treeNodes = allNodes.map((node: TreeNode) => {
// 如果有,重新生成新的vnode
if (node.visible) {
curNodesMap.set(node.value, 1);
// 维持住已经渲染的节点,不进行dom的增删
let nodeView = nodesMap.get(node.value);
// 如果需要展示,生成新的vnode
if (!nodeView && node.visible) {
// 初次仅渲染可显示的节点
// 不存在节点视图,则创建该节点视图并插入到当前位置
const nodeView = this.renderItem(node);
nodeView = this.renderItem(node);
nodesMap.set(node.value, nodeView);
return nodeView;
}
// 维持住已经渲染的节点,不进行dom的增删
const nodeView = nodesMap.get(node.value);
return nodeView;
});

// 更新缓存后,被删除的节点要移除掉,避免内存泄露
this.$nextTick(() => {
const keys = [...nodesMap.keys()];
keys.forEach((value: string) => {
if (!curNodesMap.get(value)) {
nodesMap.delete(value);
}
});
curNodesMap.clear();
});
},
// 同步 Store 选项
updateStoreConfig() {
Expand Down Expand Up @@ -474,11 +485,6 @@ export default mixins(getConfigReceiverMixins<TypeTreeInstance, TreeConfig>('tre
</transition-group>
);

return (
<div class={classList}>
{treeNodeList}
{emptyNode}
</div>
);
return <div class={classList}>{emptyNode || treeNodeList}</div>;
},
});
15 changes: 13 additions & 2 deletions src/tree/tree-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default mixins(getConfigReceiverMixins<Vue, TreeConfig>('tree'), keepAnim
data() {
return {
data: null,
clicked: false,
};
},
methods: {
Expand Down Expand Up @@ -280,6 +281,14 @@ export default mixins(getConfigReceiverMixins<Vue, TreeConfig>('tree'), keepAnim
return itemNodes;
},
handleClick(evt: MouseEvent) {
// checkbox 上也有 emit click 事件
// 用这个逻辑避免重复的 click 事件被触发
if (this.clicked) return;
this.clicked = true;
setTimeout(() => {
this.clicked = false;
});

const { node } = this;
const state: TypeEventState = {
mouseEvent: evt,
Expand All @@ -304,9 +313,11 @@ export default mixins(getConfigReceiverMixins<Vue, TreeConfig>('tree'), keepAnim
this.data = this.node.data;
}
},
destroyed() {
this.data = null;
},
render(createElement: CreateElement) {
const { node } = this;

const { tree, level, value } = node;

if (!tree || !tree.nodeMap.get(value)) {
Expand All @@ -317,7 +328,7 @@ export default mixins(getConfigReceiverMixins<Vue, TreeConfig>('tree'), keepAnim
return (
<div
class={classList}
data-value={node.value}
data-value={value}
data-level={level}
style={styles}
onClick={(evt: MouseEvent) => this.handleClick(evt)}
Expand Down
5 changes: 0 additions & 5 deletions test/ssr/__snapshots__/ssr.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2968,7 +2968,6 @@ exports[`ssr snapshot test renders ./examples/config-provider/demos/others.vue c
<div size="medium" class="t-time-picker__input"><span class="t-time-picker__input-placeholder">select time</span></div>
</div> <br><br><br> <span class="t-tag t-tag--primary t-size-m t-tag--dark t-tag--close">Fearure Tag<svg fill="none" viewBox="0 0 16 16" width="1em" height="1em" class="t-icon t-icon-close-circle t-tag__icon-close"><path fill="currentColor" d="M4.98 10.31L7.3 8 5 5.69l.7-.7L8 7.28 10.31 5l.7.7L8.72 8l2.3 2.31-.7.7L8 8.72 5.69 11l-.7-.7z" fill-opacity="0.9"></path><path fill="currentColor" d="M8 1a7 7 0 110 14A7 7 0 018 1zm0 1a6 6 0 100 12A6 6 0 008 2z" fill-opacity="0.9"></path></svg></span> <span class="t-tag t-tag--success t-size-m t-tag--dark t-tag--close">Fearure Tag<svg fill="none" viewBox="0 0 16 16" width="1em" height="1em" class="t-icon t-icon-close-circle t-tag__icon-close"><path fill="currentColor" d="M4.98 10.31L7.3 8 5 5.69l.7-.7L8 7.28 10.31 5l.7.7L8.72 8l2.3 2.31-.7.7L8 8.72 5.69 11l-.7-.7z" fill-opacity="0.9"></path><path fill="currentColor" d="M8 1a7 7 0 110 14A7 7 0 018 1zm0 1a6 6 0 100 12A6 6 0 008 2z" fill-opacity="0.9"></path></svg></span> <span class="t-tag t-tag--warning t-size-m t-tag--dark t-tag--close">Fearure Tag<svg fill="none" viewBox="0 0 16 16" width="1em" height="1em" class="t-icon t-icon-close-circle t-tag__icon-close"><path fill="currentColor" d="M4.98 10.31L7.3 8 5 5.69l.7-.7L8 7.28 10.31 5l.7.7L8.72 8l2.3 2.31-.7.7L8 8.72 5.69 11l-.7-.7z" fill-opacity="0.9"></path><path fill="currentColor" d="M8 1a7 7 0 110 14A7 7 0 018 1zm0 1a6 6 0 100 12A6 6 0 008 2z" fill-opacity="0.9"></path></svg></span> <span class="t-tag t-tag--danger t-size-m t-tag--dark t-tag--close">Fearure Tag<svg fill="none" viewBox="0 0 16 16" width="1em" height="1em" class="t-icon t-icon-close-circle t-tag__icon-close"><path fill="currentColor" d="M4.98 10.31L7.3 8 5 5.69l.7-.7L8 7.28 10.31 5l.7.7L8.72 8l2.3 2.31-.7.7L8 8.72 5.69 11l-.7-.7z" fill-opacity="0.9"></path><path fill="currentColor" d="M8 1a7 7 0 110 14A7 7 0 018 1zm0 1a6 6 0 100 12A6 6 0 008 2z" fill-opacity="0.9"></path></svg></span> <br><br>
<div class="t-tree t-tree--transition">
<transition-group-stub tag="div" name="t-tree-toggle" enterActiveClass="t-tree__item--enter-active" leaveActiveClass="t-tree__item--leave-active" class="t-tree__list"></transition-group-stub>
<div class="t-tree__empty">Tree Empty Data</div>
</div> <br><br>
<div class="t-tree t-tree--transition">
Expand Down Expand Up @@ -15259,21 +15258,17 @@ exports[`ssr snapshot test renders ./examples/tree/demos/disabled.vue correctly
exports[`ssr snapshot test renders ./examples/tree/demos/empty.vue correctly 1`] = `
<div class="tdesign-tree-demo">
<div class="t-tree t-tree--transition">
<transition-group-stub tag="div" name="t-tree-toggle" enterActiveClass="t-tree__item--enter-active" leaveActiveClass="t-tree__item--leave-active" class="t-tree__list"></transition-group-stub>
<div class="t-tree__empty">暂无数据</div>
</div><br>
<div class="t-tree t-tree--transition">
<transition-group-stub tag="div" name="t-tree-toggle" enterActiveClass="t-tree__item--enter-active" leaveActiveClass="t-tree__item--leave-active" class="t-tree__list"></transition-group-stub>
<div class="t-tree__empty">😊 空数据(string)</div>
</div><br>
<div class="t-tree t-tree--transition">
<transition-group-stub tag="div" name="t-tree-toggle" enterActiveClass="t-tree__item--enter-active" leaveActiveClass="t-tree__item--leave-active" class="t-tree__list"></transition-group-stub>
<div class="t-tree__empty">
<div>😊 空数据( empty props )</div>
</div>
</div><br>
<div class="t-tree t-tree--transition">
<transition-group-stub tag="div" name="t-tree-toggle" enterActiveClass="t-tree__item--enter-active" leaveActiveClass="t-tree__item--leave-active" class="t-tree__list"></transition-group-stub>
<div class="t-tree__empty">
<div>😊 空数据(slot)</div>
</div>
Expand Down
28 changes: 0 additions & 28 deletions test/unit/tree/__snapshots__/demo.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3177,13 +3177,6 @@ exports[`Tree:demo empty demo works fine 1`] = `
<div
class="t-tree t-tree--transition"
>
<transition-group-stub
class="t-tree__list"
enteractiveclass="t-tree__item--enter-active"
leaveactiveclass="t-tree__item--leave-active"
name="t-tree-toggle"
tag="div"
/>
<div
class="t-tree__empty"
>
Expand All @@ -3195,13 +3188,6 @@ exports[`Tree:demo empty demo works fine 1`] = `
<div
class="t-tree t-tree--transition"
>
<transition-group-stub
class="t-tree__list"
enteractiveclass="t-tree__item--enter-active"
leaveactiveclass="t-tree__item--leave-active"
name="t-tree-toggle"
tag="div"
/>
<div
class="t-tree__empty"
>
Expand All @@ -3213,13 +3199,6 @@ exports[`Tree:demo empty demo works fine 1`] = `
<div
class="t-tree t-tree--transition"
>
<transition-group-stub
class="t-tree__list"
enteractiveclass="t-tree__item--enter-active"
leaveactiveclass="t-tree__item--leave-active"
name="t-tree-toggle"
tag="div"
/>
<div
class="t-tree__empty"
>
Expand All @@ -3233,13 +3212,6 @@ exports[`Tree:demo empty demo works fine 1`] = `
<div
class="t-tree t-tree--transition"
>
<transition-group-stub
class="t-tree__list"
enteractiveclass="t-tree__item--enter-active"
leaveactiveclass="t-tree__item--leave-active"
name="t-tree-toggle"
tag="div"
/>
<div
class="t-tree__empty"
>
Expand Down
37 changes: 37 additions & 0 deletions test/unit/tree/api.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { mount } from '@vue/test-utils';
import Tree from '@/src/tree/index.ts';
import { delay } from './kit';

describe('Tree:api', () => {
jest.useRealTimers();
describe('remove', () => {
it('删除指定节点后,应当移除 dom 节点', async () => {
const data = [
{
value: 't1',
children: [
{
value: 't1.1',
},
],
},
{
value: 't2',
},
];
const wrapper = mount({
render() {
return <Tree ref="tree" data={data} expandAll />;
},
});
expect(wrapper.find('[data-value="t1"]').exists()).toBe(true);
expect(wrapper.find('[data-value="t1.1"]').exists()).toBe(true);
expect(wrapper.find('[data-value="t2"]').exists()).toBe(true);

wrapper.vm.$refs.tree.remove('t2');
await delay(10);

expect(wrapper.find('[data-value="t2"]').exists()).toBe(false);
});
});
});
83 changes: 83 additions & 0 deletions test/unit/tree/filter.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { mount } from '@vue/test-utils';
import Tree from '@/src/tree/index.ts';
import { delay } from './kit';

describe('Tree:filter', () => {
jest.useRealTimers();
describe(':props.filter', () => {
it('数据可过滤展示', async () => {
const data = [
{
value: 't1',
children: [
{
value: 't1.1',
},
{
value: 't1.2',
},
],
},
];

const wrapper = mount({
data() {
return {
filter: null,
};
},
created() {
this.filter = (node) => node.value.indexOf('2') >= 0;
},
render() {
return <Tree data={data} expandAll filter={this.filter}></Tree>;
},
});

await delay(10);

const t1 = wrapper.find('[data-value="t1"]');
let t1d1 = wrapper.find('[data-value="t1.1"]');
const t1d2 = wrapper.find('[data-value="t1.2"]');

// t1.2 被命中, t1 被锁定, t1.1 隐藏
expect(t1.exists()).toBe(true);
expect(t1.classes('t-tree__item--visible')).toBe(true);
expect(t1.classes('t-is-disabled')).toBe(true);
expect(t1d1.exists()).toBe(false);
expect(t1d2.classes('t-tree__item--visible')).toBe(true);

await wrapper.setData({
filter: (node) => node.value.indexOf('1.1') >= 0,
});

await delay(10);

// t1.1 被命中, t1 被锁定, t1.2 隐藏
t1d1 = wrapper.find('[data-value="t1.1"]');
expect(t1d1.exists()).toBe(true);
expect(t1d1.classes('t-tree__item--visible')).toBe(true);
expect(t1d2.classes('t-tree__item--visible')).toBe(false);

await wrapper.setData({
filter: (node) => node.value.indexOf('1.3') >= 0,
});
await delay(10);

// 无命中,全部隐藏
expect(t1.classes('t-tree__item--visible')).toBe(false);
expect(t1d1.classes('t-tree__item--visible')).toBe(false);
expect(t1d2.classes('t-tree__item--visible')).toBe(false);

await wrapper.setData({
filter: null,
});
await delay(10);

// 清除过滤器,全部显示
expect(t1.classes('t-tree__item--visible')).toBe(true);
expect(t1d1.classes('t-tree__item--visible')).toBe(true);
expect(t1d2.classes('t-tree__item--visible')).toBe(true);
});
});
});
Loading

0 comments on commit 7f15b35

Please sign in to comment.