generated from sachinraja/ts-lib-starter
-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(yupFieldRule): sync
yup
rule resolvers (#30)
* feat(yupFieldRule): Supports yup validateSync * test: yupFieldRule * chore: add one ToDo * chore(isPromise): Determine if it is a `Promise` object
- Loading branch information
1 parent
64dbc86
commit a0ea9c7
Showing
14 changed files
with
421 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<script lang="ts" setup> | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<router-link to="/"> | ||
Home | ||
</router-link> | ||
<router-link to="/yup"> | ||
Yup | ||
</router-link> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
<script lang="ts" setup> | ||
import { useForm } from 'slimeform' | ||
import { yupFieldRule } from 'slimeform/resolvers' | ||
import * as yup from 'yup' | ||
import RouteNav from '~/components/RouteNav.vue' | ||
const local = ref('en') | ||
/** mock i18n `t` function */ | ||
const mockT = (_: string) => local.value === 'en' ? 'Valid age up to 120 years old' : '有效年龄至 120 岁' | ||
yup.object({ | ||
}) | ||
const { form, status } = useForm({ | ||
form: () => ({ | ||
age: '', | ||
// ToDo: 支持 yup 的异步验证 | ||
asyncTest: '', | ||
}), | ||
rule: { | ||
age: [ | ||
yupFieldRule(yup.string() | ||
.required(), | ||
), | ||
yupFieldRule(yup.number() | ||
.max(120, () => mockT('xxx_i18n_key')) | ||
.integer() | ||
.nullable(), | ||
), | ||
], | ||
}, | ||
defaultMessage: 'none', | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<RouteNav /> | ||
<div | ||
space-y-5 | ||
text-left | ||
max-w-400px | ||
w-full | ||
mx-auto | ||
rounded-xl | ||
border="1" | ||
p="4" | ||
> | ||
<h2 text-2xl mb-2> | ||
Yup Rule Demo | ||
</h2> | ||
<div> | ||
<h3 text-xl mb-1> | ||
Input Age | ||
</h3> | ||
<label> | ||
<input | ||
v-model="form.age" | ||
type="text" | ||
placeholder="edit me" | ||
autocomplete="false" | ||
|
||
p="x-4 y-2" | ||
w="250px" | ||
text="center" | ||
bg="transparent" | ||
border="~ rounded gray-200 dark:gray-700" | ||
outline="none active:none" | ||
> | ||
</label> | ||
<div> | ||
<p>Value: {{ form.age }}</p> | ||
<p>isDirty: {{ status.age.isDirty }}</p> | ||
<p>isError: {{ status.age.isError }}</p> | ||
<p>message: {{ status.age.message }}</p> | ||
</div> | ||
</div> | ||
<div> | ||
<h3 text-xl mb-1> | ||
Async Rule | ||
</h3> | ||
<label> | ||
<input | ||
v-model="form.asyncTest" | ||
type="text" | ||
placeholder="edit me" | ||
autocomplete="false" | ||
|
||
p="x-4 y-2" | ||
w="250px" | ||
text="center" | ||
bg="transparent" | ||
border="~ rounded gray-200 dark:gray-700" | ||
outline="none active:none" | ||
> | ||
</label> | ||
<div> | ||
<p>Value: {{ form.asyncTest }}</p> | ||
<p>isDirty: {{ status.asyncTest.isDirty }}</p> | ||
<p>isError: {{ status.asyncTest.isError }}</p> | ||
<p>message: {{ status.asyncTest.message }}</p> | ||
</div> | ||
</div> | ||
<div> | ||
<h4 text-lg mb-1> | ||
Local | ||
</h4> | ||
<div space-x-4> | ||
<label> | ||
<input v-model="local" type="radio" value="en"> | ||
<span ml-1>en</span> | ||
</label> | ||
<label> | ||
<input v-model="local" type="radio" value="zh-CN"> | ||
<span ml-1>zh-CN</span> | ||
</label> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './yup' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { expect, test } from 'vitest' | ||
import { nextTick, ref } from 'vue' | ||
import * as yup from 'yup' | ||
import { useForm } from '../../src' | ||
import { useSetup } from '../.test' | ||
import { yupFieldRule } from './yup' | ||
|
||
test('yupFieldRule', async () => { | ||
const wr = useSetup(() => { | ||
const local = ref('en') | ||
/** mock i18n `t` function */ | ||
const mockT = () => local.value === 'en' ? 'A' : '文' | ||
|
||
const { form, status, isError } = useForm({ | ||
form: () => ({ | ||
age: '', | ||
}), | ||
rule: { | ||
age: [ | ||
yupFieldRule(yup.string() | ||
.required(), | ||
), | ||
yupFieldRule(yup.number() | ||
.max(120, () => mockT()) | ||
.integer() | ||
.nullable(), | ||
), | ||
], | ||
}, | ||
}) | ||
return { form, status, isError, local } | ||
}) | ||
wr.form.age = 'abc' | ||
|
||
await nextTick() | ||
expect(wr.status.age.isError).true | ||
expect(wr.isError).true | ||
expect(wr.status.age.message).includes('must be a `number`') | ||
|
||
wr.form.age = '18' | ||
|
||
await nextTick() | ||
expect(wr.status.age.isError).false | ||
expect(wr.isError).false | ||
expect(wr.status.age.message).toBe('') | ||
|
||
wr.form.age = '18.55' | ||
await nextTick() | ||
expect(wr.status.age.isError).true | ||
expect(wr.status.age.message).includes('integer') | ||
|
||
wr.form.age = '' | ||
await nextTick() | ||
expect(wr.status.age.isError).true | ||
expect(wr.status.age.message).includes('required') | ||
|
||
wr.form.age = '121' | ||
await nextTick() | ||
expect(wr.status.age.isError).true | ||
expect(wr.status.age.message).toBe('A') | ||
|
||
wr.local = 'zh-CN' | ||
await nextTick() | ||
expect(wr.status.age.message).toBe('文') | ||
|
||
wr.unmount() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import type { BaseSchema, ValidationError } from 'yup' | ||
import type { ValidateOptions } from 'yup/lib/types' | ||
|
||
export interface ResolverOptions { | ||
model?: 'validateSync' | 'validate' | ||
} | ||
|
||
/** yup field rule resolver */ | ||
export const yupFieldRule = <SchemaT extends BaseSchema, TContext = {}>( | ||
fieldSchema: SchemaT, | ||
schemaOptions: ValidateOptions<TContext> = {}, | ||
) => { | ||
return (val: unknown) => { | ||
try { | ||
fieldSchema.validateSync( | ||
val, | ||
Object.assign({ abortEarly: false }, schemaOptions), | ||
) | ||
return true | ||
} | ||
catch (error: any) { | ||
if (!error?.inner) | ||
throw error | ||
return parseYupError(error) | ||
} | ||
} | ||
} | ||
|
||
function parseYupError(error: ValidationError) { | ||
return error.errors[0] | ||
} |
Oops, something went wrong.