Skip to content

Commit cdee169

Browse files
committed
Add some tests.
1 parent 76a90b3 commit cdee169

File tree

14 files changed

+1569
-232
lines changed

14 files changed

+1569
-232
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,14 @@
5656
},
5757
"devDependencies": {
5858
"@antfu/eslint-config": "^2.21.1",
59-
"@types/node": "^20.14.2",
59+
"@types/node": "^20.14.6",
6060
"@types/sortablejs": "^1.15.8",
6161
"@vitejs/plugin-vue": "^5.0.5",
6262
"@vitest/ui": "^1.6.0",
6363
"autoprefixer": "^10.4.19",
6464
"daisyui": "^4.12.2",
6565
"eslint": "^9.5.0",
66+
"happy-dom": "^14.12.0",
6667
"octicons-css": "^19.8.0",
6768
"postcss": "^8.4.38",
6869
"postcss-import": "^16.1.0",

pnpm-lock.yaml

Lines changed: 162 additions & 161 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/common/Alert.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,37 @@ export enum AlertKind {
55
SUCCESS,
66
}
77

8-
export function showAlert(message: string, showTimeSec: number, kind: AlertKind = AlertKind.WARNING, attachEle: HTMLElement = document.body) {
8+
/**
9+
* 消息提示
10+
*
11+
* Message prompt
12+
*
13+
* @param message 提示的消息 / Message to prompt
14+
* @param showTimeSec 显示的时间(秒) / Display time (seconds)
15+
* @param kind 消息类型 / Message type
16+
* @param attachEle 附加到的元素 / Element to attach
17+
*/
18+
export function showAlert(message: string, showTimeSec: number = 4, kind: AlertKind = AlertKind.WARNING, attachEle: HTMLElement = document.body) {
919
let alertDiv = ``
1020
switch (kind) {
1121
case AlertKind.ERROR: {
12-
alertDiv = ` <div role="alert" class="iw-alert-wrap iw-alert-wrap--error">
13-
${message}
14-
</div>`
22+
alertDiv = ` <div role="alert" class="iw-alert-wrap iw-alert-wrap--error">${message}</div>`
1523
break
1624
}
1725
case AlertKind.WARNING: {
18-
alertDiv = ` <div role="alert" class="iw-alert-wrap iw-alert-wrap--warning">
19-
${message}
20-
</div>`
26+
alertDiv = ` <div role="alert" class="iw-alert-wrap iw-alert-wrap--warning">${message}</div>`
2127
break
2228
}
2329
case AlertKind.INFO: {
24-
alertDiv = ` <div role="alert" class="iw-alert-wrap iw-alert-wrap--info">
25-
${message}
26-
</div>`
30+
alertDiv = ` <div role="alert" class="iw-alert-wrap iw-alert-wrap--info">${message}</div>`
2731
break
2832
}
2933
case AlertKind.SUCCESS: {
30-
alertDiv = ` <div role="alert" class="iw-alert-wrap iw-alert-wrap--success">
31-
${message}
32-
</div>`
34+
alertDiv = ` <div role="alert" class="iw-alert-wrap iw-alert-wrap--success">${message}</div>`
3335
break
3436
}
3537
default: {
36-
alertDiv = ` <div role="alert" class="iw-alert-wrap">
37-
${message}
38-
</div>`
38+
alertDiv = ` <div role="alert" class="iw-alert-wrap">${message}</div>`
3939
break
4040
}
4141
}

src/props/functionProps.ts

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ export type SimpleDataSliceProps = ChangeAllOptional<DataSliceProps>
4848
*
4949
* Generate data slice props
5050
*
51-
* @param simple 简单数据分片属性 / Simple data slice props
51+
* @param tableSimple 表格级简单数据分片属性 / Table level simple data slice props
52+
* @param layoutSimple 布局级简单数据分片属性 / Layout level simple data slice props
5253
* @returns 数据分片属性 / Data slice props
5354
*/
54-
export function generateDataSliceProps(simple?: SimpleDataSliceProps): DataSliceProps {
55+
export function generateDataSliceProps(tableSimple?: SimpleDataSliceProps, layoutSimple?: SimpleDataSliceProps): DataSliceProps {
5556
return {
56-
offsetNumber: simple?.offsetNumber ?? 0,
57-
fetchNumber: simple?.fetchNumber ?? 10,
58-
fetchNumbers: simple?.fetchNumbers ?? [5, 10, 20, 30, 50, 100],
57+
offsetNumber: layoutSimple?.offsetNumber ?? tableSimple?.offsetNumber ?? 0,
58+
fetchNumber: layoutSimple?.fetchNumber ?? tableSimple?.fetchNumber ?? 10,
59+
fetchNumbers: layoutSimple?.fetchNumbers ?? tableSimple?.fetchNumbers ?? [5, 10, 20, 30, 50, 100],
5960
}
6061
}
6162

@@ -144,13 +145,14 @@ export type SimpleAggDataProps = ChangeOptionalExcept<AggDataProps, 'enabledColu
144145
*
145146
* Generate aggregate data props
146147
*
147-
* @param simple 简单聚合数据属性 / Simple aggregate data props
148+
* @param tableSimple 表格级简单聚合数据属性 / Table level simple aggregate data props
149+
* @param layoutSimple 布局级简单聚合数据属性 / Layout level simple aggregate data props
148150
* @returns 聚合数据属性 / Aggregate data props
149151
*/
150-
export function generateAggDataProps(simple: SimpleAggDataProps): AggDataProps {
152+
export function generateAggDataProps(tableSimple?: SimpleAggDataProps, layoutSimple?: SimpleAggDataProps): AggDataProps {
151153
return {
152-
enabledColumnNames: simple.enabledColumnNames,
153-
items: simple.items ?? [],
154+
enabledColumnNames: (layoutSimple?.enabledColumnNames ?? tableSimple?.enabledColumnNames)!,
155+
items: layoutSimple?.items ?? tableSimple?.items ?? [],
154156
}
155157
}
156158

@@ -206,13 +208,14 @@ export type SimpleFilterDataProps = ChangeOptionalExcept<FilterDataProps, 'enabl
206208
*
207209
* Generate filter data props
208210
*
209-
* @param simple 简单过滤数据属性 / Simple filter data props
211+
* @param tableSimple 表格级简单过滤数据属性 / Table level simple filter data props
212+
* @param layoutSimple 布局级简单过滤数据属性 / Layout level simple filter data props
210213
* @returns 过滤数据属性 / Filter data props
211214
*/
212-
export function generateFilterDataProps(simple: SimpleFilterDataProps): FilterDataProps {
215+
export function generateFilterDataProps(tableSimple?: SimpleFilterDataProps, layoutSimple?: SimpleFilterDataProps): FilterDataProps {
213216
return {
214-
enabledColumnNames: simple.enabledColumnNames,
215-
groups: simple.groups ?? [],
217+
enabledColumnNames: (layoutSimple?.enabledColumnNames ?? tableSimple?.enabledColumnNames)!,
218+
groups: layoutSimple?.groups ?? tableSimple?.groups ?? [],
216219
}
217220
}
218221

@@ -294,14 +297,15 @@ export type SimpleGroupDataProps = ChangeOptionalExcept<GroupDataProps, 'enabled
294297
*
295298
* Generate group data props
296299
*
297-
* @param simple 简单分组数据属性 / Simple group data props
300+
* @param tableSimple 表格级简单分组数据属性 / Table level simple group data props
301+
* @param layoutSimple 布局级简单分组数据属性 / Layout level simple group data props
298302
* @returns 分组数据属性 / Group data props
299303
*/
300-
export function generateGroupDataProps(simple: SimpleGroupDataProps): GroupDataProps {
304+
export function generateGroupDataProps(tableSimple?: SimpleGroupDataProps, layoutSimple?: SimpleGroupDataProps): GroupDataProps {
301305
return {
302-
enabledColumnNames: simple.enabledColumnNames,
303-
item: simple.item,
304-
slices: simple.slices,
306+
enabledColumnNames: (layoutSimple?.enabledColumnNames ?? tableSimple?.enabledColumnNames)!,
307+
item: layoutSimple?.item ?? tableSimple?.item,
308+
slices: layoutSimple?.slices ?? tableSimple?.slices,
305309
}
306310
}
307311

@@ -359,13 +363,14 @@ export type SimpleSortDataProps = ChangeOptionalExcept<SortDataProps, 'enabledCo
359363
*
360364
* Generate sort data props
361365
*
362-
* @param simple 简单排序数据属性 / Simple sort data props
366+
* @param tableSimple 表格级简单排序数据属性 / Table level simple sort data props
367+
* @param layoutSimple 布局级简单排序数据属性 / Layout level simple sort data props
363368
* @returns 排序数据属性 / Sort data props
364369
*/
365-
export function generateSortDataProps(simple: SimpleSortDataProps): SortDataProps {
370+
export function generateSortDataProps(tableSimple?: SimpleSortDataProps, layoutSimple?: SimpleSortDataProps): SortDataProps {
366371
return {
367-
enabledColumnNames: simple.enabledColumnNames,
368-
items: simple.items ?? [],
372+
enabledColumnNames: (layoutSimple?.enabledColumnNames ?? tableSimple?.enabledColumnNames)!,
373+
items: layoutSimple?.items ?? tableSimple?.items ?? [],
369374
}
370375
}
371376

@@ -441,17 +446,18 @@ export type SimpleGanttLayoutProps = ChangeOptionalExcept<GanttLayoutProps, 'pla
441446
*
442447
* Generate Gantt layout props
443448
*
444-
* @param simple 简单甘特布局属性 / Simple Gantt layout props
449+
* @param tableSimple 表格级简单甘特布局属性 / Table level simple Gantt layout props
450+
* @param layoutSimple 布局级简单甘特布局属性 / Table level simple Gantt layout props
445451
* @returns 甘特布局属性 / Gantt layout props
446452
*/
447-
export function generateGanttLayoutProps(simple: SimpleGanttLayoutProps): GanttLayoutProps {
453+
export function generateGanttLayoutProps(tableSimple?: SimpleGanttLayoutProps, layoutSimple?: SimpleGanttLayoutProps): GanttLayoutProps {
448454
return {
449-
timelineWidth: simple.timelineWidth ?? 300,
450-
showKind: simple.showKind ?? GanttShowKind.DAY,
451-
planStartTimeColumnName: simple.planStartTimeColumnName,
452-
planEndTimeColumnName: simple.planEndTimeColumnName,
453-
actualStartTimeColumnName: simple.actualStartTimeColumnName,
454-
actualEndTimeColumnName: simple.actualEndTimeColumnName,
455+
timelineWidth: layoutSimple?.timelineWidth ?? tableSimple?.timelineWidth ?? 300,
456+
showKind: layoutSimple?.showKind ?? tableSimple?.showKind ?? GanttShowKind.DAY,
457+
planStartTimeColumnName: (layoutSimple?.planStartTimeColumnName ?? tableSimple?.planStartTimeColumnName)!,
458+
planEndTimeColumnName: (layoutSimple?.planEndTimeColumnName ?? tableSimple?.planEndTimeColumnName)!,
459+
actualStartTimeColumnName: layoutSimple?.actualStartTimeColumnName ?? tableSimple?.actualStartTimeColumnName,
460+
actualEndTimeColumnName: layoutSimple?.actualEndTimeColumnName ?? tableSimple?.actualEndTimeColumnName,
455461
}
456462
}
457463

@@ -487,12 +493,13 @@ export type SimpleEditDataProps = ChangeOptionalExcept<EditDataProps, 'enabledCo
487493
*
488494
* Generate edit data props
489495
*
490-
* @param simple 简单编辑数据属性 / Simple edit data props
496+
* @param tableSimple 表格级简单编辑数据属性 / Table level simple edit data props
497+
* @param layoutSimple 布局级简单编辑数据属性 / Layout level simple edit data props
491498
* @returns 编辑数据属性 / Edit data props
492499
*/
493-
export function generateEditDataProps(simple: SimpleEditDataProps): EditDataProps {
500+
export function generateEditDataProps(tableSimple?: SimpleEditDataProps, layoutSimple?: SimpleEditDataProps): EditDataProps {
494501
return {
495-
enabledColumnNames: simple.enabledColumnNames,
496-
markEditable: simple.markEditable ?? false,
502+
enabledColumnNames: (layoutSimple?.enabledColumnNames ?? tableSimple?.enabledColumnNames)!,
503+
markEditable: layoutSimple?.markEditable ?? tableSimple?.markEditable ?? false,
497504
}
498505
}

src/props/kernelProps.ts

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { getRandomString } from '../utils/basic'
6-
import type { ChangeAllOptional, ChangeOptionalExcept, ChangeOptionalExceptWithTypes } from '../utils/tsHelper'
6+
import type { ChangeAllOptional, ChangeOptionalExcept } from '../utils/tsHelper'
77
import { DataKind, LayoutKind, SizeKind, SubDataShowKind, getDefaultIconByDataKind, getDefaultIconByLayoutKind } from './enumProps'
88

99
import type { TableEventProps } from './eventProps'
@@ -164,13 +164,13 @@ function generateCommonFunctionProps(tableSimple: SimpleCommonFunctionProps, lay
164164
showSelectColumn: layoutSimple?.showSelectColumn ?? tableSimple.showSelectColumn ?? false,
165165
subDataShowKind: layoutSimple?.subDataShowKind ?? tableSimple.subDataShowKind ?? SubDataShowKind.FOLD_SUB_DATA,
166166
actionColumn: layoutSimple?.actionColumn ?? tableSimple.actionColumn,
167-
slice: generateDataSliceProps(layoutSimple?.slice ?? tableSimple.slice),
168-
gantt: (layoutSimple?.gantt ?? tableSimple.gantt) && generateGanttLayoutProps((layoutSimple?.gantt ?? tableSimple.gantt)!),
169-
filter: (layoutSimple?.filter ?? tableSimple.filter) && generateFilterDataProps((layoutSimple?.filter ?? tableSimple.filter)!),
170-
group: (layoutSimple?.group ?? tableSimple.group) && generateGroupDataProps((layoutSimple?.group ?? tableSimple.group)!),
171-
sort: (layoutSimple?.sort ?? tableSimple.sort) && generateSortDataProps((layoutSimple?.sort ?? tableSimple.sort)!),
172-
agg: (layoutSimple?.agg ?? tableSimple.agg) && generateAggDataProps((layoutSimple?.agg ?? tableSimple.agg)!),
173-
edit: (layoutSimple?.edit ?? tableSimple.edit) && generateEditDataProps((layoutSimple?.edit ?? tableSimple.edit)!),
167+
slice: generateDataSliceProps(tableSimple.slice, layoutSimple?.slice),
168+
gantt: (layoutSimple?.gantt ?? tableSimple.gantt) && generateGanttLayoutProps(tableSimple.gantt, layoutSimple?.gantt),
169+
filter: (layoutSimple?.filter ?? tableSimple.filter) && generateFilterDataProps(tableSimple.filter, layoutSimple?.filter),
170+
group: (layoutSimple?.group ?? tableSimple.group) && generateGroupDataProps(tableSimple.group, layoutSimple?.group),
171+
sort: (layoutSimple?.sort ?? tableSimple.sort) && generateSortDataProps(tableSimple.sort, layoutSimple?.sort),
172+
agg: (layoutSimple?.agg ?? tableSimple.agg) && generateAggDataProps(tableSimple.agg, layoutSimple?.agg),
173+
edit: (layoutSimple?.edit ?? tableSimple.edit) && generateEditDataProps(tableSimple.edit, layoutSimple?.edit),
174174
}
175175
}
176176

@@ -761,14 +761,38 @@ export interface LayoutProps extends CommonFunctionProps {
761761
*
762762
* Simple layout props
763763
*/
764-
export type SimpleLayoutProps = ChangeOptionalExceptWithTypes<LayoutProps, 'title', {
764+
export interface SimpleLayoutProps extends SimpleCommonFunctionProps {
765+
/**
766+
* ID
767+
*
768+
* ID
769+
*/
770+
id?: string
771+
/**
772+
* 标题
773+
*
774+
* Title
775+
*/
776+
title: string
777+
/**
778+
* 布局类型
779+
*
780+
* Layout kind
781+
*/
782+
layoutKind?: LayoutKind
783+
/**
784+
* 图标(来自内部图标库)
785+
*
786+
* Icon (from internal icon library)
787+
*/
788+
icon?: string
765789
/**
766790
* 列
767791
*
768792
* Columns
769793
*/
770794
columns?: SimpleLayoutColumnProps[]
771-
}>
795+
}
772796
/**
773797
* 生成布局属性
774798
*

src/utils/basic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function groupBy<T>(array: T[], predicate: (value: T, index: number, arra
2121
*
2222
* @param element 当前元素 / Current element
2323
* @param parentClassName 父元素的类名 / Parent element class name
24-
* @returns
24+
* @returns 父元素 / Parent element
2525
*/
2626
export function getParentWithClass(element: HTMLElement | null, parentClassName: string): HTMLElement | null {
2727
while (element) {

src/utils/vueHelper.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ export function deepToRaw<T extends Record<string, any>>(sourceObj: T): T {
1919
const objectIterator = (input: any): any => {
2020
if (Array.isArray(input)) {
2121
return input.map(item => objectIterator(item))
22-
} if (isRef(input) || isReactive(input) || isProxy(input)) {
22+
} if (isRef(input)) {
23+
return objectIterator(toRaw(input.value))
24+
} if (isReactive(input) || isProxy(input)) {
2325
return objectIterator(toRaw(input))
2426
} if (input && typeof input === 'object') {
2527
return Object.keys(input).reduce((acc, key) => {

test/components/Alert.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { describe, expect, it, vi } from 'vitest'
2+
import { AlertKind, showAlert } from '../../src/components/common/Alert'
3+
4+
describe('showAlert', () => {
5+
function checkAlert(className: string, message: string) {
6+
const alert = document.querySelector(`.${className}`)!
7+
expect(alert).not.toBeNull()
8+
expect(alert.textContent).toBe(message)
9+
}
10+
11+
it('should display an error alert', () => {
12+
vi.useFakeTimers()
13+
showAlert('Error message', 4, AlertKind.ERROR)
14+
checkAlert('iw-alert-wrap--error', 'Error message')
15+
vi.advanceTimersByTime(4000)
16+
expect(document.querySelector('.iw-alert-wrap--error')).toBeNull()
17+
vi.useRealTimers()
18+
})
19+
20+
it('should display a warning alert', () => {
21+
vi.useFakeTimers()
22+
showAlert('Warning message', 4, AlertKind.WARNING)
23+
checkAlert('iw-alert-wrap--warning', 'Warning message')
24+
vi.advanceTimersByTime(4000)
25+
expect(document.querySelector('.iw-alert-wrap--warning')).toBeNull()
26+
vi.useRealTimers()
27+
})
28+
29+
it('should display an info alert', () => {
30+
vi.useFakeTimers()
31+
showAlert('Info message', 4, AlertKind.INFO)
32+
checkAlert('iw-alert-wrap--info', 'Info message')
33+
vi.advanceTimersByTime(4000)
34+
expect(document.querySelector('.iw-alert-wrap--info')).toBeNull()
35+
vi.useRealTimers()
36+
})
37+
38+
it('should display a success alert', () => {
39+
vi.useFakeTimers()
40+
showAlert('Success message', 4, AlertKind.SUCCESS)
41+
checkAlert('iw-alert-wrap--success', 'Success message')
42+
vi.advanceTimersByTime(4000)
43+
expect(document.querySelector('.iw-alert-wrap--success')).toBeNull()
44+
vi.useRealTimers()
45+
})
46+
47+
it('should remove the alert after the specified time', () => {
48+
vi.useFakeTimers()
49+
showAlert('Temporary message', 2, AlertKind.INFO)
50+
checkAlert('iw-alert-wrap--info', 'Temporary message')
51+
vi.advanceTimersByTime(2000)
52+
expect(document.querySelector('.iw-alert-wrap--info')).toBeNull()
53+
vi.useRealTimers()
54+
})
55+
56+
it('should attach the alert to a specific element', () => {
57+
vi.useFakeTimers()
58+
const attachEle = document.createElement('div')
59+
document.body.append(attachEle)
60+
showAlert('Attached message', 4, AlertKind.WARNING, attachEle)
61+
const alert = attachEle.querySelector('.iw-alert-wrap--warning')!
62+
expect(alert).not.toBeNull()
63+
expect(alert.textContent).toBe('Attached message')
64+
vi.advanceTimersByTime(4000)
65+
expect(attachEle.querySelector('.iw-alert-wrap--warning')).toBeNull()
66+
attachEle.remove()
67+
vi.useRealTimers()
68+
})
69+
})

0 commit comments

Comments
 (0)