5 changed files with 221 additions and 11 deletions
@ -0,0 +1,154 @@ |
|||||
|
import { flushPromises, mount } from '@vue/test-utils'; |
||||
|
import { defineComponent, h, nextTick } from 'vue'; |
||||
|
|
||||
|
import { afterAll, bench, describe } from 'vitest'; |
||||
|
|
||||
|
import { setupVbenForm } from '../src/config'; |
||||
|
import { FormApi } from '../src/form-api'; |
||||
|
import { encodeFormValues } from '../src/form-codec'; |
||||
|
import { useVbenForm } from '../src/use-vben-form'; |
||||
|
|
||||
|
interface ContactValues { |
||||
|
enabled: boolean; |
||||
|
metadata: { |
||||
|
permissions: string[]; |
||||
|
team: string; |
||||
|
}; |
||||
|
name: string; |
||||
|
phone: string; |
||||
|
tags: string[]; |
||||
|
} |
||||
|
|
||||
|
interface PerformanceFormValues extends Record<string, unknown> { |
||||
|
contacts: ContactValues[]; |
||||
|
settings: { |
||||
|
alerts: boolean; |
||||
|
locale: string; |
||||
|
sections: string[]; |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
const ROW_COUNT = 100; |
||||
|
|
||||
|
const TestInput = defineComponent({ |
||||
|
inheritAttrs: false, |
||||
|
emits: ['update:modelValue'], |
||||
|
setup(_props, { attrs, emit }) { |
||||
|
function handleInput(event: Event) { |
||||
|
const target = event.target; |
||||
|
if (target instanceof HTMLInputElement) { |
||||
|
emit('update:modelValue', target.value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return () => |
||||
|
h('input', { |
||||
|
...attrs, |
||||
|
onInput: handleInput, |
||||
|
value: attrs.modelValue ?? '', |
||||
|
}); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
function createFormValues(): PerformanceFormValues { |
||||
|
return { |
||||
|
contacts: Array.from({ length: ROW_COUNT }, (_, index) => ({ |
||||
|
enabled: index % 2 === 0, |
||||
|
metadata: { |
||||
|
permissions: ['read', 'write', 'review'], |
||||
|
team: `team-${index % 10}`, |
||||
|
}, |
||||
|
name: ` Contact ${index} `, |
||||
|
phone: `10086-${index}`, |
||||
|
tags: ['primary', 'on-call', `group-${index % 5}`], |
||||
|
})), |
||||
|
settings: { |
||||
|
alerts: true, |
||||
|
locale: 'zh-CN', |
||||
|
sections: ['profile', 'security', 'notifications'], |
||||
|
}, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
const codec = { |
||||
|
decode: (values: Readonly<PerformanceFormValues>) => ({ ...values }), |
||||
|
encode: (values: Readonly<PerformanceFormValues>) => ({ |
||||
|
...values, |
||||
|
contacts: values.contacts.map((contact) => ({ |
||||
|
...contact, |
||||
|
name: contact.name.trim(), |
||||
|
})), |
||||
|
}), |
||||
|
}; |
||||
|
|
||||
|
const formValues = createFormValues(); |
||||
|
const codecFormApi = new FormApi<PerformanceFormValues>({ codec }); |
||||
|
codecFormApi.mount({ meta: {}, values: formValues } as never, new Map()); |
||||
|
|
||||
|
setupVbenForm({ config: {}, rules: {} }); |
||||
|
const [ArrayForm, arrayFormApi] = useVbenForm({ |
||||
|
schema: [ |
||||
|
{ |
||||
|
children: [ |
||||
|
{ |
||||
|
component: TestInput, |
||||
|
fieldName: 'name', |
||||
|
label: 'Name', |
||||
|
}, |
||||
|
], |
||||
|
defaultValue: Array.from({ length: ROW_COUNT }, (_, index) => ({ |
||||
|
name: `Contact ${index}`, |
||||
|
})), |
||||
|
fieldName: 'contacts', |
||||
|
type: 'array', |
||||
|
}, |
||||
|
], |
||||
|
}); |
||||
|
const arrayWrapper = mount(ArrayForm); |
||||
|
await flushPromises(); |
||||
|
let arrayEditIteration = 0; |
||||
|
|
||||
|
afterAll(() => { |
||||
|
arrayWrapper.unmount(); |
||||
|
}); |
||||
|
|
||||
|
describe('form codec performance', () => { |
||||
|
bench( |
||||
|
'encode 100 nested rows without isolation', |
||||
|
() => { |
||||
|
encodeFormValues(codec, formValues); |
||||
|
}, |
||||
|
{ time: 1000, warmupTime: 200 }, |
||||
|
); |
||||
|
|
||||
|
bench( |
||||
|
'encode 100 nested rows with isolated input', |
||||
|
() => { |
||||
|
codecFormApi.formatValues(formValues); |
||||
|
}, |
||||
|
{ time: 1000, warmupTime: 200 }, |
||||
|
); |
||||
|
|
||||
|
bench( |
||||
|
'create submit snapshot for 100 nested rows', |
||||
|
async () => { |
||||
|
await codecFormApi.getValueSnapshot(); |
||||
|
}, |
||||
|
{ time: 1000, warmupTime: 200 }, |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
describe('form array performance', () => { |
||||
|
bench( |
||||
|
'edit one field in a 100-row array', |
||||
|
async () => { |
||||
|
arrayEditIteration += 1; |
||||
|
await arrayFormApi.setFieldValue( |
||||
|
'contacts[50].name', |
||||
|
`Contact ${arrayEditIteration}`, |
||||
|
); |
||||
|
await nextTick(); |
||||
|
}, |
||||
|
{ time: 1000, warmupTime: 200 }, |
||||
|
); |
||||
|
}); |
||||
Loading…
Reference in new issue