Skip to content

Commit c8b438f

Browse files
authored
fix(auto-complete): 修复eslint和单元测试问题 (#394)
1 parent 70a2130 commit c8b438f

File tree

16 files changed

+337
-194
lines changed

16 files changed

+337
-194
lines changed

packages/devui-vue/devui/auto-complete/__tests__/auto-complete.spec.ts

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { mount } from '@vue/test-utils';
22
import { nextTick, ref } from 'vue';
33
import DAutoComplete from '../src/auto-complete';
4-
54
// delay api
65
const wait = (delay = 300) =>
76
new Promise(resolve => setTimeout(() => resolve(true), delay));
@@ -13,7 +12,7 @@ describe('auto-complete', () => {
1312
<d-auto-complete
1413
:source="source"
1514
v-model="value"
16-
:dAutoCompleteWidth="450"
15+
:width="450"
1716
/>
1817
`,
1918
setup() {
@@ -71,7 +70,7 @@ describe('auto-complete', () => {
7170
:source="source"
7271
v-model="value"
7372
:disabled="isDisabled"
74-
/>
73+
/>
7574
<button @click="toggle">{{ isDisabled ? 'Enable AutoComplete' : 'Disable AutoComplete' }}</button>
7675
</div>
7776
`,
@@ -128,8 +127,8 @@ describe('auto-complete', () => {
128127
disabledKey="disabled"
129128
isSearching
130129
:formatter="formatter"
131-
>
132-
<template #searchingTemplate="slotProps" >
130+
>
131+
<template #searching="slotProps" >
133132
<div id="devui-is-searching-template">
134133
{{slotProps}}
135134
</div>
@@ -234,13 +233,13 @@ describe('auto-complete', () => {
234233
<d-auto-complete
235234
:source="source"
236235
v-model="value"
237-
>
238-
<template #itemTemplate="slotProps" >
236+
>
237+
<template #item="slotProps" >
239238
<div>
240239
第{{slotProps.index}}项: {{slotProps.item}}
241240
</div>
242241
</template>
243-
<template #noResultItemTemplate="slotProps" >
242+
<template #nothing="slotProps" >
244243
<div id="noResultItemTemplate">
245244
{{slotProps}}
246245
</div>
@@ -345,13 +344,16 @@ describe('auto-complete', () => {
345344
expect(selectValueCB).toHaveBeenCalledTimes(1);
346345
});
347346
it('allowEmptyValueSearch ', async () => {
347+
const div = document.createElement('div');
348+
div.id="app";
349+
document.body.appendChild(div);
348350
const wrapper = mount({
349351
components: {'d-auto-complete': DAutoComplete },
350352
template: `
351353
<d-auto-complete
352354
:source="source"
353355
v-model="value"
354-
:allowEmptyValueSearch="allowEmptyValueSearch"
356+
:allow-empty-value-search="allowEmptyValueSearch"
355357
/>
356358
`,
357359
setup() {
@@ -377,41 +379,38 @@ describe('auto-complete', () => {
377379
expect(input.element.value).toBe('');
378380
await input.trigger('focus');
379381
await nextTick();
382+
await input.setValue('');
383+
await wait(300);
384+
await nextTick();
380385
expect(wrapper.find('ul').element.childElementCount).toBe(5);
381386
});
382-
383-
it('appendToBody & appendToBodyDirections', async () => {
387+
it('appendToBody & position', async () => {
384388
const wrapper = mount({
385389
components: {'d-auto-complete': DAutoComplete },
386390
template: `
387391
<d-auto-complete
388392
:source="source"
389393
v-model="value"
390-
:appendToBodyDirections="appendToBodyDirections"
391-
:allowEmptyValueSearch="allowEmptyValueSearch"
394+
:append-to-body="appendToBody"
395+
:position="position"
392396
/>
393397
`,
394398
setup() {
395399
const value = ref('');
396-
const allowEmptyValueSearch = ref(true);
400+
const appendToBody = ref(true);
397401
const source = [
398402
'CC#',
399403
'C',
400404
'C++',
401405
'CPython',
402406
'CoffeeScript',
403407
];
404-
const appendToBodyDirections = ref({
405-
originX: 'left',
406-
originY: 'bottom',
407-
overlayX: 'left',
408-
overlayY: 'top',
409-
});
408+
const position = ref(['bottom']);
410409
return {
411410
value,
412411
source,
413-
allowEmptyValueSearch,
414-
appendToBodyDirections
412+
appendToBody,
413+
position
415414
};
416415
}
417416
});
@@ -424,10 +423,20 @@ describe('auto-complete', () => {
424423
await nextTick();
425424
await wait(300);
426425
await nextTick();
427-
expect(wrapper.find('ul').element.childElementCount).toBe(5);
428-
expect(wrapper.find('.selected').element.innerHTML).toBe('CC#');
426+
expect(wrapper.find('.devui-select-open').exists()).toBe(true);
427+
const ul = document.querySelector('.devui-list-unstyled');
428+
let lis = 0;
429+
if(ul&&ul.getElementsByTagName('li')){
430+
lis=ul.getElementsByTagName('li').length;
431+
}
432+
expect(lis).toBe(5);
433+
const li_ed = document.querySelector('.selected');
434+
let li_text = '';
435+
if(li_ed&&li_ed.getElementsByTagName('li')){
436+
li_text=li_ed.innerHTML;
437+
}
438+
expect(li_text).toBe('CC#');
429439
});
430-
431440
it('latestSource',async () => {
432441
const wrapper = mount({
433442
components: {'d-auto-complete': DAutoComplete },
@@ -530,6 +539,7 @@ describe('auto-complete', () => {
530539
expect(wrapper.find('.devui-auto-complete').exists()).toBe(true);
531540
const input = wrapper.find('input');
532541
expect(input.element.value).toBe('');
542+
await input.trigger('click');
533543
await input.setValue('c');
534544
await nextTick();
535545
expect(wrapper.find('.devui-dropdown-menu').exists()).toBe(true);
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import type { App } from 'vue';
22
import AutoComplete from './src/auto-complete';
33

4-
AutoComplete.install = function(app: App): void {
5-
app.component(AutoComplete.name, AutoComplete);
6-
};
4+
export * from './src/auto-complete-types';
75

86
export { AutoComplete };
97

@@ -12,6 +10,6 @@ export default {
1210
category: '数据录入',
1311
status: '100%',
1412
install(app: App): void {
15-
app.use(AutoComplete as any);
13+
app.component(AutoComplete.name, AutoComplete);
1614
}
1715
};
Lines changed: 89 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import type { PropType, ExtractPropTypes, InjectionKey, SetupContext, Ref } from 'vue';
2-
const defaultFormatter = (item: any) => (item ? item.label || item.toString() : '');
3-
const defaultValueParse = (item: any) => item;
2+
export interface SourceItemObj {
3+
label: string;
4+
disabled: boolean;
5+
[propName: string]: unknown;
6+
}
7+
const defaultFormatter = (item: string | SourceItemObj) => {
8+
if(typeof item === 'string'){
9+
return item;
10+
}
11+
return item!==null ? item.label || item.toString() : '';
12+
};
13+
const defaultValueParse = (item: string | SourceItemObj) => item;
414
export type Placement =
515
| 'top'
616
| 'right'
@@ -14,122 +24,132 @@ export type Placement =
1424
| 'bottom-end'
1525
| 'left-start'
1626
| 'left-end';
27+
28+
29+
export type SourceType = Array<string>| Array<SourceItemObj>;
30+
1731
export const autoCompleteProps = {
1832
modelValue: {
1933
type: String,
20-
default:''
34+
default: ''
2135
},
22-
source:{
23-
type :Array,
24-
default:null
36+
source: {
37+
type : Array as PropType<SourceType>,
38+
default: null
2539
},
26-
allowEmptyValueSearch:{
27-
type:Boolean,
28-
default:false
40+
allowEmptyValueSearch: {
41+
type: Boolean,
42+
default: false
2943
},
30-
position :{
44+
appendToBody:{
45+
type: Boolean,
46+
default: false
47+
},
48+
position : {
3149
type: Array as PropType<Array<Placement>>,
3250
default: ['bottom-end'],
3351
},
34-
disabled:{
35-
type:Boolean,
36-
default:false
52+
disabled: {
53+
type: Boolean,
54+
default: false
3755
},
38-
delay:{
39-
type:Number,
40-
default:300
56+
delay: {
57+
type: Number,
58+
default: 300
4159
},
42-
disabledKey:{
43-
type:String,
44-
default:null
60+
disabledKey: {
61+
type: String,
62+
default: null
4563
},
4664
formatter: {
47-
type:Function as PropType<(item: any) => string>,
48-
default:defaultFormatter
65+
type: Function as PropType<(item: string | SourceItemObj) => string>,
66+
default: defaultFormatter
4967
},
5068
isSearching: {
51-
type:Boolean,
52-
default:false
69+
type: Boolean,
70+
default: false
5371
},
54-
sceneType:{
55-
type:String,
56-
default:null
72+
sceneType: {
73+
type: String,
74+
default: null
5775
},
58-
searchFn:{
59-
type:Function as PropType<(term: string) => Array<any>>,
60-
default:null
76+
searchFn: {
77+
type: Function as PropType<(term: string) => SourceType>,
78+
default: null
6179
},
62-
tipsText:{
63-
type:String,
80+
tipsText: {
81+
type: String,
6482
default:'最近输入'
6583
},
66-
latestSource:{
67-
type:Array,
68-
default:null
84+
latestSource: {
85+
type: Array,
86+
default: null
6987
},
70-
valueParser:{
71-
type:Function as PropType<(item: any) => any>,
72-
default:defaultValueParse
88+
valueParser: {
89+
type: Function as PropType<(item: string | SourceItemObj) => string>,
90+
default: defaultValueParse
7391
},
7492
enableLazyLoad: {
75-
type:Boolean,
76-
default:false
93+
type: Boolean,
94+
default: false
7795
},
78-
width:{
96+
width: {
7997
type: Number,
80-
default:400
98+
default: 400
8199
},
82-
showAnimation:{
83-
type:Boolean,
84-
default:true
100+
showAnimation: {
101+
type: Boolean,
102+
default: true
85103
},
86-
maxHeight:{
87-
type:Number,
88-
default:300
104+
maxHeight: {
105+
type: Number,
106+
default: 300
89107
},
90-
transInputFocusEmit:{
91-
type:Function as PropType<() => void>,
92-
default:null
108+
transInputFocusEmit: {
109+
type: Function as PropType<() => void>,
110+
default: null
93111
},
94112
selectValue:{
95-
type:Function as PropType<(val: any) => any>,
96-
default:null
113+
type: Function as PropType<(val: string) => string>,
114+
default: null
97115
},
98-
loadMore:{
99-
type:Function as PropType<() => void>,
100-
default:null
116+
loadMore: {
117+
type: Function as PropType<() => void>,
118+
default: null
101119
}
102120
} as const;
103121

104122
export type AutoCompleteProps = ExtractPropTypes<typeof autoCompleteProps>;
105123

106124
export interface AutoCompleteRootType {
107-
ctx: SetupContext<any>;
125+
ctx: SetupContext;
108126
props: AutoCompleteProps;
109127
}
110-
export type SearchFnType = (term: string) => Array<any>;
111-
export type FormatterType = (item: any) => string;
112-
export type DefaultFuncType = (arg?: any) => any;
113-
export type HandleSearch = (term?: string | string,enableLazyLoad?: boolean) => void;
114-
export type RecentlyFocus = (latestSource: Array<any>) => void;
115-
export type InputDebounceCb = (...rest: any) => Promise<void>;
116-
export type TransInputFocusEmit = (any?: any) => void;
117-
export type SelectOptionClick = (any?: any) => void;
128+
export type SearchFnType = (term: string) => SourceType;
129+
export type FormatterType = (item: string | SourceItemObj) => string;
130+
export type DefaultFuncType = () => void;
131+
export type HandleSearch = (term: string,enableLazyLoad?: boolean) => void;
132+
export type RecentlyFocus = (latestSource: SourceType) => void;
133+
export type InputDebounceCb = (value: string) => void;
134+
export type TransInputFocusEmit = () => unknown;
135+
export type SelectOptionClick = (item: string | SourceItemObj) => void;
136+
export type SelectValueType = (value: string) => unknown;
118137
// 弹出选择框参数
119138
export type DropdownProps = {
120139
props: AutoCompleteProps;
121-
searchList: Ref<any[]>;
140+
searchList: Ref<SourceType>;
122141
searchStatus?: Ref<boolean>;
123142
showNoResultItemTemplate: Ref<boolean>;
124143
term?: string;
125144
visible: Ref<boolean>;
126145
selectedIndex: Ref<number>;
127-
selectOptionClick: HandleSearch;
128-
dropDownRef: Ref<HTMLUListElement>;
146+
selectOptionClick: SelectOptionClick;
147+
dropDownRef: Ref;
129148
showLoading: Ref<boolean>;
130-
loadMore: (arg?: any) => void;
131-
latestSource: Ref<any[]>;
149+
loadMore: () => void;
150+
latestSource: Ref<Array<SourceItemObj>>;
132151
modelValue: Ref<string>;
133152
hoverIndex: Ref<number>;
153+
valueParser: () => void;
134154
};
135155
export const DropdownPropsKey: InjectionKey<DropdownProps>=Symbol('DropdownPropsKey');

0 commit comments

Comments
 (0)