Compare commits

...

3 Commits

Author SHA1 Message Date
chenjiahan
eec2ac4c0f release: @vant/cli 4.0.0-rc.2 2021-10-27 16:19:32 +08:00
neverland
8585842712
feat(@vant/cli): support custom vite config (#9738) 2021-10-27 14:46:37 +08:00
neverland
4778b07d40
test(Form): migrate props test cases (#9734) 2021-10-27 10:39:43 +08:00
10 changed files with 640 additions and 539 deletions

View File

@ -7,6 +7,7 @@
- [build.site.publicPath](#buildsitepublicpath)
- [build.srcDir](#buildsrcdir)
- [build.namedExport](#buildnamedexport)
- [build.configureVite](#buildconfigurevite)
- [site.title](#sitetitle)
- [site.logo](#sitelogo)
- [site.description](#sitedescription)
@ -138,6 +139,47 @@ module.exports = {
开启此选项后,会通过 `export * from 'xxx'` 导出组件内部的所有模块、类型定义。
### build.configureVite
- Type: `(config: InlineConfig): InlineConfig`
- Default: `undefined`
vant-cli 使用 vite 来构建组件库和文档站点,通过 `configureVite` 选项可以自定义 vite 配置(从 4.0.0 版本开始支持)。
```js
module.exports = {
build: {
configureVite(config) {
// 添加一个自定义插件
config.plugins.push(vitePluginXXX);
return config;
},
},
};
```
在自定义配置时,可以通过 `process.env.BUILD_TARGET` 对构建目标进行区分:
```js
module.exports = {
build: {
configureVite(config) {
const { BUILD_TARGET } = process.env;
if (BUILD_TARGET === 'package') {
// 修改组件库构建配置
}
if (BUILD_TARGET === 'site') {
// 修改文档站点构建配置
}
return config;
},
},
};
```
### site.title
- Type: `string`

View File

@ -1,6 +1,6 @@
{
"name": "@vant/cli",
"version": "4.0.0-rc.1",
"version": "4.0.0-rc.2",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"bin": {

View File

@ -1,3 +1,4 @@
import { get } from 'lodash';
import { sep, join } from 'path';
import {
lstatSync,
@ -7,6 +8,7 @@ import {
outputFileSync,
} from 'fs-extra';
import { SRC_DIR, getVantConfig } from './constant';
import type { InlineConfig } from 'vite';
export const EXT_REGEXP = /\.\w+$/;
export const SFC_REGEXP = /\.(vue)$/;
@ -134,4 +136,14 @@ export function smartOutputFile(filePath: string, content: string) {
outputFileSync(filePath, content);
}
export function mergeCustomViteConfig(config: InlineConfig) {
const vantConfig = getVantConfig();
const configureVite = get(vantConfig, 'build.configureVite');
if (configureVite) {
return configureVite(config);
}
return config;
}
export { getVantConfig };

View File

@ -1,6 +1,8 @@
import { build } from 'vite';
import { mergeCustomViteConfig } from '../common';
import { getViteConfigForPackage } from '../config/vite.package';
export async function compilePackage(minify: boolean) {
return build(getViteConfigForPackage(minify));
const config = mergeCustomViteConfig(getViteConfigForPackage(minify));
return build(config);
}

View File

@ -4,7 +4,7 @@ import {
getViteConfigForSiteDev,
getViteConfigForSiteProd,
} from '../config/vite.site';
import { replaceExt } from '../common';
import { mergeCustomViteConfig, replaceExt } from '../common';
import { CSS_LANG } from '../common/css';
import { genPackageEntry } from './gen-package-entry';
import { genPackageStyle } from './gen-package-style';
@ -37,9 +37,11 @@ export async function genSiteEntry(): Promise<void> {
export async function compileSite(production = false) {
await genSiteEntry();
if (production) {
await build(getViteConfigForSiteProd());
const config = mergeCustomViteConfig(getViteConfigForSiteProd());
await build(config);
} else {
const server = await createServer(getViteConfigForSiteDev());
const config = mergeCustomViteConfig(getViteConfigForSiteDev());
const server = await createServer(config);
await server.listen();
const { version } = require('vite/package.json');

View File

@ -92,7 +92,7 @@ function getHTMLMeta(vantConfig: any) {
}
export function getViteConfigForSiteDev(): InlineConfig {
setBuildTarget('package');
setBuildTarget('site');
const vantConfig = getVantConfig();
const siteConfig = getSiteConfig(vantConfig);

View File

@ -1,100 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`colon prop 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__title van-field__label"><span>Label:</span></div>
<div class="van-cell__value van-field__value">
<div class="van-field__body"><input type="text" class="van-field__control"></div>
</div>
</div>
<div class="van-cell van-field">
<div class="van-cell__title van-field__label">Custom Label:</div>
<div class="van-cell__value van-field__value">
<div class="van-field__body"><input type="text" class="van-field__control"></div>
</div>
</div>
</form>
`;
exports[`error-message-align prop 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body"><input type="text" class="van-field__control"></div>
<div class="van-field__error-message van-field__error-message--right">Error</div>
</div>
</div>
</form>
`;
exports[`input-align prop 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body"><input type="text" class="van-field__control van-field__control--right"></div>
</div>
</div>
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body">
<div class="van-field__control van-field__control--right van-field__control--custom">
<div></div>
</div>
</div>
</div>
</div>
</form>
`;
exports[`label-align prop 1`] = `
<form class="van-form">
<div class="van-cell van-field van-field--label-right">
<div class="van-cell__title van-field__label van-field__label--right"><span>Label</span></div>
<div class="van-cell__value van-field__value">
<div class="van-field__body"><input type="text" class="van-field__control"></div>
</div>
</div>
<div class="van-cell van-field van-field--label-center">
<div class="van-cell__title van-field__label van-field__label--center"><span>Label</span></div>
<div class="van-cell__value van-field__value">
<div class="van-field__body"><input type="text" class="van-field__control"></div>
</div>
</div>
</form>
`;
exports[`label-width prop 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__title van-field__label" style="width: 5rem;"><span>Label</span></div>
<div class="van-cell__value van-field__value">
<div class="van-field__body"><input type="text" class="van-field__control"></div>
</div>
</div>
<div class="van-cell van-field">
<div class="van-cell__title van-field__label" style="width: 10vw;"><span>Label</span></div>
<div class="van-cell__value van-field__value">
<div class="van-field__body"><input type="text" class="van-field__control"></div>
</div>
</div>
</form>
`;
exports[`validate-first prop 1`] = `
<form class="van-form">
<div class="van-cell van-field van-field--error">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body"><input type="text" name="A" class="van-field__control"></div>
<div class="van-field__error-message">A failed</div>
</div>
</div>
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body"><input type="text" name="B" class="van-field__control"></div>
</div>
</div> <button type="submit" class="van-button van-button--default van-button--normal">
<div class="van-button__content"></div>
</button>
</form>
`;

View File

@ -0,0 +1,171 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render colon when using colon prop 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__title van-field__label">
<label>
Label:
</label>
</div>
<div class="van-cell__value van-field__value">
<div class="van-field__body">
<input type="text"
class="van-field__control"
>
</div>
</div>
</div>
<div class="van-cell van-field">
<div class="van-cell__title van-field__label">
Custom Label:
</div>
<div class="van-cell__value van-field__value">
<div class="van-field__body">
<input type="text"
class="van-field__control"
>
</div>
</div>
</div>
</form>
`;
exports[`should render error-message-align prop correctly 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body">
<input type="text"
class="van-field__control"
>
</div>
<div class="van-field__error-message van-field__error-message--right">
Error
</div>
</div>
</div>
</form>
`;
exports[`should render input-align prop correctly 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body">
<input type="text"
class="van-field__control van-field__control--right"
>
</div>
</div>
</div>
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body">
<div class="van-field__control van-field__control--right van-field__control--custom">
<div>
</div>
</div>
</div>
</div>
</div>
</form>
`;
exports[`should render label-align prop correctly 1`] = `
<form class="van-form">
<div class="van-cell van-field van-field--label-right">
<div class="van-cell__title van-field__label van-field__label--right">
<label>
Label
</label>
</div>
<div class="van-cell__value van-field__value">
<div class="van-field__body">
<input type="text"
class="van-field__control"
>
</div>
</div>
</div>
<div class="van-cell van-field van-field--label-center">
<div class="van-cell__title van-field__label van-field__label--center">
<label>
Label
</label>
</div>
<div class="van-cell__value van-field__value">
<div class="van-field__body">
<input type="text"
class="van-field__control"
>
</div>
</div>
</div>
</form>
`;
exports[`should render label-width prop correctly 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__title van-field__label"
style="width: 5rem;"
>
<label>
Label
</label>
</div>
<div class="van-cell__value van-field__value">
<div class="van-field__body">
<input type="text"
class="van-field__control"
>
</div>
</div>
</div>
<div class="van-cell van-field">
<div class="van-cell__title van-field__label"
style="width: 10vw;"
>
<label>
Label
</label>
</div>
<div class="van-cell__value van-field__value">
<div class="van-field__body">
<input type="text"
class="van-field__control"
>
</div>
</div>
</div>
</form>
`;
exports[`should validate first field when using validate-first prop 1`] = `
<form class="van-form">
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body">
<input type="text"
name="A"
class="van-field__control"
>
</div>
<div class="van-field__error-message">
A failed
</div>
</div>
</div>
<div class="van-cell van-field">
<div class="van-cell__value van-cell__value--alone van-field__value">
<div class="van-field__body">
<input type="text"
name="B"
class="van-field__control"
>
</div>
</div>
</div>
</form>
`;

View File

@ -1,433 +0,0 @@
import { later, mockScrollIntoView } from '../../../test';
import { mountForm, submitForm, getSimpleRules } from './shared';
test('rules prop - execute order', async () => {
const onFailed = jest.fn();
const wrapper = mountForm({
template: `
<van-form @failed="onFailed">
<van-field name="A" :rules="rules" value="123" />
<van-button native-type="submit" />
</van-form>
`,
data() {
return {
rules: [
{ required: true, message: 'A' },
{ validator: (val) => val.length > 6, message: 'B' },
{ validator: (val) => val !== 'foo', message: 'C' },
],
};
},
methods: {
onFailed,
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'B', name: 'A' }],
values: { A: '123' },
});
});
test('rules prop - pattern', async () => {
const onFailed = jest.fn();
const wrapper = mountForm({
template: `
<van-form @failed="onFailed">
<van-field name="A" :rules="rules" value="123" />
<van-button native-type="submit" />
</van-form>
`,
data() {
return {
rules: [{ pattern: /\d{6}/, message: 'foo' }],
};
},
methods: {
onFailed,
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'foo', name: 'A' }],
values: { A: '123' },
});
});
test('rules prop - message function', async () => {
const onFailed = jest.fn();
const wrapper = mountForm({
template: `
<van-form @failed="onFailed">
<van-field name="A" :rules="rules" value="123" />
<van-button native-type="submit" />
</van-form>
`,
data() {
return {
rules: [{ pattern: /\d{6}/, message: (val) => val }],
};
},
methods: {
onFailed,
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: '123', name: 'A' }],
values: { A: '123' },
});
});
test('rules prop - formatter', async () => {
const onFailed = jest.fn();
const wrapper = mountForm({
template: `
<van-form @failed="onFailed">
<van-field name="A" :rules="rules" value=" " />
<van-button native-type="submit" />
</van-form>
`,
data() {
return {
rules: [
{
message: 'foo',
required: true,
formatter: (val, rule) => {
expect(rule.message).toEqual('foo');
return val.trim();
},
},
],
};
},
methods: {
onFailed,
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'foo', name: 'A' }],
values: { A: ' ' },
});
});
test('rules prop - async validator', async () => {
const onFailed = jest.fn();
const wrapper = mountForm({
template: `
<van-form @failed="onFailed">
<van-field name="A" :rules="rules" value="123" />
<van-button native-type="submit" />
</van-form>
`,
data() {
return {
rules: [
{
validator: (value, rule) => {
expect(value).toEqual('123');
expect(typeof rule).toEqual('object');
return new Promise((resolve) => resolve(true));
},
message: 'should pass',
},
{
validator: () => new Promise((resolve) => resolve(false)),
message: 'should fail',
},
],
};
},
methods: {
onFailed,
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'should fail', name: 'A' }],
values: { A: '123' },
});
});
test('validate-first prop', async () => {
const onSubmit = jest.fn();
const onFailed = jest.fn();
const wrapper = mountForm({
template: `
<van-form validate-first @submit="onSubmit" @failed="onFailed">
<van-field name="A" :rules="rulesA" :value="value" />
<van-field name="B" :rules="rulesB" :value="value" />
<van-button native-type="submit" />
</van-form>
`,
data() {
return {
...getSimpleRules(),
value: '',
};
},
methods: {
onSubmit,
onFailed,
},
});
await submitForm(wrapper);
expect(wrapper.html()).toMatchSnapshot();
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'A failed', name: 'A' }],
values: { A: '', B: '' },
});
wrapper.setData({ value: 'foo' });
await submitForm(wrapper);
expect(onSubmit).toHaveBeenCalledWith({ A: 'foo', B: 'foo' });
});
test('colon prop', () => {
const wrapper = mountForm({
template: `
<van-form colon>
<van-field label="Label" />
<van-field>
<template #label>Custom Label</template>
</van-field>
</van-form>
`,
});
expect(wrapper.html()).toMatchSnapshot();
});
test('label-align prop', () => {
const wrapper = mountForm({
template: `
<van-form label-align="right">
<van-field label="Label" />
<van-field label="Label" label-align="center" />
</van-form>
`,
});
expect(wrapper.html()).toMatchSnapshot();
});
test('label-width prop', () => {
const wrapper = mountForm({
template: `
<van-form label-width="5rem">
<van-field label="Label" />
<van-field label="Label" label-width="10vw" />
</van-form>
`,
});
expect(wrapper.html()).toMatchSnapshot();
});
test('input-align prop', () => {
const wrapper = mountForm({
template: `
<van-form input-align="right">
<van-field />
<van-field>
<template #input>
<div />
</template>
</van-field>
</van-form>
`,
});
expect(wrapper.html()).toMatchSnapshot();
});
test('error-message-align prop', () => {
const wrapper = mountForm({
template: `
<van-form error-message-align="right">
<van-field error-message="Error" />
</van-form>
`,
});
expect(wrapper.html()).toMatchSnapshot();
});
test('validate-trigger - onBlur', async () => {
const wrapper = mountForm({
template: `
<van-form ref="form">
<van-field name="A" :rules="rulesA" value="" />
</van-form>
`,
data: getSimpleRules,
});
const input = wrapper.find('input');
input.trigger('input');
await later();
expect(wrapper.contains('.van-field__error-message')).toBeFalsy();
input.trigger('blur');
await later();
expect(wrapper.contains('.van-field__error-message')).toBeTruthy();
});
test('validate-trigger - onChange', async () => {
const wrapper = mountForm({
template: `
<van-form validate-trigger="onChange" ref="form">
<van-field v-model="value" name="A" :rules="rulesA" />
</van-form>
`,
data() {
return {
...getSimpleRules(),
value: '',
};
},
});
const input = wrapper.find('input');
input.trigger('blur');
await later();
expect(wrapper.contains('.van-field__error-message')).toBeFalsy();
wrapper.setData({ value: '1' });
await later();
expect(wrapper.contains('.van-field__error-message')).toBeFalsy();
wrapper.setData({ value: '' });
await later();
expect(wrapper.contains('.van-field__error-message')).toBeTruthy();
});
test('validate-trigger - custom trigger in rules', async () => {
const wrapper = mountForm({
template: `
<van-form validate-trigger="none" ref="form">
<van-field name="A" :rules="rulesA" :value="valueA" />
<van-field name="B" :rules="rulesB" :value="valueB" />
</van-form>
`,
data() {
return {
valueA: '',
valueB: '',
rulesA: [
{
message: 'A',
required: true,
trigger: 'onChange',
},
],
rulesB: [
{
message: 'B',
required: true,
trigger: 'onBlur',
},
],
};
},
});
const inputs = wrapper.findAll('input');
inputs[0].trigger('blur');
wrapper.setData({ valueB: '1' });
await later();
wrapper.setData({ valueB: '' });
await later();
expect(wrapper.contains('.van-field__error-message')).toBeFalsy();
inputs[1].trigger('blur');
wrapper.setData({ valueA: '1' });
await later();
wrapper.setData({ valueA: '' });
await later();
expect(
wrapper.element.querySelectorAll('.van-field__error-message').length
).toEqual(2);
});
test('scroll-to-error prop', async () => {
const fn = mockScrollIntoView();
const wrapper = mountForm({
template: `
<van-form scroll-to-error>
<van-field name="A" :rules="rulesA" value="" />
<van-button native-type="submit" />
</van-form>
`,
data: getSimpleRules,
});
await submitForm(wrapper);
expect(fn).toHaveBeenCalledTimes(1);
});
test('show-error-message prop', async () => {
const wrapper = mountForm({
template: `
<van-form :show-error-message="showErrorMessage">
<van-field name="A" :rules="rulesA" value="" />
<van-button native-type="submit" />
</van-form>
`,
data() {
return {
...getSimpleRules(),
showErrorMessage: false,
};
},
});
await submitForm(wrapper);
expect(wrapper.contains('.van-field__error-message')).toBeFalsy();
wrapper.setData({ showErrorMessage: true });
await submitForm(wrapper);
expect(wrapper.contains('.van-field__error-message')).toBeTruthy();
});
test('show-error prop', async () => {
const wrapper = mountForm({
template: `
<van-form :show-error="showError">
<van-field name="A" :rules="rulesA" value="" />
<van-button native-type="submit" />
</van-form>
`,
data() {
return {
...getSimpleRules(),
showError: false,
};
},
});
await submitForm(wrapper);
expect(wrapper.contains('.van-field--error')).toBeFalsy();
wrapper.setData({ showError: true });
await submitForm(wrapper);
expect(wrapper.contains('.van-field--error')).toBeTruthy();
});

View File

@ -0,0 +1,405 @@
import { mount, later, mockScrollIntoView } from '../../../test';
import { submitForm, getSimpleRules } from './shared';
import { Form } from '..';
import { Field, FieldRule } from '../../field';
test('should ensure execute order of rules prop', async () => {
const onFailed = jest.fn();
const rules: FieldRule[] = [
{ required: true, message: 'A' },
{ validator: (val) => val.length > 6, message: 'B' },
{ validator: (val) => val !== 'foo', message: 'C' },
];
const wrapper = mount({
render() {
return (
<Form onFailed={onFailed}>
<Field name="A" rules={rules} modelValue="123" />
</Form>
);
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'B', name: 'A' }],
values: { A: '123' },
});
});
test('should support pattern in rules prop', async () => {
const onFailed = jest.fn();
const rules: FieldRule[] = [{ pattern: /\d{6}/, message: 'foo' }];
const wrapper = mount({
render() {
return (
<Form onFailed={onFailed}>
<Field name="A" rules={rules} modelValue="123" />
</Form>
);
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'foo', name: 'A' }],
values: { A: '123' },
});
});
test('should support message function in rules prop', async () => {
const onFailed = jest.fn();
const rules: FieldRule[] = [{ pattern: /\d{6}/, message: (val) => val }];
const wrapper = mount({
render() {
return (
<Form onFailed={onFailed}>
<Field name="A" rules={rules} modelValue="123" />
</Form>
);
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: '123', name: 'A' }],
values: { A: '123' },
});
});
test('should support formatter in rules prop', async () => {
const onFailed = jest.fn();
const rules: FieldRule[] = [
{
message: 'foo',
required: true,
formatter: (val, rule) => {
expect(rule.message).toEqual('foo');
return val.trim();
},
},
];
const wrapper = mount({
render() {
return (
<Form onFailed={onFailed}>
<Field name="A" rules={rules} modelValue=" " />
</Form>
);
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'foo', name: 'A' }],
values: { A: ' ' },
});
});
test('should support async validator in rules prop', async () => {
const onFailed = jest.fn();
const rules: FieldRule[] = [
{
validator: (value, rule) => {
expect(value).toEqual('123');
expect(typeof rule).toEqual('object');
return new Promise((resolve) => resolve(true));
},
message: 'should pass',
},
{
validator: () => new Promise((resolve) => resolve(false)),
message: 'should fail',
},
];
const wrapper = mount({
render() {
return (
<Form onFailed={onFailed}>
<Field name="A" rules={rules} modelValue="123" />
</Form>
);
},
});
await submitForm(wrapper);
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'should fail', name: 'A' }],
values: { A: '123' },
});
});
test('should validate first field when using validate-first prop', async () => {
const onSubmit = jest.fn();
const onFailed = jest.fn();
const wrapper = mount({
data() {
return {
...getSimpleRules(),
value: '',
};
},
render() {
return (
<Form validateFirst onSubmit={onSubmit} onFailed={onFailed}>
<Field name="A" rules={this.rulesA} modelValue={this.value} />
<Field name="B" rules={this.rulesB} modelValue={this.value} />
</Form>
);
},
});
await submitForm(wrapper);
expect(wrapper.html()).toMatchSnapshot();
expect(onFailed).toHaveBeenCalledWith({
errors: [{ message: 'A failed', name: 'A' }],
values: { A: '', B: '' },
});
await wrapper.setData({ value: 'foo' });
await submitForm(wrapper);
expect(onSubmit).toHaveBeenCalledWith({ A: 'foo', B: 'foo' });
});
test('should render colon when using colon prop', () => {
const wrapper = mount({
render() {
return (
<Form colon>
<Field label="Label" />
<Field v-slots={{ label: () => 'Custom Label' }} />
</Form>
);
},
});
expect(wrapper.html()).toMatchSnapshot();
});
test('should render label-align prop correctly', () => {
const wrapper = mount({
render() {
return (
<Form labelAlign="right">
<Field label="Label" />
<Field label="Label" labelAlign="center" />
</Form>
);
},
});
expect(wrapper.html()).toMatchSnapshot();
});
test('should render label-width prop correctly', () => {
const wrapper = mount({
render() {
return (
<Form labelWidth="5rem">
<Field label="Label" />
<Field label="Label" labelWidth="10vw" />
</Form>
);
},
});
expect(wrapper.html()).toMatchSnapshot();
});
test('should render input-align prop correctly', () => {
const wrapper = mount({
render() {
return (
<Form inputAlign="right">
<Field />
<Field v-slots={{ input: () => <div /> }} />
</Form>
);
},
});
expect(wrapper.html()).toMatchSnapshot();
});
test('should render error-message-align prop correctly', () => {
const wrapper = mount({
render() {
return (
<Form errorMessageAlign="right">
<Field errorMessage="Error" />
</Form>
);
},
});
expect(wrapper.html()).toMatchSnapshot();
});
test('should trigger validate after blurring when validate-trigger prop is onBlur', async () => {
const wrapper = mount({
data: getSimpleRules,
render() {
return (
<Form ref="form" validateTrigger="onBlur">
<Field name="A" rules={this.rulesA} modelValue="" />
</Form>
);
},
});
const input = wrapper.find('input');
await input.trigger('input');
expect(wrapper.find('.van-field__error-message').exists()).toBeFalsy();
await input.trigger('blur');
expect(wrapper.find('.van-field__error-message').exists()).toBeTruthy();
});
test('should trigger validate after inputting when validate-trigger prop is onChange', async () => {
const wrapper = mount({
data() {
return {
...getSimpleRules(),
value: '',
};
},
render() {
return (
<Form validateTrigger="onChange" ref="form">
<Field v-model={this.value} name="A" rules={this.rulesA} />
</Form>
);
},
});
const input = wrapper.find('input');
await input.trigger('blur');
expect(wrapper.find('.van-field__error-message').exists()).toBeFalsy();
await wrapper.setData({ value: '1' });
expect(wrapper.find('.van-field__error-message').exists()).toBeFalsy();
await wrapper.setData({ value: '' });
expect(wrapper.find('.van-field__error-message').exists).toBeTruthy();
});
test('should allow to custom trigger in rules', async () => {
const rulesA = [
{
message: 'A',
required: true,
trigger: 'onChange' as const,
},
];
const rulesB = [
{
message: 'B',
required: true,
trigger: 'onBlur' as const,
},
];
const wrapper = mount({
data() {
return {
valueA: '',
valueB: '',
};
},
render() {
return (
<Form validate-trigger="none" ref="form">
<Field name="A" rules={rulesA} modelValue={this.valueA} />
<Field name="B" rules={rulesB} modelValue={this.valueB} />
</Form>
);
},
});
const inputs = wrapper.findAll('input');
await inputs[0].trigger('blur');
await wrapper.setData({ valueB: '1' });
await wrapper.setData({ valueB: '' });
expect(wrapper.find('.van-field__error-message').exists()).toBeFalsy();
await inputs[1].trigger('blur');
await wrapper.setData({ valueA: '1' });
await wrapper.setData({ valueA: '' });
await later();
expect(
wrapper.element.querySelectorAll('.van-field__error-message').length
).toEqual(2);
});
test('should trigger scroll when using scroll-to-error prop', async () => {
const fn = mockScrollIntoView();
const wrapper = mount({
data: getSimpleRules,
render() {
return (
<Form scrollToError>
<Field name="A" rules={this.rulesA} modelValue="" />
</Form>
);
},
});
await submitForm(wrapper);
expect(fn).toHaveBeenCalledTimes(1);
});
test('should allow to control the display of error message by show-error-message prop', async () => {
const wrapper = mount({
data() {
return {
...getSimpleRules(),
showErrorMessage: false,
};
},
render() {
return (
<Form showErrorMessage={this.showErrorMessage}>
<Field name="A" rules={this.rulesA} modelValue="" />
</Form>
);
},
});
await submitForm(wrapper);
expect(wrapper.find('.van-field__error-message').exists()).toBeFalsy();
await wrapper.setData({ showErrorMessage: true });
await submitForm(wrapper);
expect(wrapper.find('.van-field__error-message').exists()).toBeTruthy();
});
test('should allow to control the display of error status by show-error prop', async () => {
const wrapper = mount({
data() {
return {
...getSimpleRules(),
showError: false,
};
},
render() {
return (
<Form showError={this.showError}>
<Field name="A" rules={this.rulesA} modelValue="" />
</Form>
);
},
});
await submitForm(wrapper);
expect(wrapper.find('.van-field--error').exists()).toBeFalsy();
await wrapper.setData({ showError: true });
await submitForm(wrapper);
expect(wrapper.find('.van-field--error').exists()).toBeTruthy();
});