Skip to content

Commit

Permalink
[use] 完善 AutoGrid 单元测试
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhang-Wei-666 committed Nov 5, 2024
1 parent ebfd271 commit be90544
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 121 deletions.
310 changes: 197 additions & 113 deletions packages/components/src/auto-grid/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,134 +106,218 @@ describe('auto-grid', () => {
expect(children[12].innerHTML.trim()).toBe('2');
});

it('启用折叠时, 超出指定显示行数的子元素不会渲染', async () => {
const wrapper = mount(MixteAutoGrid, {
props: { itemWidth: 200, collapsed: true },
slots: {
default: Array.from({ length: 10 }).map((_, i) => h('div', `item-${i + 1}`)),
},
describe('collapsed & collapsedRows', () => {
it('启用折叠时, 超出指定显示行数的子元素不会渲染', async () => {
const wrapper = mount(MixteAutoGrid, {
props: { itemWidth: 200, collapsed: true },
slots: {
default: Array.from({ length: 10 }).map((_, i) => h('div', `item-${i + 1}`)),
},
});

// 未设置显示行数时, 默认只显示一行
wrapper.setProps({ width: '400' });
await nextTick();
expect(wrapper.element.children.length).toBe(2);

// 设置显示行数为 1
wrapper.setProps({ width: '400', collapsedRows: '1' });
await nextTick();
expect(wrapper.element.children.length).toBe(2);

// 设置显示行数为 2
wrapper.setProps({ width: '400', collapsedRows: '2' });
await nextTick();
expect(wrapper.element.children.length).toBe(4);

// 行数足够时, 显示所有子元素
wrapper.setProps({ width: '400', collapsedRows: '5' });
await nextTick();
expect(wrapper.element.children.length).toBe(10);

// 宽度足够时, 显示所有子元素
wrapper.setProps({ width: '2000', collapsedRows: '1' });
await nextTick();
expect(wrapper.element.children.length).toBe(10);
});

// 未设置显示行数时, 默认只显示一行
wrapper.setProps({ width: '400' });
await nextTick();
expect(wrapper.element.children.length).toBe(2);

// 设置显示行数为 1
wrapper.setProps({ width: '400', collapsedRows: '1' });
await nextTick();
expect(wrapper.element.children.length).toBe(2);

// 设置显示行数为 2
wrapper.setProps({ width: '400', collapsedRows: '2' });
await nextTick();
expect(wrapper.element.children.length).toBe(4);

// 行数足够时, 显示所有子元素
wrapper.setProps({ width: '400', collapsedRows: '5' });
await nextTick();
expect(wrapper.element.children.length).toBe(10);

// 宽度足够时, 显示所有子元素
wrapper.setProps({ width: '2000', collapsedRows: '1' });
await nextTick();
expect(wrapper.element.children.length).toBe(10);
});

it('启用折叠时并且有子元素溢出时, 可以使用 overflowSuffix 插槽替代最后一个子节点显示', async () => {
const renderCount = ref(0);
const wrapper = mount(MixteAutoGrid, {
props: { itemWidth: 200, collapsed: true },
slots: {
default: () => Array.from({ length: renderCount.value }).map((_, i) => h('div', `item-${i + 1}`)),
overflowSuffix: 'item-overflowSuffix',
},
it('启用折叠时并且有子元素溢出时, 可以使用 overflowSuffix 插槽替代最后一个子节点显示', async () => {
const renderCount = ref(0);
const wrapper = mount(MixteAutoGrid, {
props: { itemWidth: 200, collapsed: true },
slots: {
default: () => Array.from({ length: renderCount.value }).map((_, i) => h('div', `item-${i + 1}`)),
overflowSuffix: 'item-overflowSuffix',
},
});

// 单行无节点溢出, 不显示 overflowSuffix 插槽
renderCount.value = 10;
wrapper.setProps({ width: '2000', collapsedRows: '1' });
await nextTick();
expect(wrapper.element.children.length).toBe(10);
Array.from((wrapper.element as HTMLDivElement).children).forEach((child, i) => {
expect(child.innerHTML.trim()).toBe(`<div>item-${i + 1}</div>`);
});

// 单行有节点溢出, 显示 overflowSuffix 插槽
renderCount.value = 11;
wrapper.setProps({ width: '2000', collapsedRows: '1' });
await nextTick();
expect(wrapper.element.children.length).toBe(10);
Array.from((wrapper.element as HTMLDivElement).children).forEach((child, i) => {
if (i < 9) expect(child.innerHTML.trim()).toBe(`<div>item-${i + 1}</div>`);
else expect(child.innerHTML.trim()).toBe('item-overflowSuffix');
});

// 多行无节点溢出, 不显示 overflowSuffix 插槽
renderCount.value = 20;
wrapper.setProps({ width: '2000', collapsedRows: '2' });
await nextTick();
expect(wrapper.element.children.length).toBe(20);
Array.from((wrapper.element as HTMLDivElement).children).forEach((child, i) => {
expect(child.innerHTML.trim()).toBe(`<div>item-${i + 1}</div>`);
});

// 多行有节点溢出, 显示 overflowSuffix 插槽
renderCount.value = 21;
wrapper.setProps({ width: '2000', collapsedRows: '2' });
await nextTick();
expect(wrapper.element.children.length).toBe(20);
Array.from((wrapper.element as HTMLDivElement).children).forEach((child, i) => {
if (i < 19) expect(child.innerHTML.trim()).toBe(`<div>item-${i + 1}</div>`);
else expect(child.innerHTML.trim()).toBe('item-overflowSuffix');
});
});

// 单行无节点溢出, 不显示 overflowSuffix 插槽
renderCount.value = 10;
wrapper.setProps({ width: '2000', collapsedRows: '1' });
await nextTick();
expect(wrapper.element.children.length).toBe(10);
Array.from((wrapper.element as HTMLDivElement).children).forEach((child, i) => {
expect(child.innerHTML.trim()).toBe(`<div>item-${i + 1}</div>`);
});
it('启用折叠时并且有子元素溢出时, 切换 overflowSuffix 插槽', async () => {
const wrapper = mount(
defineComponent({
props: {
renderOverflowSuffix: {
type: Boolean,
default: true,
},
},
render() {
const other: Record<string, () => VNodeChild> = {};

if (this.renderOverflowSuffix)
other.overflowSuffix = () => 'item-overflowSuffix';

// 单行有节点溢出, 显示 overflowSuffix 插槽
renderCount.value = 11;
wrapper.setProps({ width: '2000', collapsedRows: '1' });
await nextTick();
expect(wrapper.element.children.length).toBe(10);
Array.from((wrapper.element as HTMLDivElement).children).forEach((child, i) => {
if (i < 9) expect(child.innerHTML.trim()).toBe(`<div>item-${i + 1}</div>`);
else expect(child.innerHTML.trim()).toBe('item-overflowSuffix');
return h(MixteAutoGrid, { width: 400, itemWidth: 200, collapsed: true }, {
default: () => Array.from({ length: 3 }).map((_, i) => h('div', `item-${i + 1}`)),
...other,
});
},
}),
);

// 默认显示 overflowSuffix 插槽
expect(wrapper.element.children.length).toBe(2);
expect(wrapper.element.children[0].innerHTML.trim()).toBe('<div>item-1</div>');
expect(wrapper.element.children[1].innerHTML.trim()).toBe('item-overflowSuffix');

// 切换 overflowSuffix 插槽
await wrapper.setProps({ renderOverflowSuffix: false });
expect(wrapper.element.children.length).toBe(2);
expect(wrapper.element.children[0].innerHTML.trim()).toBe('<div>item-1</div>');
expect(wrapper.element.children[1].innerHTML.trim()).toBe('<div>item-2</div>');

// 切换 overflowSuffix 插槽
await wrapper.setProps({ renderOverflowSuffix: true });
expect(wrapper.element.children.length).toBe(2);
expect(wrapper.element.children[0].innerHTML.trim()).toBe('<div>item-1</div>');
expect(wrapper.element.children[1].innerHTML.trim()).toBe('item-overflowSuffix');

// 切换 overflowSuffix 插槽
await wrapper.setProps({ renderOverflowSuffix: false });
expect(wrapper.element.children.length).toBe(2);
expect(wrapper.element.children[0].innerHTML.trim()).toBe('<div>item-1</div>');
expect(wrapper.element.children[1].innerHTML.trim()).toBe('<div>item-2</div>');
});
});

describe('fluid', () => {
it('启用平铺子元素时, 若只有一行子元素, 那么会平铺所有子元素', () => {
const wrapper = mount(MixteAutoGrid, {
props: { width: '800', itemWidth: '200', fluid: true },
slots: {
default: () => Array.from({ length: 3 }).map((_, i) => h('div', `item-${i + 1}`)),
},
});

const element = wrapper.element as HTMLDivElement;

// 多行无节点溢出, 不显示 overflowSuffix 插槽
renderCount.value = 20;
wrapper.setProps({ width: '2000', collapsedRows: '2' });
await nextTick();
expect(wrapper.element.children.length).toBe(20);
Array.from((wrapper.element as HTMLDivElement).children).forEach((child, i) => {
expect(child.innerHTML.trim()).toBe(`<div>item-${i + 1}</div>`);
// 渲染节点数量
expect(element.children.length).toBe(3);

// 组件样式应该调整为平铺所有子元素
expect(postcssJs.objectify(postcss.parse(element.getAttribute('style')!))).toStrictEqual({
...defaultStyle,
width: '800px',
gridTemplateColumns: 'repeat(3, 1fr)',
});
});

// 多行有节点溢出, 显示 overflowSuffix 插槽
renderCount.value = 21;
wrapper.setProps({ width: '2000', collapsedRows: '2' });
await nextTick();
expect(wrapper.element.children.length).toBe(20);
Array.from((wrapper.element as HTMLDivElement).children).forEach((child, i) => {
if (i < 19) expect(child.innerHTML.trim()).toBe(`<div>item-${i + 1}</div>`);
else expect(child.innerHTML.trim()).toBe('item-overflowSuffix');
it('启用平铺子元素时, 若不止一行子元素, 那么不会会平铺所有子元素', () => {
const wrapper = mount(MixteAutoGrid, {
props: { width: '800', itemWidth: '200', fluid: true },
slots: {
default: () => Array.from({ length: 5 }).map((_, i) => h('div', `item-${i + 1}`)),
},
});

const element = wrapper.element as HTMLDivElement;

// 渲染节点数量
expect(element.children.length).toBe(5);

// 组件样式不应平铺所有子元素,而是按照正常的列数
expect(postcssJs.objectify(postcss.parse(element.getAttribute('style')!))).toStrictEqual({
...defaultStyle,
width: '800px',
gridTemplateColumns: 'repeat(4, 1fr)',
});
});
});

it('启用折叠时并且有子元素溢出时, 切换 overflowSuffix 插槽', async () => {
const wrapper = mount(
defineComponent({
props: {
renderOverflowSuffix: {
type: Boolean,
default: true,
},
},
render() {
const other: Record<string, () => VNodeChild> = {};
describe('组件导出变量', () => {
it('columnCount', async () => {
const wrapper = mount(MixteAutoGrid, {
props: { width: 600, itemWidth: 200 },
});
await nextTick();

if (this.renderOverflowSuffix)
other.overflowSuffix = () => 'item-overflowSuffix';
// 获取组件实例
const vm = wrapper.vm as any;
expect(vm.columnCount).toBe(3);

return h(MixteAutoGrid, { width: 400, itemWidth: 200, collapsed: true }, {
default: () => Array.from({ length: 3 }).map((_, i) => h('div', `item-${i + 1}`)),
...other,
});
// 修改宽度,测试 columnCount 的变化
await wrapper.setProps({ width: 400 });
expect(vm.columnCount).toBe(2);

await wrapper.setProps({ width: 199 });
expect(vm.columnCount).toBe(1);
});

it('isCollapsed', async () => {
const wrapper = mount(MixteAutoGrid, {
props: { collapsed: true, collapsedRows: 1, itemWidth: 200, width: 400 },
slots: {
default: () => Array.from({ length: 5 }).map((_, i) => h('div', `item-${i + 1}`)),
},
}),
);

// 默认显示 overflowSuffix 插槽
expect(wrapper.element.children.length).toBe(2);
expect(wrapper.element.children[0].innerHTML.trim()).toBe('<div>item-1</div>');
expect(wrapper.element.children[1].innerHTML.trim()).toBe('item-overflowSuffix');

// 切换 overflowSuffix 插槽
await wrapper.setProps({ renderOverflowSuffix: false });
expect(wrapper.element.children.length).toBe(2);
expect(wrapper.element.children[0].innerHTML.trim()).toBe('<div>item-1</div>');
expect(wrapper.element.children[1].innerHTML.trim()).toBe('<div>item-2</div>');

// 切换 overflowSuffix 插槽
await wrapper.setProps({ renderOverflowSuffix: true });
expect(wrapper.element.children.length).toBe(2);
expect(wrapper.element.children[0].innerHTML.trim()).toBe('<div>item-1</div>');
expect(wrapper.element.children[1].innerHTML.trim()).toBe('item-overflowSuffix');

// 切换 overflowSuffix 插槽
await wrapper.setProps({ renderOverflowSuffix: false });
expect(wrapper.element.children.length).toBe(2);
expect(wrapper.element.children[0].innerHTML.trim()).toBe('<div>item-1</div>');
expect(wrapper.element.children[1].innerHTML.trim()).toBe('<div>item-2</div>');
});
await nextTick();

// 获取组件实例
const vm = wrapper.vm as any;
expect(vm.isCollapsed).toBe(true);

// 修改 collapsedRows,使得不折叠
await wrapper.setProps({ collapsedRows: 3 });
expect(vm.isCollapsed).toBe(false);
});
});

sharedTest(MixteAutoGrid);
Expand Down
10 changes: 5 additions & 5 deletions packages/components/src/auto-grid/src/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
const props = defineProps<AutoGridProps>();
const slots = defineSlots<AutoGridSlots>();
const { rootRef, collapsedRows, length, rootStyle } = useAutoGrid(props);
const { rootRef, collapsedRows, columnCount, rootStyle } = useAutoGrid(props);
/** 所有子元素 */
const children = computed(() => {
Expand All @@ -34,7 +34,7 @@
let renderChildren = children.value;
if (props.collapsed) {
const rowsChildrenLength = collapsedRows.value * length.value;
const rowsChildrenLength = collapsedRows.value * columnCount.value;
renderChildren = renderChildren.slice(0, rowsChildrenLength);
Expand All @@ -49,7 +49,7 @@
});
const finalRootStyle = computed<CSSProperties>(() => {
if (props.fluid && (children.value.length < length.value)) {
if (props.fluid && (children.value.length < columnCount.value)) {
return {
...rootStyle.value,
gridTemplateColumns: `repeat(${children.value.length}, 1fr)`,
Expand All @@ -69,10 +69,10 @@
defineExpose({
/** 每行可以渲染的子元素数量 */
columnCount: length,
columnCount,
/** 子元素是否折叠 */
isCollapsed: computed(() => {
return props.collapsed && children.value.length > collapsedRows.value * length.value;
return props.collapsed && children.value.length > collapsedRows.value * columnCount.value;
}),
});
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ export function useAutoGrid(props: CommomAutoGridProps) {
const collapsedRows = computed(() => isNumeric(props.collapsedRows) ? Math.max(1, +props.collapsedRows) : 1);

/** 每行可以渲染的子元素数量 */
const length = computed(() => {
const columnCount = computed(() => {
return Math.floor((width.value + gapX.value) / (itemWidth.value + gapX.value)) || 1;
});

const rootStyle = computed<CSSProperties>(() => ({
width: isCustomWidth.value ? `${props.width}px` : '100%',
display: 'grid',
gridTemplateColumns: `repeat(${length.value}, 1fr)`,
gridTemplateColumns: `repeat(${columnCount.value}, 1fr)`,
columnGap: `${gapX.value}px`,
rowGap: `${gapY.value}px`,
}));
Expand All @@ -56,7 +56,7 @@ export function useAutoGrid(props: CommomAutoGridProps) {
rootRef,

collapsedRows,
length,
columnCount,

rootStyle,
};
Expand Down

0 comments on commit be90544

Please sign in to comment.