Skip to content

Commit

Permalink
feat(useValidation): add toObject (#723)
Browse files Browse the repository at this point in the history
  • Loading branch information
pikax committed Jan 6, 2021
1 parent 3d73368 commit 28e9fd3
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 66 deletions.
4 changes: 3 additions & 1 deletion docs/.vuepress/components/ValidationExample.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ export default defineComponent({
if (form.$anyInvalid) {
alert("invalid form");
} else {
alert("submit form");
const o = form.toObject();
alert(`submit form "${JSON.stringify(o)}"`);
console.log("submitted", o);
}
};
Expand Down
11 changes: 10 additions & 1 deletion docs/composable/validation/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ interface ValidationValue<T> {

$anyInvalid: boolean; // any validation invalid
$errors: any[]; // array of errors

toObject(): T;
}

// validator
Expand Down Expand Up @@ -159,6 +161,9 @@ validationUsername.containsInvalidWords.$customProp; //custom prop

// custom properties
validationUsername.$placeholder; // custom prop

// retrieve value object
validationUsername.toObject(); // returns string
```

### NestedValidationObject
Expand Down Expand Up @@ -205,6 +210,8 @@ form.settings.$errors;
form.personal.$anyDirty;
form.personal.$anyInvalid;
form.personal.$errors;

form.toObject(); // returns { settings: { email: '' }, personal: { name: { first: '', last: '' } } }
```

```ts
Expand Down Expand Up @@ -308,7 +315,9 @@ export default defineComponent({
if (form.$anyInvalid) {
alert("invalid form");
} else {
alert("submit form");
const o = form.toObject();
alert(`submit form "${JSON.stringify(o)}"`);
console.log("submitted", o);
}
};
Expand Down
4 changes: 4 additions & 0 deletions packages/axios/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,9 @@
"@types/node": "^14.14.20",
"@vue/runtime-core": "^3.0.5",
"typescript": "^4.1.3"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-beta.14",
"axios": "^0.22.0"
}
}
170 changes: 131 additions & 39 deletions packages/vue-composable/__tests__/validation/validation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ describe("validation", () => {
$value,
required(x: string) {
return !!x;
}
},
},
test1: {
$value: $value1,
required(x: string) {
return !!x;
}
}
},
},
});

expect(validation).toMatchObject({
Expand All @@ -30,16 +30,16 @@ describe("validation", () => {
$dirty: false,
$value: $value.value,
required: {
$invalid: true
}
$invalid: true,
},
},
test1: {
$dirty: false,
$value: $value1.value,
required: {
$invalid: true
}
}
$invalid: true,
},
},
});

$value.value = "hello";
Expand All @@ -55,31 +55,31 @@ describe("validation", () => {
$dirty: true,
$value: $value.value,
required: {
$invalid: false
}
$invalid: false,
},
},
test1: {
$dirty: false,
$value: $value1.value,
required: {
$invalid: true
}
}
$invalid: true,
},
},
});
});

it("validator should run if dependent of other ref", async () => {
const password = ref("");
const form = useValidation({
password: {
$value: password
$value: password,
},
password2: {
$value: ref(""),
samePassword(r: string, ctx: any) {
return r === ctx.password.$value;
}
}
},
},
});

expect(form.password2.samePassword.$invalid).toBe(false);
Expand All @@ -95,8 +95,8 @@ describe("validation", () => {
const v = useValidation({
password: {
$value: ref(""),
$args
}
$args,
},
});

expect(v.password.$args).toStrictEqual($args);
Expand All @@ -109,8 +109,8 @@ describe("validation", () => {
$value: ref(""),
required() {
throw error;
}
}
},
},
});

await nextTick();
Expand All @@ -122,15 +122,17 @@ describe("validation", () => {

it("should handle promise validator", async () => {
let promiseResolve: Function = NO_OP;
const promise = new Promise<boolean>(resolve => (promiseResolve = resolve));
const promise = new Promise<boolean>(
(resolve) => (promiseResolve = resolve)
);

const v = useValidation({
password: {
$value: ref(""),
required() {
return promise;
}
}
},
},
});

expect(v.password.required.$pending).toBe(true);
Expand All @@ -143,7 +145,9 @@ describe("validation", () => {

it("should handle promise validator with objectValidator", async () => {
let promiseResolve: Function = NO_OP;
const promise = new Promise<boolean>(resolve => (promiseResolve = resolve));
const promise = new Promise<boolean>(
(resolve) => (promiseResolve = resolve)
);

const v = useValidation({
password: {
Expand All @@ -152,9 +156,9 @@ describe("validation", () => {
$validator() {
return promise;
},
$message: ref("Err")
}
}
$message: ref("Err"),
},
},
});

v.password.$value;
Expand All @@ -178,15 +182,15 @@ describe("validation", () => {
},
match() {
throw Error("error 2");
}
}
},
},
});
v.input.$value = "1";
await nextTick();

expect(v.input.$errors).toStrictEqual([
new Error("error 1"),
new Error("error 2")
new Error("error 2"),
]);
});

Expand All @@ -199,21 +203,109 @@ describe("validation", () => {
$validator(x: string) {
return false;
},
$message
}
$message,
},
},
otherInput: {
$value: "",
required(x: string) {
return false;
}
}
},
},
});

expect(v.input.$errors).toMatchObject([$message]);
expect(v.otherInput.$errors).toMatchObject([]);
});

describe("object", () => {
it("should convert to object", () => {
const v = useValidation({
input: {
$value: "",
required: {
$validator(x: string) {
return false;
},
$message: "test",
},
},
otherInput: {
$value: "",
required(x: string) {
return false;
},
},
});

expect(v.toObject()).toMatchObject({ input: "", otherInput: "" });

v.input.$value = "test";
v.otherInput.$value = "other";

expect(v.toObject()).toMatchObject({
input: "test",
otherInput: "other",
});

expect(v.input.toObject()).toBe("test");
});

it("should convert to object even on nested validations", () => {
const v = useValidation({
address: {
address1: {
$value: "address1",
},
address2: {
part1: {
$value: "part1",
},
part2: {
$value: "part2",
},
},
},
});
expect(v.toObject()).toMatchObject({
address: {
address1: "address1",
address2: {
part1: "part1",
part2: "part2",
},
},
});

v.address.address2.part1.$value = "1";

expect(v.toObject()).toMatchObject({
address: {
address1: "address1",
address2: {
part1: "1",
part2: "part2",
},
},
});

expect(v.address.toObject()).toMatchObject({
address1: "address1",
address2: {
part1: "1",
part2: "part2",
},
});

expect(v.address.address1.toObject()).toBe(v.address.address1.$value);

expect(v.address.address2.toObject()).toMatchObject({
part1: "1",
part2: "part2",
});
});
});

describe("render", () => {
it("should show error", async () => {
const required = (x: any) => !!x;
Expand All @@ -223,9 +315,9 @@ describe("validation", () => {
required,
otherRequired: {
$validator: required,
$message: ref("password is required")
}
}
$message: ref("password is required"),
},
},
});

const { mount } = createVue({
Expand All @@ -245,9 +337,9 @@ describe("validation", () => {
`,
setup() {
return {
form
form,
};
}
},
});

const vm = mount();
Expand Down
4 changes: 4 additions & 0 deletions packages/vue-composable/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,9 @@
"peerDependencies2": {
"@vue/composition-api": "^1.0.0-beta.14",
"vue": "^2.6.10"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-beta.14",
"vue": "^2.6.10"
}
}

0 comments on commit 28e9fd3

Please sign in to comment.