Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/devui-vue/devui-cli/commands/code-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const eslintCheck = async (components) => {

const unitTestSingle = async (name) => {
log(chalkUnitTest(`Start unit test ${name}...`));
await shell.exec(`pnpm test --filter vue-devui -- --colors --noStackTrace --testMatch **/${name}.spec.ts`);
await shell.exec(`pnpm test --filter vue-devui -- --colors --noStackTrace --testMatch **/${name}/**/{*.spec.ts,*.spec.tsx}`);
log(chalkUnitTest(`Unit test ${name} finished!`));
};

Expand Down
29 changes: 29 additions & 0 deletions packages/devui-vue/devui/tree/__tests__/basic-tree/basic-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ref } from 'vue';

export const basicData = ref([
{
label: 'Parent node 1',
open: true,
disabled: true,
children: [
{
label: 'Parent node 1-1',
disableToggle: true,
children: [
{
label: 'Leaf node 1-1-1',
}
]
},
{
label: 'Leaf node 1-2',
},
{
label: 'Leaf node 1-3',
},
]
},
{
label: 'Leaf node 2',
}
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ComponentPublicInstance, nextTick } from 'vue';
import { DOMWrapper, mount, VueWrapper } from '@vue/test-utils';
import { Tree } from '../../';
import { basicData } from './basic-data';

describe('Basic tree should include rendering of nested nodes and responses to hover, click and expand/collapse events.', () => {
let wrapper: VueWrapper<ComponentPublicInstance>;
let firstNode: Omit<DOMWrapper<Element>, 'exists'>;
let lastNode: Omit<DOMWrapper<Element>, 'exists'>;

beforeAll(() => {
wrapper = mount({
setup() {
return () => {
return <Tree data={basicData.value} />;
};
},
});

firstNode = wrapper.get('.devui-tree-node:first-child');
lastNode = wrapper.get('.devui-tree-node:last-child');
});

afterAll(() => {
wrapper.unmount();
});

it('Should render tree container correctly.', () => {
expect(wrapper.classes()).toContain('devui-tree');
});

it('Should render correct number of child nodes.', () => {
expect(wrapper.element.childElementCount).toBe(5);
});

it('Should render correct node content.', () => {
expect(firstNode.text()).toBe('Parent node 1');
expect(lastNode.text()).toBe('Leaf node 2');
});

it('Should render the style of child node correctly.', () => {
const childNodeParent = wrapper.get('.devui-tree-node:nth-child(2)');
const childNodeLeaf = wrapper.get('.devui-tree-node:nth-child(3)');

expect(childNodeParent.attributes('style').indexOf('padding-left: 24px;') > -1).toBe(true);
expect(childNodeLeaf.attributes('style').indexOf('padding-left: 24px;') > -1).toBe(true);
});

it.todo('Should render the style of node connection line correctly.');

it.todo('The node should be highlighted when clicked.');

it.todo('The node should be disabled and unclickable when disabled is set to true.');

it('The node should expand and collapse correctly when the expand-collapse button is clicked.', async () => {
// 初始状态,节点是展开的
expect(firstNode.classes()).toContain('devui-tree-node__open');

// 点击之后,节点收起
await wrapper.get('.devui-tree-node__folder:first-child').trigger('click');
await nextTick();
expect(firstNode.classes()).not.toContain('devui-tree-node__open');

// 再次点击,节点展开
await wrapper.get('.devui-tree-node__folder:first-child').trigger('click');
await nextTick();
expect(firstNode.classes()).toContain('devui-tree-node__open');
});

it.todo('The node should be disabled and unclickable when disableToggle is set to true.');
});
208 changes: 22 additions & 186 deletions packages/devui-vue/devui/tree/__tests__/tree.spec.ts
Original file line number Diff line number Diff line change
@@ -1,188 +1,24 @@
import { mount, VueWrapper } from '@vue/test-utils';
import type { ComponentPublicInstance } from 'vue';
import { ref, nextTick } from 'vue';
import DTree from '../src/tree';

describe('tree', () => {
let wrapper: VueWrapper<ComponentPublicInstance>;

beforeEach(() => {
const data = ref([
{
label: 'parent node 1 - expanded',
open: true,
disabled: true,
level: 1,
children: [
{
label: 'parent node 11 - folded',
level: 2,
children: [
{
label: 'leaf node 111',
level: 3,
},
{
label: 'leaf node 112',
level: 3,
},
{
label: 'leaf node 113',
level: 3,
},
{
label: 'leaf node 114',
level: 3,
}
]
},
{
label: 'parent node 12 - folded',
disableToggle: true,
level: 2,
children: [
{
label: 'leaf node 121',
level: 3,
},
{
label: 'leaf node 122',
level: 3,
},
{
label: 'leaf node 123',
level: 3,
},
{
label: 'leaf node 124',
level: 3,
}
]
},
{
label: 'parent node 13 - without children - dynamic loading',
isParent: true,
level: 2,
}
]
},
{
label: 'parent node 2 - folded',
level: 1,
children: [
{
label: 'parent node 21 - expanded',
open: true,
level: 2,
children: [
{
label: 'leaf node 211',
level: 3,
},
{
label: 'leaf node 212',
level: 3,
},
{
label: 'leaf node 213',
level: 3,
},
{
label: 'leaf node 214',
level: 3,
}
]
},
{
label: 'parent node 22 - folded',
level: 2,
children: [
{
label: 'leaf node 221',
level: 3,
},
{
label: 'leaf node 222',
level: 3,
},
{
label: 'leaf node 223',
level: 3,
},
{
label: 'leaf node 224',
level: 3,
}
]
},
{
label: 'parent node 23 - folded',
level: 2,
children: [
{
label: 'leaf node 231',
level: 3,
},
{
label: 'leaf node 232',
level: 3,
},
{
label: 'leaf node 233',
level: 3,
},
{
label: 'leaf node 234',
level: 3,
}
]
}
]
},
{
id: 'dynamicNode',
label: 'parent node 3 - without children - dynamic loading',
isParent: true,
level: 1,
data: {
id: 'newChildNode',
name: 'new child node'
}
}
]);

wrapper = mount({
components: { DTree },
template: `
<d-tree :data="data"></d-tree>
`,
setup () {
return {
data,
};
}
});
});

it('should render correctly', () => {
expect(wrapper.classes()).toContain('devui-tree');
expect(wrapper.element.childElementCount).toBe(6);
});

it('should expand and collapse correctly', async () => {
const firstNode = wrapper.get('.devui-tree-node:first-child');

// 初始状态,节点是展开的
expect(firstNode.classes()).toContain('devui-tree-node__open');

// 点击之后,节点收起
await wrapper.get('.devui-tree-node__folder:first-child').trigger('click');
await nextTick();
expect(firstNode.classes()).not.toContain('devui-tree-node__open');

// 再次点击,节点展开
await wrapper.get('.devui-tree-node__folder:first-child').trigger('click');
await nextTick();
expect(firstNode.classes()).toContain('devui-tree-node__open');
});
// 测试节点懒加载功能是否正常
it.todo('should loading child nodes dynamicly when click open button');

// 当节点下只有一个子节点时,应该合并这些节点
it.todo('should merge nodes when there is only one child node');

/**
* 测试嵌套节点渲染和基本交互
* 测试节点懒加载功能是否正常
* 当节点下只有一个子节点时,应该合并这些节点
* 节点的勾选功能正常
* 勾选复选框的禁用状态正常
* 父子check控制功能正常
* 自定义图标功能正常
* 节点的增删改(操作按钮)功能正常
* loading模板功能正常
* 搜索过滤功能正常
* 自定义树中显示和搜索的关键字功能正常
* 拖拽排序功能正常
* 虚拟滚动功能正常
* 无动画功能正常
*/
});
17 changes: 0 additions & 17 deletions packages/devui-vue/devui/tree/src/assets/close.svg

This file was deleted.

14 changes: 0 additions & 14 deletions packages/devui-vue/devui/tree/src/assets/open.svg

This file was deleted.

20 changes: 20 additions & 0 deletions packages/devui-vue/devui/tree/src/components/icon-close.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { VNodeTypes } from 'vue';

export const IconClose = (): VNodeTypes => (
<svg
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
class="svg-icon"
>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0.5" y="0.5" width="15" height="15" rx="2" stroke="#252b3a"></rect>
<path
fill="#252b3a"
d="M8.75,4 L8.75,7.25 L12,7.25 L12,8.75 L8.749,8.75 L8.75,12 L7.25,12 L7.249,8.75 L4,8.75 L4,7.25 L7.25,7.25 L7.25,4 L8.75,4 Z"
></path>
</g>
</svg>
);
17 changes: 17 additions & 0 deletions packages/devui-vue/devui/tree/src/components/icon-open.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { VNodeTypes } from 'vue';

export const IconOpen = (): VNodeTypes => (
<svg
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
class="svg-icon svg-icon-close"
>
<g stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0.5" y="0.5" width="15" height="15" rx="2" stroke="#5e7ce0"></rect>
<rect x="4" y="7" width="8" height="2" fill="#5e7ce0"></rect>
</g>
</svg>
);
Loading