Skip to content

Commit

Permalink
test: added KMenu onOpenChange unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
baiwusanyu-c committed Jan 8, 2025
1 parent 5d17ab5 commit db152a7
Show file tree
Hide file tree
Showing 8 changed files with 326 additions and 25 deletions.
36 changes: 28 additions & 8 deletions components/Menu/__test__/__snapshots__/menu.spec.ts.snap

Large diffs are not rendered by default.

112 changes: 112 additions & 0 deletions components/Menu/__test__/fixture/open-change.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<script lang="ts">
import { KMenu, KMenuItem } from '@ikun-ui/menu';
import type { SubMenuType } from '@ikun-ui/menu';
let items: SubMenuType[] = [
{
label: 'Navigation Three - Su',
title: 'Navigation Three - Su',
uid: 'SubMenu',
popupClassName: 'ikun-test',
icon: 'i-carbon-logo-vue',
children: [
{
type: 'group',
label: 'Item 1',
title: 'Item 1',
popupClassName: 'ikun-test',
uid: 'asda',
// icon: 'i-carbon-logo-vue',
children: [
{
label: 'Option 1',
title: 'Option 1',
uid: 'setting:1',
popupClassName: 'ikun-test',
disabled: false,
// icon: 'i-carbon-logo-vue',
children: [
{
label: 'Option 3333 Option 3333 Option 3333',
title: 'Option 3333',
icon: 'i-carbon-logo-vue',
popupClassName: 'ikun-test',
uid: 'setting:3333'
}
]
},
{
label: 'Navigation Four-dv',
// icon: 'i-carbon-logo-react',
type: 'divider',
popupClassName: 'ikun-test',
uid: 'alipay-dv'
},
{
label: 'Option 2',
popupClassName: 'ikun-test',
uid: 'setting:2'
}
]
},
{
label: 'Item 2',
uid: 'asdqqda',
disabled: true,
popupClassName: 'ikun-test',
// icon: 'i-carbon-logo-vue',
children: [
{
label: 'Option 3',
popupClassName: 'ikun-test',
uid: 'setting:3'
},
{
label: 'Option 4',
popupClassName: 'ikun-test',
uid: 'setting:4'
}
]
}
]
}
];
let triggerTime = 0;
let res = {};
const handleClick = (item: CustomEvent) => {
res = item.detail;
triggerTime = triggerTime + 1;
};
</script>

<div class="w-full fsc">
<KMenu
mode="vertical"
id="open_change_test_vertical"
on:openChange={handleClick}
triggerSubMenuAction="click"
ctxKey="11"
>
<KMenuItem {items} ctxKey="11" />
</KMenu>
<KMenu
mode="inline"
id="open_change_test_inline"
triggerSubMenuAction="click"
on:openChange={handleClick}
ctxKey="22"
>
<KMenuItem {items} ctxKey="22" />
</KMenu>
<KMenu
mode="horizontal"
id="open_change_test_horizontal"
triggerSubMenuAction="click"
on:openChange={handleClick}
ctxKey="33"
>
<KMenuItem {items} ctxKey="33" />
</KMenu>
<div id="trigger_time">{triggerTime}</div>
<div>{JSON.stringify(res)}</div>
</div>
132 changes: 132 additions & 0 deletions components/Menu/__test__/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import KMenuDelay from './fixture/delay.svelte';
import KMenuAction from './fixture/action.svelte';
import KMenuClick from './fixture/click.svelte';
import KMenuSelect from './fixture/select.svelte';
import KMenuOpenChange from './fixture/open-change.svelte';
import { tick } from 'svelte';
let host;

Expand Down Expand Up @@ -528,6 +529,137 @@ describe('Test: KMenu', () => {
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('4');
});

test('events: onOpenChange & vertical', async () => {
const instance = new KMenuOpenChange({
target: host
});
expect(instance).toBeTruthy();
await tick();
const vEl = host.querySelector('#open_change_test_vertical');
const resEl = host.querySelector('#trigger_time');
const vTrigger = vEl.querySelector('.k-menu-item');
expect(resEl.innerHTML).toBe('0');
vTrigger.dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('1');
expect(host.innerHTML).matchSnapshot();

const vContent = vEl.querySelectorAll('[slot="contentEl"]');
const vTriggerSub = vContent[0].querySelectorAll('[slot="triggerEl"]');
vTriggerSub[0].dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('1');

vTriggerSub[1].dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('2');
expect(host.innerHTML).matchSnapshot();

vTriggerSub[3].dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('3');
expect(host.innerHTML).matchSnapshot();

host.dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('4');
expect(host.innerHTML).matchSnapshot();
});

test('events: onOpenChange & inline', async () => {
const instance = new KMenuOpenChange({
target: host
});
expect(instance).toBeTruthy();
await tick();
const vEl = host.querySelector('#open_change_test_inline');
const resEl = host.querySelector('#trigger_time');
let vTrigger = vEl.querySelectorAll('[slot="triggerEl"]');
expect(resEl.innerHTML).toBe('0');
vTrigger[0].dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('1');
expect(host.innerHTML).matchSnapshot();

vTrigger = vEl.querySelectorAll('[slot="triggerEl"]');
vTrigger[1].dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('1');

vTrigger[2].dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('2');
expect(host.innerHTML).matchSnapshot();

vTrigger[2].dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('3');
expect(host.innerHTML).matchSnapshot();

vTrigger[0].dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('4');
expect(host.innerHTML).matchSnapshot();
});

test('events: onOpenChange & horizontal', async () => {
const instance = new KMenuOpenChange({
target: host
});
expect(instance).toBeTruthy();
await tick();
const vEl = host.querySelector('#open_change_test_horizontal');
const resEl = host.querySelector('#trigger_time');
const vTrigger = vEl.querySelector('[data-k-menu-h="1"]').querySelector('.k-menu-item');
expect(resEl.innerHTML).toBe('0');
vTrigger.dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('1');
expect(host.innerHTML).matchSnapshot();

const vContent = vEl.querySelectorAll('[slot="contentEl"]');
const vTriggerSub = vContent[0].querySelectorAll('[data-k-menu-h="2"]');
vTriggerSub[0]
.querySelector('.k-menu-item')
.dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('1');

vTriggerSub[1]
.querySelector('.k-menu-item')
.dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('2');
expect(host.innerHTML).matchSnapshot();

vTriggerSub[3]
.querySelector('.k-menu-item')
.dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('3');
expect(host.innerHTML).matchSnapshot();

host.dispatchEvent(new Event('click', { bubbles: true }));
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(resEl.innerHTML).toBe('4');
expect(host.innerHTML).matchSnapshot();
});
});

describe('Test: KMenuItems', () => {
Expand Down
49 changes: 43 additions & 6 deletions components/Menu/src/item.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,17 @@
// set open
if (hasSub(it)) {
value.open = !value.open;
const orgOpen = value.open;
if (value.selectedDeps && ctxProps.selectable) {
value.selected = !!value.selectedDeps!.size;
}
if (menuCtx) {
menuCtx.syncUids(value.uid!, 'open', value.open ? 'add' : 'delete');
menuCtx.onOpenChange([...menuCtx.__openUids!]);
if ((ctxProps.mode === 'vertical' && !orgOpen) || ctxProps.mode !== 'vertical') {
value.open = !value.open;
menuCtx.syncUids(value.uid!, 'open', value.open ? 'add' : 'delete');
menuCtx.onOpenChange([...menuCtx.__openUids!]);
}
}
}
Expand Down Expand Up @@ -257,13 +260,17 @@
popoverRef.forEach((ref: any, index: number) => {
if (hiddenIndex.has(index)) return;
const it = itemsList[index] || moreItem;
ref && ref.updateShow && ref.updateShow(it.open);
if (it.open) {
ref && ref.updateShow && ref.updateShow(it.open);
}
});
} else {
setTimeout(() => {
popoverRef.forEach((ref: any, index: number) => {
const it = itemsList[index] || moreItem;
ref && ref.updateShow && ref.updateShow(it.open);
if (it.open) {
ref && ref.updateShow && ref.updateShow(it.open);
}
});
}, 300);
}
Expand Down Expand Up @@ -449,7 +456,7 @@
[`${prefixCls}-disabled`]: true
};
if (hasSub(it)) {
it.children = it.children.map((item) => {
it.children = it.children!.map((item) => {
return {
...item,
disabledParent: true
Expand Down Expand Up @@ -572,6 +579,30 @@
}
return res;
};
function clearVerticalOpenStatus(it: SubMenuType, list = itemsList) {
return list.map((value) => {
if (value.uid === it.uid && !isGroup(it)) {
// set open
if (hasSub(it)) {
value.open = false;
if (menuCtx) {
menuCtx.syncUids(value.uid!, 'open', 'delete');
menuCtx.onOpenChange([...menuCtx.__openUids!]);
}
}
}
if (hasSub(value)) {
value.children = clearVerticalOpenStatus(it, value.children);
}
return value;
});
}
function onVerticalPopoverChange(it: SubMenuType, e: CustomEvent) {
if (it.disabled || it.disabledParent || e.detail) return;
itemsList = clearVerticalOpenStatus(it);
}
</script>

{#each itemsList as it, index (it.uid)}
Expand Down Expand Up @@ -670,6 +701,9 @@
arrow={false}
width={level === 1 ? 'auto' : '100%'}
placement="right"
on:change={(e) => {
onVerticalPopoverChange(it, e);
}}
on:animateStart={showSubMenuPopover}
offset={setPopoverOffset}
fallbackPlacements={['right', 'left']}
Expand Down Expand Up @@ -774,6 +808,9 @@
bind:this={popoverRef[index]}
width={widths[index]}
order={index}
on:change={(e) => {
onVerticalPopoverChange(it, e);
}}
opacity={ops[index]}
attrsTrigger={{ 'data-k-menu-h': `${level}` }}
arrow={false}
Expand Down
6 changes: 3 additions & 3 deletions components/Menu/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,17 @@ export type KMenuProps = {
};

// onClick 点击 MenuItem 调用此函数 inline
// TODO: 👀 onOpenChange SubMenu 展开/关闭的回调 inline
// onOpenChange SubMenu 展开/关闭的回调 inline
// onSelect 被选中时调用(点击子菜单标题不触发) inline
// onDeSelect 被选中时调用(点击子菜单标题不触发) inline

// onClick 点击 MenuItem 调用此函数 vertical
// TODO: 👀 onOpenChange SubMenu 展开/关闭的回调 vertical
// onOpenChange SubMenu 展开/关闭的回调 vertical
// onSelect 被选中时调用(点击子菜单标题不触发) vertical
// onDeSelect 被选中时调用(点击子菜单标题不触发) inline

// onClick 点击 MenuItem 调用此函数 horizontal
// TODO: 👀 onOpenChange SubMenu 展开/关闭的回调 horizontal
// onOpenChange SubMenu 展开/关闭的回调 horizontal
// onSelect 被选中时调用(点击子菜单标题不触发) horizontal
// onDeSelect 被选中时调用(点击子菜单标题不触发) inline

Expand Down
Loading

0 comments on commit db152a7

Please sign in to comment.