Skip to content

Commit

Permalink
fix(vue3): c-datetime-picker was passing raw strings to validation rules
Browse files Browse the repository at this point in the history
  • Loading branch information
ascott18 committed Aug 18, 2023
1 parent 223b27a commit 1c48133
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Grade, Student } from "@test/targets.models";
import { StudentViewModel } from "@test/targets.viewmodels";
import { delay, mount, nextTick } from "@test/util";
import { CDatetimePicker } from "..";

describe("CDatetimePicker", () => {
let model: StudentViewModel;
beforeEach(() => {
model = new StudentViewModel({
name: "bob",
grade: Grade.Freshman,
password: "secretValue",
email: "bob@college.edu",
phone: "123-123-1234",
color: "#ff0000",
notes: "multiline\n\nstring",
});
});

test("caller model - date value", async () => {
const wrapper = mount(() => (
<CDatetimePicker model={model.manyParams} for="date" />
));

// Assert resting state
expect(wrapper.find("label").text()).toEqual("Date");

// Set a value, and look for the value
model.manyParams.args.date = new Date("2023-08-16T01:02:03Z");
await delay(1);
expect(wrapper.find("input").element.value).contains("2023");

// Perform an input on the component, and then look for the new value.
await wrapper.find("input").setValue("1/3/2017");
await delay(1);
expect(model.manyParams.args.date.getFullYear()).toBe(2017);
});

test("validation rules are passed date, not string", async () => {
const rule = vitest.fn(
(v) => !v || v.getFullYear() > 2017 || "Year must be > 2017"
);

const wrapper = mount(() => (
//@ts-ignore useless error about extra properties
<CDatetimePicker model={model} for="birthDate" rules={[rule]} />
));

// Perform an input on the component, and then look at the args that were passed to the rule function:
await wrapper.find("input").setValue("1/3/2017");
await delay(1);
expect(wrapper.text()).toContain("Year must be > 2017");
expect(model.birthDate?.getFullYear()).toBe(2017);
expect(rule).toBeCalledTimes(1);
expect(rule).toBeCalledWith(model.birthDate);

// Do it again, but with a valid input this time. The error should be gone.
await wrapper.find("input").setValue("1/3/2018");
await delay(1);
expect(wrapper.text()).not.toContain("Year must be > 2017");
expect(model.birthDate?.getFullYear()).toBe(2018);
expect(rule).toBeCalledTimes(2);
expect(rule).toHaveBeenLastCalledWith(model.birthDate);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"
:modelValue="nativeValue"
v-bind="inputBindAttrs"
:rules="effectiveRules"
:error-messages="error"
:readonly="readonly"
:disabled="disabled"
Expand All @@ -23,6 +24,7 @@
v-else
class="c-datetime-picker"
v-bind="inputBindAttrs"
:rules="effectiveRules"
:modelValue="internalTextValue == null ? displayedValue : internalTextValue"
:error-messages="error"
:readonly="readonly"
Expand Down Expand Up @@ -208,7 +210,7 @@ export default defineComponent({
return null;
},
internalValue() {
internalValue(): Date | null | undefined {
if (this.valueOwner && this.dateMeta) {
return (this.valueOwner as any)[this.dateMeta.name];
}
Expand Down Expand Up @@ -259,6 +261,15 @@ export default defineComponent({
}
},
/** The effective set of validation rules to pass to the text field. Ensures that the real Date value is passed to the rule, rather than the text field's string value. */
effectiveRules() {
return this.inputBindAttrs.rules?.map(
(ruleFunc: (value: Date | null | undefined) => string | boolean) =>
() =>
ruleFunc(this.internalValue)
);
},
showDate() {
return (
this.internalDateKind == "datetime" || this.internalDateKind == "date"
Expand Down

0 comments on commit 1c48133

Please sign in to comment.