amis2/packages/amis/__tests__/renderers/Form/transfer.test.tsx

1810 lines
43 KiB
TypeScript
Raw Normal View History

merge: feat-virtual-list into master (#5829) * feat: select transfer 除树形模式外,增加虚拟列表能力 (#5612) * feat: select transfer 除树形模式外,增加虚拟列表能力 * 修改分组模式问题 * 更新快照 * transfer 虚拟列表单测补充 * select 虚拟列表单测补充 * 更新 select 快照 * chore: merge master into feat-virtual-list branch (#5716) * chore: combo组件items扩充编辑器的拖拽点位 (#5693) * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * fix: 数字输入框-属性配置-placeholder置灰+边框与form-input统一 amis-saas-4938 (#5666) Co-authored-by: limengyang03 <limengyang03@baidu.com> * feat:Remark组件支持自定义图标 (#5694) * feat:Remark组件支持自定义图标 * 去掉多余内容 Co-authored-by: xujiahao01 <xujiahao01@baidu.com> * fix: 修复 amis本地跑不起来 问题 * fix: https://github.com/baidu/amis/issues/4681 * feat: 使用cross-env 设置NODE_ENV 变量 * perf: 删除重复声明项 * revert: 恢复删除的SchemaRedirect Co-authored-by: 吴多益 <wuduoyi@baidu.com> * feat: ui 组件 form 支持 autoSubmit (#5695) * feat: ui 组件 form 支持 autoSubmit * 下发 onSubmit 否则只能用 handleSubmit 这个会绕过 form 的检测,无法通知到上层 * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 (#5698) * publish beta * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 * fix: filter 过滤器 isTrue/isFalse 问题修复 (#5676) * fix: filter 过滤器 isTrue 问题修复 * 修改 * 修改 * 修改 * chore: InputArray新增默认值示例, 调整Combo组件scaffold逻辑 (#5701) * chore: InputNumber严格判断大数模式,避免错误抛出string类型值 (#5703) * fix: 修复查看代码报 require is not defined 错误 (#5704) * publish beta * fix: 修复查看代码报 require is not defined 错误 * feat: 补充 ConfirmBox ui 控件, 并将 PickerContainer 改成 ConfirmBox 实现 (#5708) * publish beta * feat: 添加 ui ConfirmBox * feat: 补充 confirmBox ui 控件, 并将 pickerContainer 改成 confirmBox 实现 * PickerContainer title 逻辑不变动 * 暴露 InputTableColumnProps * 调整 ts 定义 * 升级 react-hook-form * inputTable 补充数组本身的验证 * Combo 也支持内部数组的验证 * 调整内部验证 * 调整目录 * chore: 优化 locale, theme hoc, 存在 context 直接复用 (#5702) * publish beta * chore: 优化 locale, theme hoc, 存在 context 直接复用 * chore: 日期范围类组件单元测试补充 (#5705) * dateRange * datetimeRange * timeRange * monthRange * quarter and year * 修改 * 修改 * fix: 评分组件 count 支持变量获取 (#5681) * fix: 评分组件 count 支持变量获取 * tokenize 修改为 filter Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: sansiro <sansiro@sansiro.me> * feat: tree 增加虚拟列表 (#5696) * feat: Tree 使用 VirtualList 渲染, 提升大数据时的性能 * fix: 适配编辑和新建 * chore: 增加 Tree 测试用例 * chore: 更新 Tree 测试用例 * feat: Tree虚拟列表,调整props名称 * chore: 清理 Tree 相关的无用代码 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 (#5799) * 其他 transfer 支持虚拟列表属性 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 * add * fix: tree 多级时,通过递归parent来判断展开收起,递归partial判断父元素的Partial状态 (#5807) * fix: 调整 tree 组件中,判断父子关系的方法 (#5814) * Revert "chore: merge master into feat-virtual-list branch (#5716)" (#5825) This reverts commit c9895812989c31d3471d50c2adaf7110478ad0a0. * chore: 更新 tree 虚拟滚动相关快照 和一些优化 Co-authored-by: RUNZE LU <36724300+lurunze1226@users.noreply.github.com> Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: meerkat <kit_hack@outlook.com>
2022-11-28 18:07:45 +08:00
/**
* Transfer 穿
*
* 1.
* 2.
* 3.
* 4.
* 5.
* 6.
* 7.
* 8.
* 9.
* 10.
* 11.
* 12.
merge: feat-virtual-list into master (#5829) * feat: select transfer 除树形模式外,增加虚拟列表能力 (#5612) * feat: select transfer 除树形模式外,增加虚拟列表能力 * 修改分组模式问题 * 更新快照 * transfer 虚拟列表单测补充 * select 虚拟列表单测补充 * 更新 select 快照 * chore: merge master into feat-virtual-list branch (#5716) * chore: combo组件items扩充编辑器的拖拽点位 (#5693) * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * fix: 数字输入框-属性配置-placeholder置灰+边框与form-input统一 amis-saas-4938 (#5666) Co-authored-by: limengyang03 <limengyang03@baidu.com> * feat:Remark组件支持自定义图标 (#5694) * feat:Remark组件支持自定义图标 * 去掉多余内容 Co-authored-by: xujiahao01 <xujiahao01@baidu.com> * fix: 修复 amis本地跑不起来 问题 * fix: https://github.com/baidu/amis/issues/4681 * feat: 使用cross-env 设置NODE_ENV 变量 * perf: 删除重复声明项 * revert: 恢复删除的SchemaRedirect Co-authored-by: 吴多益 <wuduoyi@baidu.com> * feat: ui 组件 form 支持 autoSubmit (#5695) * feat: ui 组件 form 支持 autoSubmit * 下发 onSubmit 否则只能用 handleSubmit 这个会绕过 form 的检测,无法通知到上层 * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 (#5698) * publish beta * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 * fix: filter 过滤器 isTrue/isFalse 问题修复 (#5676) * fix: filter 过滤器 isTrue 问题修复 * 修改 * 修改 * 修改 * chore: InputArray新增默认值示例, 调整Combo组件scaffold逻辑 (#5701) * chore: InputNumber严格判断大数模式,避免错误抛出string类型值 (#5703) * fix: 修复查看代码报 require is not defined 错误 (#5704) * publish beta * fix: 修复查看代码报 require is not defined 错误 * feat: 补充 ConfirmBox ui 控件, 并将 PickerContainer 改成 ConfirmBox 实现 (#5708) * publish beta * feat: 添加 ui ConfirmBox * feat: 补充 confirmBox ui 控件, 并将 pickerContainer 改成 confirmBox 实现 * PickerContainer title 逻辑不变动 * 暴露 InputTableColumnProps * 调整 ts 定义 * 升级 react-hook-form * inputTable 补充数组本身的验证 * Combo 也支持内部数组的验证 * 调整内部验证 * 调整目录 * chore: 优化 locale, theme hoc, 存在 context 直接复用 (#5702) * publish beta * chore: 优化 locale, theme hoc, 存在 context 直接复用 * chore: 日期范围类组件单元测试补充 (#5705) * dateRange * datetimeRange * timeRange * monthRange * quarter and year * 修改 * 修改 * fix: 评分组件 count 支持变量获取 (#5681) * fix: 评分组件 count 支持变量获取 * tokenize 修改为 filter Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: sansiro <sansiro@sansiro.me> * feat: tree 增加虚拟列表 (#5696) * feat: Tree 使用 VirtualList 渲染, 提升大数据时的性能 * fix: 适配编辑和新建 * chore: 增加 Tree 测试用例 * chore: 更新 Tree 测试用例 * feat: Tree虚拟列表,调整props名称 * chore: 清理 Tree 相关的无用代码 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 (#5799) * 其他 transfer 支持虚拟列表属性 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 * add * fix: tree 多级时,通过递归parent来判断展开收起,递归partial判断父元素的Partial状态 (#5807) * fix: 调整 tree 组件中,判断父子关系的方法 (#5814) * Revert "chore: merge master into feat-virtual-list branch (#5716)" (#5825) This reverts commit c9895812989c31d3471d50c2adaf7110478ad0a0. * chore: 更新 tree 虚拟滚动相关快照 和一些优化 Co-authored-by: RUNZE LU <36724300+lurunze1226@users.noreply.github.com> Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: meerkat <kit_hack@outlook.com>
2022-11-28 18:07:45 +08:00
*/
import {fireEvent, render, waitFor, screen} from '@testing-library/react';
2022-06-02 10:00:09 +08:00
import '../../../src';
import {render as amisRender} from '../../../src';
merge: feat-virtual-list into master (#5829) * feat: select transfer 除树形模式外,增加虚拟列表能力 (#5612) * feat: select transfer 除树形模式外,增加虚拟列表能力 * 修改分组模式问题 * 更新快照 * transfer 虚拟列表单测补充 * select 虚拟列表单测补充 * 更新 select 快照 * chore: merge master into feat-virtual-list branch (#5716) * chore: combo组件items扩充编辑器的拖拽点位 (#5693) * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * fix: 数字输入框-属性配置-placeholder置灰+边框与form-input统一 amis-saas-4938 (#5666) Co-authored-by: limengyang03 <limengyang03@baidu.com> * feat:Remark组件支持自定义图标 (#5694) * feat:Remark组件支持自定义图标 * 去掉多余内容 Co-authored-by: xujiahao01 <xujiahao01@baidu.com> * fix: 修复 amis本地跑不起来 问题 * fix: https://github.com/baidu/amis/issues/4681 * feat: 使用cross-env 设置NODE_ENV 变量 * perf: 删除重复声明项 * revert: 恢复删除的SchemaRedirect Co-authored-by: 吴多益 <wuduoyi@baidu.com> * feat: ui 组件 form 支持 autoSubmit (#5695) * feat: ui 组件 form 支持 autoSubmit * 下发 onSubmit 否则只能用 handleSubmit 这个会绕过 form 的检测,无法通知到上层 * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 (#5698) * publish beta * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 * fix: filter 过滤器 isTrue/isFalse 问题修复 (#5676) * fix: filter 过滤器 isTrue 问题修复 * 修改 * 修改 * 修改 * chore: InputArray新增默认值示例, 调整Combo组件scaffold逻辑 (#5701) * chore: InputNumber严格判断大数模式,避免错误抛出string类型值 (#5703) * fix: 修复查看代码报 require is not defined 错误 (#5704) * publish beta * fix: 修复查看代码报 require is not defined 错误 * feat: 补充 ConfirmBox ui 控件, 并将 PickerContainer 改成 ConfirmBox 实现 (#5708) * publish beta * feat: 添加 ui ConfirmBox * feat: 补充 confirmBox ui 控件, 并将 pickerContainer 改成 confirmBox 实现 * PickerContainer title 逻辑不变动 * 暴露 InputTableColumnProps * 调整 ts 定义 * 升级 react-hook-form * inputTable 补充数组本身的验证 * Combo 也支持内部数组的验证 * 调整内部验证 * 调整目录 * chore: 优化 locale, theme hoc, 存在 context 直接复用 (#5702) * publish beta * chore: 优化 locale, theme hoc, 存在 context 直接复用 * chore: 日期范围类组件单元测试补充 (#5705) * dateRange * datetimeRange * timeRange * monthRange * quarter and year * 修改 * 修改 * fix: 评分组件 count 支持变量获取 (#5681) * fix: 评分组件 count 支持变量获取 * tokenize 修改为 filter Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: sansiro <sansiro@sansiro.me> * feat: tree 增加虚拟列表 (#5696) * feat: Tree 使用 VirtualList 渲染, 提升大数据时的性能 * fix: 适配编辑和新建 * chore: 增加 Tree 测试用例 * chore: 更新 Tree 测试用例 * feat: Tree虚拟列表,调整props名称 * chore: 清理 Tree 相关的无用代码 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 (#5799) * 其他 transfer 支持虚拟列表属性 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 * add * fix: tree 多级时,通过递归parent来判断展开收起,递归partial判断父元素的Partial状态 (#5807) * fix: 调整 tree 组件中,判断父子关系的方法 (#5814) * Revert "chore: merge master into feat-virtual-list branch (#5716)" (#5825) This reverts commit c9895812989c31d3471d50c2adaf7110478ad0a0. * chore: 更新 tree 虚拟滚动相关快照 和一些优化 Co-authored-by: RUNZE LU <36724300+lurunze1226@users.noreply.github.com> Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: meerkat <kit_hack@outlook.com>
2022-11-28 18:07:45 +08:00
import {makeEnv, formatStyleObject, wait} from '../../helper';
const setup = async (items: any = {}, formOptions: any = {}) => {
const utils = render(
amisRender(
{
type: 'form',
api: '/api/mock2/form/saveForm',
body: items,
...formOptions
},
{},
makeEnv()
)
);
return utils;
};
test('Renderer:transfer', () => {
const {container} = render(
amisRender(
{
type: 'page',
body: {
type: 'form',
api: '/api/mock2/form/saveForm',
body: [
{
label: '默认',
type: 'transfer',
name: 'transfer',
options: [
{
label: '诸葛亮',
value: 'zhugeliang'
},
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
},
{
label: '李白',
value: 'libai'
},
{
label: '韩信',
value: 'hanxin'
},
{
label: '云中君',
value: 'yunzhongjun'
}
]
}
]
}
},
{},
makeEnv({})
)
);
expect(container).toMatchSnapshot();
});
test('Renderer:transfer tree', () => {
const {container} = render(
amisRender(
{
type: 'page',
body: {
type: 'form',
api: '/api/mock2/form/saveForm',
body: [
{
label: '树型展示',
type: 'transfer',
name: 'transfer4',
selectMode: 'tree',
options: [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang'
}
]
},
{
label: '战士',
children: [
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
}
]
},
{
label: '打野',
children: [
{
label: '李白',
value: 'libai'
},
{
label: '韩信',
value: 'hanxin'
},
{
label: '云中君',
value: 'yunzhongjun'
}
]
}
]
}
]
}
},
{},
makeEnv({})
)
);
expect(container).toMatchSnapshot();
});
test('Renderer:transfer group options', async () => {
const {container, findByText} = render(
amisRender(
{
type: 'page',
body: {
type: 'form',
api: '/api/mock2/form/saveForm',
body: [
{
label: '分组',
type: 'transfer',
name: 'transfer',
options: [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang'
}
]
},
{
label: '战士',
children: [
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
}
]
},
{
label: '打野',
children: [
{
label: '李白',
value: 'libai'
},
{
label: '韩信',
value: 'hanxin'
},
{
label: '云中君',
value: 'yunzhongjun'
}
]
}
]
}
]
}
},
{},
makeEnv({})
)
);
await findByText('诸葛亮');
// TODO: 莫名其妙 github 上运行就会报错
// expect(container).toMatchSnapshot();
});
test('Renderer:transfer table', async () => {
const {container, findByText} = render(
amisRender(
{
type: 'page',
body: {
type: 'form',
api: '/api/mock2/form/saveForm',
body: [
{
label: '表格形式',
type: 'transfer',
name: 'transfer',
selectMode: 'table',
columns: [
{
name: 'label',
label: '英雄'
},
{
name: 'position',
label: '位置'
}
],
options: [
{
label: '诸葛亮',
value: 'zhugeliang',
position: '中单'
},
{
label: '曹操',
value: 'caocao',
position: '上单'
},
{
label: '钟无艳',
value: 'zhongwuyan',
position: '上单'
},
{
label: '李白',
value: 'libai',
position: '打野'
},
{
label: '韩信',
value: 'hanxin',
position: '打野'
},
{
label: '云中君',
value: 'yunzhongjun',
position: '打野'
}
]
}
]
}
},
{},
makeEnv({})
)
);
await findByText('诸葛亮');
expect(container).toMatchSnapshot();
});
test('Renderer:transfer chained', async () => {
const {container, findByText} = render(
amisRender(
{
type: 'page',
body: {
type: 'form',
api: '/api/mock2/form/saveForm',
body: [
{
label: '级联选择',
type: 'transfer',
name: 'transfer5',
selectMode: 'chained',
searchable: true,
sortable: true,
options: [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang'
}
]
},
{
label: '战士',
children: [
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
}
]
},
{
label: '打野',
children: [
{
label: '李白',
value: 'libai'
},
{
label: '韩信',
value: 'hanxin'
},
{
label: '云中君',
value: 'yunzhongjun'
}
]
}
]
}
]
}
},
{},
makeEnv({})
)
);
await findByText('法师');
expect(container).toMatchSnapshot();
});
test('Renderer:transfer left tree', async () => {
const {container, findByText} = render(
amisRender(
{
type: 'page',
body: {
type: 'form',
api: '/api/mock2/form/saveForm',
body: [
{
label: '关联选择模式',
type: 'transfer',
name: 'b',
sortable: true,
searchable: true,
deferApi: '/api/mock2/form/deferOptions?label=${label}',
selectMode: 'associated',
leftMode: 'tree',
leftOptions: [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang'
}
]
},
{
label: '战士',
children: [
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
}
]
},
{
label: '打野',
children: [
{
label: '李白',
value: 'libai'
},
{
label: '韩信',
value: 'hanxin'
},
{
label: '云中君',
value: 'yunzhongjun'
}
]
}
],
options: [
{
ref: 'zhugeliang',
children: [
{
label: 'A',
value: 'a'
}
]
},
{
ref: 'caocao',
children: [
{
label: 'B',
value: 'b'
},
{
label: 'C',
value: 'c'
}
]
},
{
ref: 'zhongwuyan',
children: [
{
label: 'D',
value: 'd'
},
{
label: 'E',
value: 'e'
}
]
},
{
ref: 'libai',
defer: true
},
{
ref: 'hanxin',
defer: true
},
{
ref: 'yunzhongjun',
defer: true
}
]
}
]
}
},
{},
makeEnv({})
)
);
await findByText('诸葛亮');
expect(container).toMatchSnapshot();
});
merge: feat-virtual-list into master (#5829) * feat: select transfer 除树形模式外,增加虚拟列表能力 (#5612) * feat: select transfer 除树形模式外,增加虚拟列表能力 * 修改分组模式问题 * 更新快照 * transfer 虚拟列表单测补充 * select 虚拟列表单测补充 * 更新 select 快照 * chore: merge master into feat-virtual-list branch (#5716) * chore: combo组件items扩充编辑器的拖拽点位 (#5693) * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * fix: 数字输入框-属性配置-placeholder置灰+边框与form-input统一 amis-saas-4938 (#5666) Co-authored-by: limengyang03 <limengyang03@baidu.com> * feat:Remark组件支持自定义图标 (#5694) * feat:Remark组件支持自定义图标 * 去掉多余内容 Co-authored-by: xujiahao01 <xujiahao01@baidu.com> * fix: 修复 amis本地跑不起来 问题 * fix: https://github.com/baidu/amis/issues/4681 * feat: 使用cross-env 设置NODE_ENV 变量 * perf: 删除重复声明项 * revert: 恢复删除的SchemaRedirect Co-authored-by: 吴多益 <wuduoyi@baidu.com> * feat: ui 组件 form 支持 autoSubmit (#5695) * feat: ui 组件 form 支持 autoSubmit * 下发 onSubmit 否则只能用 handleSubmit 这个会绕过 form 的检测,无法通知到上层 * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 (#5698) * publish beta * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 * fix: filter 过滤器 isTrue/isFalse 问题修复 (#5676) * fix: filter 过滤器 isTrue 问题修复 * 修改 * 修改 * 修改 * chore: InputArray新增默认值示例, 调整Combo组件scaffold逻辑 (#5701) * chore: InputNumber严格判断大数模式,避免错误抛出string类型值 (#5703) * fix: 修复查看代码报 require is not defined 错误 (#5704) * publish beta * fix: 修复查看代码报 require is not defined 错误 * feat: 补充 ConfirmBox ui 控件, 并将 PickerContainer 改成 ConfirmBox 实现 (#5708) * publish beta * feat: 添加 ui ConfirmBox * feat: 补充 confirmBox ui 控件, 并将 pickerContainer 改成 confirmBox 实现 * PickerContainer title 逻辑不变动 * 暴露 InputTableColumnProps * 调整 ts 定义 * 升级 react-hook-form * inputTable 补充数组本身的验证 * Combo 也支持内部数组的验证 * 调整内部验证 * 调整目录 * chore: 优化 locale, theme hoc, 存在 context 直接复用 (#5702) * publish beta * chore: 优化 locale, theme hoc, 存在 context 直接复用 * chore: 日期范围类组件单元测试补充 (#5705) * dateRange * datetimeRange * timeRange * monthRange * quarter and year * 修改 * 修改 * fix: 评分组件 count 支持变量获取 (#5681) * fix: 评分组件 count 支持变量获取 * tokenize 修改为 filter Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: sansiro <sansiro@sansiro.me> * feat: tree 增加虚拟列表 (#5696) * feat: Tree 使用 VirtualList 渲染, 提升大数据时的性能 * fix: 适配编辑和新建 * chore: 增加 Tree 测试用例 * chore: 更新 Tree 测试用例 * feat: Tree虚拟列表,调整props名称 * chore: 清理 Tree 相关的无用代码 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 (#5799) * 其他 transfer 支持虚拟列表属性 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 * add * fix: tree 多级时,通过递归parent来判断展开收起,递归partial判断父元素的Partial状态 (#5807) * fix: 调整 tree 组件中,判断父子关系的方法 (#5814) * Revert "chore: merge master into feat-virtual-list branch (#5716)" (#5825) This reverts commit c9895812989c31d3471d50c2adaf7110478ad0a0. * chore: 更新 tree 虚拟滚动相关快照 和一些优化 Co-authored-by: RUNZE LU <36724300+lurunze1226@users.noreply.github.com> Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: meerkat <kit_hack@outlook.com>
2022-11-28 18:07:45 +08:00
// 跟随模式
test('Renderer:transfer follow left mode', async () => {
const {container, findByText} = render(
amisRender(
{
type: 'form',
api: '/api/mock2/form/saveForm',
body: [
{
label: '树型展示',
type: 'transfer',
name: 'transfer4',
selectMode: 'tree',
searchable: true,
resultListModeFollowSelect: true,
options: [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang'
}
]
},
{
label: '战士',
children: [
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
}
]
},
{
label: '打野',
children: [
{
label: '李白',
value: 'libai'
},
{
label: '韩信',
value: 'hanxin'
},
{
label: '云中君',
value: 'yunzhongjun'
}
]
}
]
}
]
},
{},
makeEnv({})
)
);
const zhugeliang = await findByText('诸葛亮');
fireEvent.click(zhugeliang);
await wait(200);
expect(container).toMatchSnapshot();
});
// 结果前端搜索
test('Renderer:transfer follow left mode', async () => {
const {container, findByText} = render(
amisRender(
{
type: 'form',
api: '/api/mock2/form/saveForm',
body: [
{
label: '树型展示',
type: 'transfer',
name: 'transfer4',
selectMode: 'tree',
searchable: true,
resultListModeFollowSelect: true,
resultSearchable: true,
options: [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang'
}
]
},
{
label: '战士',
children: [
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
}
]
},
{
label: '打野',
children: [
{
label: '李白',
value: 'libai'
},
{
label: '韩信',
value: 'hanxin'
},
{
label: '云中君',
value: 'yunzhongjun'
}
]
}
]
}
]
},
{},
makeEnv({})
)
);
const zhugeliang = await findByText('诸葛亮');
fireEvent.click(zhugeliang);
await wait(200);
const caocao = await findByText('曹操');
fireEvent.click(caocao);
await wait(200);
const input = container.querySelectorAll('input[type=text]')[1];
expect(input).not.toBeNull();
fireEvent.change(input, {
target: {value: 'caocao'}
});
// 300 毫秒才行
await wait(300);
const dom = container.querySelector(
'.cxd-ResultTreeList .cxd-Tree-item .cxd-Tree-itemText'
);
expect(dom).not.toBeNull();
expect(dom?.getAttribute('title')).toEqual('战士');
expect(container).toMatchSnapshot();
});
test('should call the custom filterOption if it is provided', async () => {
const filterOption = jest.fn().mockImplementation(options => options);
const options = [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang',
weapon: '翡翠仙扇'
}
]
}
];
render(
amisRender(
{
label: '树型展示',
type: 'transfer',
name: 'transfer4',
selectMode: 'tree',
searchable: true,
filterOption: filterOption,
options
},
{},
makeEnv({})
)
);
const input = screen.getByPlaceholderText('请输入关键字');
fireEvent.change(input, {
target: {value: '翡翠仙扇'}
});
await wait(300);
expect(filterOption).toBeCalledTimes(1);
expect(filterOption).toBeCalledWith(options, '翡翠仙扇', {
keys: ['label', 'value']
});
});
test('should call the string style custom filterOption if it is provided', async () => {
const options = [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang',
weapon: '翡翠仙扇'
}
]
}
];
render(
amisRender(
{
label: '树型展示',
type: 'transfer',
name: 'transfer4',
selectMode: 'tree',
searchable: true,
filterOption: 'return [];',
options
},
{},
makeEnv({})
)
);
const input = screen.getByPlaceholderText('请输入关键字');
expect(screen.getByText('诸葛亮')).toBeInTheDocument();
fireEvent.change(input, {
target: {value: '翡翠仙扇'}
});
await wait(300);
expect(screen.queryByText('诸葛亮')).not.toBeInTheDocument();
});
test('should call the notify function with error message if the filterOption is not a valid function', async () => {
const options = [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang',
weapon: '翡翠仙扇'
}
]
}
];
const mockNotify = jest.fn().mockImplementation(options => options);
render(
amisRender(
{
label: '树型展示',
type: 'transfer',
name: 'transfer4',
selectMode: 'tree',
searchable: true,
filterOption: 10086,
options
},
{},
{notify: mockNotify}
)
);
const input = screen.getByPlaceholderText('请输入关键字');
expect(screen.getByText('诸葛亮')).toBeInTheDocument();
fireEvent.change(input, {
target: {value: '翡翠仙扇'}
});
await wait(300);
expect(mockNotify).toBeCalledTimes(1);
expect(mockNotify).toBeCalledWith('error', '自定义检索函数不符合要求');
mockNotify.mockClear();
});
merge: feat-virtual-list into master (#5829) * feat: select transfer 除树形模式外,增加虚拟列表能力 (#5612) * feat: select transfer 除树形模式外,增加虚拟列表能力 * 修改分组模式问题 * 更新快照 * transfer 虚拟列表单测补充 * select 虚拟列表单测补充 * 更新 select 快照 * chore: merge master into feat-virtual-list branch (#5716) * chore: combo组件items扩充编辑器的拖拽点位 (#5693) * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * feat: combo组件items支持编辑器的拖拽 * fix: 数字输入框-属性配置-placeholder置灰+边框与form-input统一 amis-saas-4938 (#5666) Co-authored-by: limengyang03 <limengyang03@baidu.com> * feat:Remark组件支持自定义图标 (#5694) * feat:Remark组件支持自定义图标 * 去掉多余内容 Co-authored-by: xujiahao01 <xujiahao01@baidu.com> * fix: 修复 amis本地跑不起来 问题 * fix: https://github.com/baidu/amis/issues/4681 * feat: 使用cross-env 设置NODE_ENV 变量 * perf: 删除重复声明项 * revert: 恢复删除的SchemaRedirect Co-authored-by: 吴多益 <wuduoyi@baidu.com> * feat: ui 组件 form 支持 autoSubmit (#5695) * feat: ui 组件 form 支持 autoSubmit * 下发 onSubmit 否则只能用 handleSubmit 这个会绕过 form 的检测,无法通知到上层 * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 (#5698) * publish beta * chore: sdk embed 方法添加 callback 在 callback 中可确保 scoped 方法是可用的 * fix: filter 过滤器 isTrue/isFalse 问题修复 (#5676) * fix: filter 过滤器 isTrue 问题修复 * 修改 * 修改 * 修改 * chore: InputArray新增默认值示例, 调整Combo组件scaffold逻辑 (#5701) * chore: InputNumber严格判断大数模式,避免错误抛出string类型值 (#5703) * fix: 修复查看代码报 require is not defined 错误 (#5704) * publish beta * fix: 修复查看代码报 require is not defined 错误 * feat: 补充 ConfirmBox ui 控件, 并将 PickerContainer 改成 ConfirmBox 实现 (#5708) * publish beta * feat: 添加 ui ConfirmBox * feat: 补充 confirmBox ui 控件, 并将 pickerContainer 改成 confirmBox 实现 * PickerContainer title 逻辑不变动 * 暴露 InputTableColumnProps * 调整 ts 定义 * 升级 react-hook-form * inputTable 补充数组本身的验证 * Combo 也支持内部数组的验证 * 调整内部验证 * 调整目录 * chore: 优化 locale, theme hoc, 存在 context 直接复用 (#5702) * publish beta * chore: 优化 locale, theme hoc, 存在 context 直接复用 * chore: 日期范围类组件单元测试补充 (#5705) * dateRange * datetimeRange * timeRange * monthRange * quarter and year * 修改 * 修改 * fix: 评分组件 count 支持变量获取 (#5681) * fix: 评分组件 count 支持变量获取 * tokenize 修改为 filter Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: sansiro <sansiro@sansiro.me> * feat: tree 增加虚拟列表 (#5696) * feat: Tree 使用 VirtualList 渲染, 提升大数据时的性能 * fix: 适配编辑和新建 * chore: 增加 Tree 测试用例 * chore: 更新 Tree 测试用例 * feat: Tree虚拟列表,调整props名称 * chore: 清理 Tree 相关的无用代码 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 (#5799) * 其他 transfer 支持虚拟列表属性 * feat: select transfer 树形模式增加虚拟滚动支持, treeSelect 虚拟滚动参数 * add * fix: tree 多级时,通过递归parent来判断展开收起,递归partial判断父元素的Partial状态 (#5807) * fix: 调整 tree 组件中,判断父子关系的方法 (#5814) * Revert "chore: merge master into feat-virtual-list branch (#5716)" (#5825) This reverts commit c9895812989c31d3471d50c2adaf7110478ad0a0. * chore: 更新 tree 虚拟滚动相关快照 和一些优化 Co-authored-by: RUNZE LU <36724300+lurunze1226@users.noreply.github.com> Co-authored-by: zhou999 <zhousq809@163.com> Co-authored-by: PE_Sicca <46698676+swjtulmy@users.noreply.github.com> Co-authored-by: limengyang03 <limengyang03@baidu.com> Co-authored-by: 徐佳豪 <1440054388@qq.com> Co-authored-by: xujiahao01 <xujiahao01@baidu.com> Co-authored-by: h7ml <h7ml@qq.com> Co-authored-by: 吴多益 <wuduoyi@baidu.com> Co-authored-by: liaoxuezhi <2betop.cn@gmail.com> Co-authored-by: meerkat <kit_hack@outlook.com>
2022-11-28 18:07:45 +08:00
test('Renderer:transfer group mode with virtual', async () => {
const options = [...Array(20)].map((_, i) => ({
label: `group-${i + 1}`,
children: [...Array(10)].map((_, j) => ({
label: `option-${i * 10 + j + 1}`,
value: `value-${i * 10 + j + 1}`
}))
}));
const {container, getByText, queryByText} = await setup([
{
label: '分组',
type: 'transfer',
name: 'transfer',
options: options,
virtualThreshold: 100,
itemHeight: 40
}
]);
const optionsOrLabel = container.querySelectorAll(
'.cxd-GroupedSelection.cxd-Transfer-selection > div > div > div > div.cxd-GroupedSelection-group'
);
expect(optionsOrLabel.length > 0).toBeTruthy();
const firstStyle = formatStyleObject(optionsOrLabel[0].getAttribute('style'));
expect(firstStyle.top).toBe(0);
expect(firstStyle.height).toBe(40);
await waitFor(() => expect(optionsOrLabel.length > 1).toBeTruthy());
expect(formatStyleObject(optionsOrLabel[1].getAttribute('style')).top).toBe(
40
);
expect(getByText('option-1')).toBeInTheDocument();
expect(await queryByText('option-100')).toBeNull();
const scrollContainer = container.querySelector(
'.cxd-GroupedSelection.cxd-Transfer-selection > div > div'
)!;
// 滚动到底部
fireEvent.scroll(scrollContainer, {
target: {
scrollTop: 9999
}
});
await wait(300);
// 最后一项
const lastOne = container.querySelector(
'.cxd-GroupedSelection.cxd-Transfer-selection > div > div > div > div.cxd-GroupedSelection-group:last-of-type'
);
expect(formatStyleObject(lastOne!.getAttribute('style')).top).toBe(8760);
expect(await queryByText('option-1')).toBeNull();
expect(container).toMatchSnapshot();
});
test('Renderer:transfer table mode with virtual', async () => {
const options = [...Array(200)].map((_, i) => ({
label: `label-${i + 1}`,
value: i + 1
}));
const value = [...Array(10)].map((_, i) => i * 2 + 1).join(',');
const {container, getByText} = await setup([
{
label: '分组',
type: 'transfer',
name: 'transfer',
options: options,
value: value,
virtualThreshold: 10,
selectMode: 'table',
columns: [
{
name: 'label',
label: '名称'
},
{
name: 'value',
label: '值'
}
]
}
]);
const virtualTable = container.querySelector(
'.cxd-Transfer-select .cxd-Table-content.is-virtual .cxd-Table-content-virtual table.cxd-Table-table'
)!;
expect(virtualTable).toBeInTheDocument();
const resultList = container.querySelector(
'.cxd-Transfer-result .cxd-Selections.cxd-Transfer-value .cxd-Selections-items'
)!;
expect(resultList.firstChild).toHaveClass('cxd-Selections-item');
expect(container).toMatchSnapshot('result not virtual');
// 点击后value 变为 11 项,右侧列表变成虚拟列表
fireEvent.click(getByText('label-2'));
await wait(300);
const firstVirtualItem = resultList.querySelector(
'div > div:first-of-type > div > .cxd-Selections-item'
);
expect(firstVirtualItem).toBeInTheDocument();
expect(formatStyleObject(firstVirtualItem!.getAttribute('style'))!.top).toBe(
0
);
expect(container).toMatchSnapshot('result virtual');
});
test('Renderer:transfer chained mode with virtual', async () => {
const options = [...Array(10)].map((_, i) => ({
label: `group-${i + 1}`,
children: [...Array(200)].map((_, j) => ({
label: `group-${i + 1}-option-${j + 1}`,
value: `${i + 1}-${j + 1}`
}))
}));
const {container, getByText, queryByText} = await setup([
{
label: '分组',
type: 'transfer',
name: 'transfer',
options: options,
virtualThreshold: 100,
selectMode: 'chained'
}
]);
const cols = container.querySelectorAll('.cxd-ChainedSelection-col');
expect(cols.length).toBe(2);
expect(cols[0].children.length).toBe(10);
expect(cols[1].firstChild).toHaveClass('cxd-ChainedSelection-placeholder');
fireEvent.click(getByText('group-2'));
await wait(300);
expect(cols[1].firstChild).not.toHaveClass(
'cxd-ChainedSelection-placeholder'
);
expect(getByText('group-2-option-1')).toBeInTheDocument();
expect(await queryByText('group-2-option-200')).toBeNull();
expect(container).toMatchSnapshot();
});
test('Renderer:transfer associated mode with virtual', async () => {
const options = [...Array(200)].map((_, i) => ({
label: `label-${i + 1}`,
value: i + 1
}));
const {container, getByText, queryByText} = await setup([
{
label: '关联选择模式',
type: 'transfer',
name: 'b',
sortable: true,
searchable: true,
selectMode: 'associated',
leftMode: 'tree',
leftOptions: [
{
label: '法师',
children: [
{
label: '诸葛亮',
value: 'zhugeliang'
}
]
},
{
label: '战士',
children: [
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
}
]
}
],
options: [
{
ref: 'zhugeliang',
children: [
{
label: 'A',
value: 'a'
}
]
},
{
ref: 'caocao',
children: [
{
label: 'B',
value: 'b'
},
{
label: 'C',
value: 'c'
}
]
},
{
ref: 'zhongwuyan',
children: options
}
]
}
]);
const rightCol = container.querySelector('.cxd-AssociatedSelection-right');
expect(rightCol).toBeInTheDocument();
fireEvent.click(getByText('诸葛亮'));
await wait(200);
expect(
rightCol!.querySelector(
'.cxd-GroupedSelection .cxd-GroupedSelection-item .cxd-GroupedSelection-itemLabel span'
)!.innerHTML
).toBe('A');
fireEvent.click(getByText('钟无艳'));
await wait(200);
expect(
rightCol!.querySelectorAll('.cxd-GroupedSelection-item').length < 200
).toBeTruthy();
expect(getByText('label-1')).toBeInTheDocument();
expect(await queryByText('label-100')).toBeNull();
expect(container).toMatchSnapshot();
});
test('Renderer:transfer with showInvalidMatch & unmatched do not add', async () => {
const schema = {
label: '默认',
type: 'transfer',
name: 'transfer',
value: 'v,w,x,y,z',
selectMode: 'tree',
options: [
{
label: '诸葛亮',
value: 'zhugeliang'
},
{
label: '曹操',
value: 'caocao'
},
{
label: '钟无艳',
value: 'zhongwuyan'
}
]
};
const {container, getByText, queryByText, rerender} = await setup({
...schema,
deferApi: 'xxx'
});
function leftItems() {
return container.querySelectorAll('.cxd-Transfer-select .cxd-Tree-item');
}
function rightItems() {
return container.querySelectorAll(
'.cxd-Transfer-result .cxd-Selections-item'
);
}
expect(leftItems()!.length).toBe(3);
expect(rightItems()!.length).toBe(5);
expect(
rightItems()[0]!.querySelector('.cxd-Selections-label')!
).not.toHaveClass('is-invalid');
fireEvent.click(rightItems()[0]!.querySelector('.cxd-Selections-delBtn')!);
await wait(500);
expect(leftItems()!.length).toBe(3);
expect(rightItems()!.length).toBe(4);
rerender(amisRender({...schema, showInvalidMatch: true}));
await wait(500);
expect(rightItems()[0]!.querySelector('.cxd-Selections-label')!).toHaveClass(
'is-invalid'
);
fireEvent.click(rightItems()[0]!.querySelector('.cxd-Selections-delBtn')!);
await wait(500);
expect(container).toMatchSnapshot();
expect(leftItems()!.length).toBe(3);
expect(rightItems()!.length).toBe(4);
});
test('Renderer:transfer with searchApi', async () => {
const onSubmit = jest.fn();
const fetcher = jest.fn().mockImplementationOnce(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
options: [
{
"label": "法师",
"children": [
{
"label": "诸葛亮",
"value": "zhugeliang"
}
]
},
{
"label": "战士",
"children": [
{
"label": "钟无艳",
"value": "zhongwuyan"
}
]
}
]
}
}
})
);
const {getByText, container} = render(
amisRender(
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"label": "树型展示",
"type": "transfer",
"name": "transfer",
"selectMode": "tree",
"searchable": true,
"searchApi": "/api/transfer/search?name=${term}",
"options": [
{
"label": "法师",
"children": [
{
"label": "诸葛亮",
"value": "zhugeliang"
}
]
},
{
"label": "战士",
"value": "zhanshi",
"children": [
{
"label": "曹操",
"value": "caocao"
},
{
"label": "钟无艳",
"value": "zhongwuyan"
}
]
},
{
"label": "打野",
"children": [
{
"label": "李白",
"value": "libai"
},
{
"label": "韩信",
"value": "hanxin"
},
{
"label": "云中君",
"value": "yunzhongjun"
}
]
}
]
}
]
},
{onSubmit},
makeEnv({
fetcher
})
)
);
const zhangshi = container.querySelector('span[title=战士]');
expect(zhangshi).not.toBeNull();
zhangshi && fireEvent.click(zhangshi);
fireEvent.click(getByText('提交'));
await wait(100);
expect(onSubmit).toBeCalledTimes(1);
expect(onSubmit.mock.calls[0][0]).toEqual({
transfer: "caocao,zhongwuyan"
});
const input = container.querySelector('input[placeholder=请输入关键字]');
expect(input).not.toBeNull();
input && fireEvent.change(input, {
target: {value: 'a'}
});
await wait(300);
const caocao = container.querySelector('span[title=李白]');
expect(caocao).toBeNull();
});
test('Renderer:transfer tree onlyChildren true', async () => {
const onSubmit = jest.fn();
const schema = {
"type": "form",
"api": "/api/mock2/form/saveForm",
"debug": true,
"body": [
{
"label": "默认",
"type": "transfer",
"name": "transfer",
"value": "libai",
"selectMode": "tree",
"searchable": true,
"onlyChildren": true,
"options": [
{
"label": "法师",
"children": [
{
"label": "诸葛亮",
"value": "zhugeliang"
}
]
},
{
"label": "战士",
"value": "战士",
"children": [
{
"label": "曹操",
"disabled": true,
"value": "caocao"
},
{
"label": "钟无艳",
"value": "zhongwuyan"
}
]
},
{
"label": "打野",
"children": [
{
"label": "李白",
"value": "libai"
},
{
"label": "韩信",
"value": "hanxin"
},
{
"label": "云中君",
"value": "yunzhongjun"
}
]
}
]
}
]
};
const {getByText, container} = render(
amisRender(schema, {onSubmit}, makeEnv({}))
);
const checkbox = container.querySelector('.cxd-Checkbox');
expect(checkbox).not.toBeNull();
checkbox && fireEvent.click(checkbox);
fireEvent.click(getByText('提交'));
await wait(100);
expect(onSubmit).toBeCalledTimes(1);
expect(onSubmit.mock.calls[0][0]).toEqual({
transfer: "zhugeliang,zhongwuyan,libai,hanxin,yunzhongjun"
});
});
test('Renderer:transfer search highlight', async () => {
const onSubmit = jest.fn();
const {container} = render(
amisRender(
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"label": "默认",
"type": "transfer",
"name": "transfer",
"selectMode": "tree",
"searchable": true,
"options": [
{
"label": "法师",
"children": [
{
"label": "诸葛亮",
"value": "zhugeliang"
}
]
},
{
"label": "战士",
"children": [
{
"label": "曹操",
"disabled": true,
"value": "caocao"
},
{
"label": "钟无艳",
"value": "zhongwuyan"
}
]
},
{
"label": "打野",
"children": [
{
"label": "李白",
"value": "libai"
},
{
"label": "韩信",
"value": "hanxin"
},
{
"label": "云中君",
"value": "yunzhongjun"
}
]
}
]
}
]
},
{onSubmit},
makeEnv({})
)
)
const input = container.querySelectorAll('input[type=text]')[0];
expect(input).not.toBeNull();
fireEvent.change(input, {
target: {value: '战士'}
});
await wait(500);
const isMatchDom = container.querySelector('.is-matched');
expect(isMatchDom).not.toBeNull();
});
test('Renderer:transfer tree search', async () => {
const onSubmit = jest.fn();
const {container, findByText, getByText} = render(
amisRender(
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"label": "默认",
"type": "transfer",
"name": "transfer",
"selectMode": "tree",
"searchable": true,
"options": [
{
"label": "法师",
"children": [
{
"label": "诸葛亮",
"value": "zhugeliang"
}
]
},
{
"label": "战士",
"children": [
{
"label": "曹操",
"value": "caocao"
},
{
"label": "钟无艳",
"value": "zhongwuyan"
}
]
},
{
"label": "打野",
"children": [
{
"label": "李白",
"value": "libai"
},
{
"label": "韩信",
"value": "hanxin"
},
{
"label": "云中君",
"value": "yunzhongjun"
}
]
}
]
}
]
},
{onSubmit},
makeEnv({})
)
)
const input = container.querySelectorAll('input[type=text]')[0];
expect(input).not.toBeNull();
fireEvent.change(input, {
target: {
value: '战士'
}
});
await(300);
const caocao = getByText('曹操');
expect(caocao).not.toBeNull();
fireEvent.click(caocao);
fireEvent.change(input, {
target: {
value: ''
}
});
await(300);
fireEvent.change(input, {
target: {
value: '打野'
}
});
await(300);
const libai = getByText('李白');
expect(libai).not.toBeNull();
fireEvent.click(libai);
await wait(500);
fireEvent.click(getByText('提交'));
await wait(300);
expect(onSubmit).toBeCalledTimes(1);
expect(onSubmit.mock.calls[0][0]).toEqual({
transfer: "caocao,libai"
});
});
test('Renderer:Transfer with pagination', async () => {
const mockData = [
{
"label": "Laura Lewis",
"value": "1"
},
{
"label": "David Gonzalez",
"value": "2"
},
{
"label": "Christopher Rodriguez",
"value": "3"
},
{
"label": "Sarah Young",
"value": "4"
},
{
"label": "James Jones",
"value": "5"
},
{
"label": "Larry Robinson",
"value": "6"
},
{
"label": "Christopher Perez",
"value": "7"
},
{
"label": "Sharon Davis",
"value": "8"
},
{
"label": "Kenneth Anderson",
"value": "9"
},
{
"label": "Deborah Lewis",
"value": "10"
},
{
"label": "Jennifer Lewis",
"value": "11"
},
{
"label": "Laura Miller",
"value": "12"
},
{
"label": "Larry Harris",
"value": "13"
},
{
"label": "Patricia Robinson",
"value": "14"
},
{
"label": "Mark Davis",
"value": "15"
},
{
"label": "Jessica Harris",
"value": "16"
},
{
"label": "Anna Brown",
"value": "17"
},
{
"label": "Lisa Young",
"value": "18"
},
{
"label": "Donna Williams",
"value": "19"
},
{
"label": "Shirley Davis",
"value": "20"
}
];
const fetcher = jest.fn().mockImplementation((api) => {
const perPage = 10; /** 锁死10个方便测试 */
const page = Number(api.query.page || 1);
return Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
count: mockData.length,
page: page,
items: mockData.concat().splice((page - 1) * perPage, perPage)
}
}
});
});
const {container} = render(
amisRender(
{
"type": "form",
"debug": true,
"body": [
{
"label": "默认",
"type": "transfer",
"name": "transfer",
"joinValues": false,
"extractValue": false,
"source": "/api/mock2/options/transfer?page=${page}&perPage=${perPage}",
"pagination": {
"enable": true,
"layout": ["pager", "perpage", "total"],
"popOverContainerSelector": ".cxd-Panel--form"
},
"value": [
{"label": "Laura Lewis", "value": "1", id: 1},
{"label": "Christopher Rodriguez", "value": "3", id: 3},
{"label": "Laura Miller", "value": "12", id: 12},
{"label": "Patricia Robinson", "value": "14", id: 14}
]
}
]
}, {}, makeEnv({fetcher})));
await wait(500);
expect(container.querySelector('.cxd-Transfer-footer-pagination')).toBeInTheDocument();
const checkboxes = container.querySelectorAll('input[type=checkbox]')!;
expect(checkboxes.length).toEqual(11); /** 包括顶部全选 */
expect((checkboxes[1] as HTMLInputElement)?.checked).toEqual(true);
expect((checkboxes[2] as HTMLInputElement)?.checked).toEqual(false);
expect((checkboxes[3] as HTMLInputElement)?.checked).toEqual(true);
expect((checkboxes[4] as HTMLInputElement)?.checked).toEqual(false);
const nextBtn = container.querySelector('.cxd-Pagination-next')!;
fireEvent.click(nextBtn);
await wait(500);
const checkboxes2 = container.querySelectorAll('input[type=checkbox]')!;
expect(checkboxes2.length).toEqual(11);
expect((checkboxes2[1] as HTMLInputElement)?.checked).toEqual(false);
expect((checkboxes2[2] as HTMLInputElement)?.checked).toEqual(true);
expect((checkboxes2[3] as HTMLInputElement)?.checked).toEqual(false);
expect((checkboxes2[4] as HTMLInputElement)?.checked).toEqual(true);
})
test.only('Renderer:Transfer with pagination and data source from data scope', async () => {
const mockData = [
{
"label": "Laura Lewis",
"value": "1"
},
{
"label": "David Gonzalez",
"value": "2"
},
{
"label": "Christopher Rodriguez",
"value": "3"
},
{
"label": "Sarah Young",
"value": "4"
},
{
"label": "James Jones",
"value": "5"
},
{
"label": "Larry Robinson",
"value": "6"
},
{
"label": "Christopher Perez",
"value": "7"
},
{
"label": "Sharon Davis",
"value": "8"
},
{
"label": "Kenneth Anderson",
"value": "9"
},
{
"label": "Deborah Lewis",
"value": "10"
},
{
"label": "Jennifer Lewis",
"value": "11"
},
{
"label": "Laura Miller",
"value": "12"
},
{
"label": "Larry Harris",
"value": "13"
},
{
"label": "Patricia Robinson",
"value": "14"
},
{
"label": "Mark Davis",
"value": "15"
},
{
"label": "Jessica Harris",
"value": "16"
},
{
"label": "Anna Brown",
"value": "17"
},
{
"label": "Lisa Young",
"value": "18"
},
{
"label": "Donna Williams",
"value": "19"
},
{
"label": "Shirley Davis",
"value": "20"
}
];
const fetcher = jest.fn().mockImplementation((api) => {
return Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
count: mockData.length,
items: mockData
}
}
});
});
const {container} = render(
amisRender(
{
"type": "form",
"debug": true,
"body": [
{
"type": "service",
"api": {
"url": "/api/mock2/options/loadDataOnce",
"method": "get",
"responseData": {
"transferOptions": "${items}"
}
},
body: [
{
"label": "默认",
"type": "transfer",
"name": "transfer",
"joinValues": false,
"extractValue": false,
"source": "${transferOptions}",
"pagination": {
"enable": true,
"layout": ["pager", "perpage", "total"],
"popOverContainerSelector": ".cxd-Panel--form"
},
"value": [
{"label": "Laura Lewis", "value": "1", id: 1},
{"label": "Christopher Rodriguez", "value": "3", id: 3},
{"label": "Laura Miller", "value": "12", id: 12},
{"label": "Patricia Robinson", "value": "14", id: 14}
]
}
]
}
]
}, {}, makeEnv({fetcher})));
await wait(500);
expect(container.querySelector('.cxd-Transfer-footer-pagination')).toBeInTheDocument();
const checkboxes = container.querySelectorAll('input[type=checkbox]')!;
expect(checkboxes.length).toEqual(11); /** 包括顶部全选 */
expect((checkboxes[1] as HTMLInputElement)?.checked).toEqual(true);
expect((checkboxes[2] as HTMLInputElement)?.checked).toEqual(false);
expect((checkboxes[3] as HTMLInputElement)?.checked).toEqual(true);
expect((checkboxes[4] as HTMLInputElement)?.checked).toEqual(false);
const nextBtn = container.querySelector('.cxd-Pagination-next')!;
fireEvent.click(nextBtn);
await wait(500);
const checkboxes2 = container.querySelectorAll('input[type=checkbox]')!;
expect(checkboxes2.length).toEqual(11);
expect((checkboxes2[1] as HTMLInputElement)?.checked).toEqual(false);
expect((checkboxes2[2] as HTMLInputElement)?.checked).toEqual(true);
expect((checkboxes2[3] as HTMLInputElement)?.checked).toEqual(false);
expect((checkboxes2[4] as HTMLInputElement)?.checked).toEqual(true);
})