Skip to content

Commit 904c016

Browse files
committed
feat: add test for autonomic forms, Hot fix for dispatching events to parent form from autonomic form.
1 parent 85b2838 commit 904c016

File tree

9 files changed

+156
-76
lines changed

9 files changed

+156
-76
lines changed

examples/autonomic-form/App.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
<station-form />
66

77
<button @click = "showChanges">Changes</button>
8+
<button @click = "showChanges" v-if = "formState.changed">Save</button>
89
</div>
910
</template>
1011

1112
<script setup lang='ts'>
1213
13-
import {Form, FormField} from "../../src";
14+
import {Form, FormField, useFormState} from "../../src";
1415
import StationForm from "./station-form.vue";
1516
1617
const form = new Form();
18+
const formState = useFormState(form);
1719
// @ts-ignore
1820
window.theForm = form;
1921
function showChanges() {

project/pages/test/App.vue

Lines changed: 20 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,28 @@
1-
<template>
2-
<div class="container-examples">
3-
<div :key = "values">Values: {{values}}</div>
4-
5-
<div :key = "changes">Changes: {{changes}}</div>
6-
<div :key = "pureValue">Pure values: {{pureValue}}</div>
7-
<div :key = "pureAvailabilities">Pure av: {{pureAvailabilities}}</div>
1+
<script setup lang="ts">
82
9-
<input-field name = "birthday" type = "date" label = "Placeholder" />
3+
import {useFormValues, Form, FormField} from "../../../src/index";
4+
import ParentForm from "./parent-form.vue";
105
11-
<input-field name = "birthday" type = "date" label = "Other mask" mask = "MM/DD/YYYY" :handlers = "[testFrom, testTo]"/>
6+
const form = new Form({
7+
name: "grand"
8+
})
9+
const values = useFormValues(form);
1210
11+
// @ts-ignore
12+
window.theForm = form;
13+
</script>
1314

15+
<template>
16+
<div class="container">
17+
<form-field name="username" label="username"/>
18+
{{ values }}
19+
<parent-form/>
1420
</div>
1521
</template>
1622

17-
<script setup lang='ts'>
18-
import Form from "../../../src/classes/Form";
19-
import {ref} from "vue";
20-
import copyObject from "./../../../src/utils/copy-object";
21-
import {InputField} from "../../../src/index";
22-
import DateController from "../../../src/controllers/date-controller";
23-
24-
// @ts-ignore
25-
const form = window.form = new Form({
26-
name: "main",
27-
parent:false
28-
});
29-
const show = ref(false);
30-
31-
setInterval(() => {
32-
if (!form) return;
33-
34-
values.value = copyObject(form?.values);
35-
changes.value = copyObject(form.changes);
36-
pureValue.value = copyObject(form.TEST_PURE_VALUE);
37-
pureAvailabilities.value = copyObject(form.TEST_PURE_AVAILABILITIES)
38-
}, 50);
39-
40-
41-
42-
43-
const values = ref(0);
44-
const changes = ref({});
45-
const pureValue= ref({});
46-
const pureAvailabilities = ref({})
47-
48-
const name = ref('username');
49-
50-
function change() {
51-
name.value = name.value === 'username' ? 'age' : 'username';
23+
<style scoped>
24+
.container {
25+
padding: 20px;
26+
border: 2px solid black;
5227
}
53-
function clean() {
54-
form.cleanValues();
55-
}
56-
57-
function testFrom(date: unknown) {
58-
if (typeof date !== 'string') return null;
59-
return new Date(date)
60-
}
61-
62-
function testTo(str?: string) {
63-
if (typeof str !== 'string') return null;
64-
65-
const p = DateController.ConvertToDate(str, "MM/DD/YYYY");
66-
if (!p) return null;
67-
68-
return DateController.GetPrettyDate(p, 'YYYY-MM-DD')
69-
}
70-
71-
</script>
72-
73-
<style>
74-
75-
</style>
28+
</style>

project/pages/test/child-form.vue

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script setup lang="ts">
2+
3+
import {useFormValues, Form, FormField} from "../../../src/index";
4+
5+
6+
const form = new Form({
7+
name: "child"
8+
})
9+
const values = useFormValues(form);
10+
</script>
11+
12+
<template>
13+
<div class="container">
14+
<form-field name="username" label="username"/>
15+
{{ values }}
16+
</div>
17+
</template>
18+
19+
<style scoped>
20+
.container {
21+
padding: 20px;
22+
border: 2px solid black;
23+
}
24+
</style>

project/pages/test/main.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import InputTestDateLocal from "./input-test-date-local.vue";
1010
import InputNativeDate from "./input-native-date.vue";
1111

1212
config({
13+
1314
inputTypes: {
1415
country,
1516
"account-type": accountType,
@@ -18,7 +19,7 @@ config({
1819
'local-date': InputTestDateLocal,
1920
'native-date': InputNativeDate
2021
},
21-
// debug: true
22+
debug: true
2223
})
2324

2425
createApp(App).mount('#app')

project/pages/test/parent-form.vue

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<script setup lang="ts">
2+
3+
import {useFormValues, Form, FormField} from "../../../src/index";
4+
import ChildForm from "./child-form.vue";
5+
6+
7+
const form = new Form({
8+
name: "parent"
9+
})
10+
const values = useFormValues(form);
11+
</script>
12+
13+
<template>
14+
15+
<div class="container">
16+
<form-field name="username" label="username"/>
17+
{{ values }}
18+
19+
<child-form/>
20+
</div>
21+
</template>
22+
23+
<style scoped>
24+
.container {
25+
padding: 20px;
26+
border: 2px solid black;
27+
}
28+
</style>

src/classes/Form.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,11 @@ export default class Form extends EventEmitter implements FormDependence {
107107
* */
108108
#changes = {};
109109
get changes(): any {
110-
if (this.parent && !this.autonomic) return getPropFromObject(this.parent.changes, Form.getTargetName(this));
111-
return this.#changes;
110+
if (!this.parent || this.autonomic) return this.#changes;
111+
112+
const parentChanges = this.parent.changes;
113+
if (!this.name) throw FormError.FormWithoutName()
114+
return getPropFromObject(parentChanges, this.name);
112115
}
113116

114117
#values = {}
@@ -454,8 +457,6 @@ export default class Form extends EventEmitter implements FormDependence {
454457
* Наша система построена так, что бы все значения идут от родителя к дочернему элементу (values, changes, event, other..)
455458
* */
456459
dispatchEvent<T extends FormEvent>(event: T) {
457-
458-
459460
if (event instanceof CompareEvent) {
460461
debug.msg(`[%c${Form.restoreFullName(this)}%c] %c${event?.comparison.length ? 'found updates' : 'not effect'}%c`,
461462
debug.colorName, debug.colorDefault,
@@ -464,7 +465,16 @@ export default class Form extends EventEmitter implements FormDependence {
464465
)
465466

466467
if (event.comparison.length) this.emit(Form.EVENT_CHANGED, this.changed);
467-
468+
469+
// HOT FIX FOR AUTONOMIC FORM
470+
{
471+
let p = this.parent;
472+
while(p) {
473+
p.emit(Form.EVENT_CHANGED, p.changed);
474+
p = p.parent;
475+
}
476+
}
477+
468478
// Проходим по всем дочерним элементам и уведомляем их
469479
this.dependencies.forEach(dep => {
470480
if (dep.name) {

src/classes/FormError.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export default class FormError extends Error{
1212
static RepeatDependingWithSameName(name: string, element: any) {
1313
return new FormError(`The element with the name ${name} has already been subscribed to the form.`, element);
1414
}
15-
static ProxyFormWithoutName() {
16-
return new FormError(`Can't create FormProxy without name.`);
15+
static FormWithoutName() {
16+
return new FormError(`For some case form should has the name.`);
1717
}
1818
static TryToGetValueWithoutName() {
1919
return new FormError(`Can't get value without name. Looks like form.getValueByName(). Current method has one required param.`)

tests/units/form/form-changed.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,23 @@ describe("Form.changed", () => {
6969
form.cleanChangesByField("name");
7070
expect(form.changed).toBe(false);
7171
})
72+
73+
test("With three parent", () => {
74+
const grandParent = new Form({name: 'grand'})
75+
const parent = new Form({name: 'parent', parent: grandParent})
76+
const child = new Form({name: 'child', parent: parent})
77+
78+
79+
child.change({name: 'Jack'})
80+
81+
console.log(child.values)
82+
console.log(child.changes)
83+
console.log(parent.changes)
84+
console.log(grandParent.changes)
85+
86+
expect(grandParent.changed).toBe(true)
87+
expect(parent.changed).toBe(true)
88+
expect(child.changed).toBe(true)
89+
})
7290

7391
})

tests/units/hooks/use-form-state.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,48 @@ describe("Use form state", () => {
2626
expect(formState.changed).toBe(false)
2727
})
2828
test("After change/revert it should be updated", () => {})
29+
30+
test("Autonomic form: children changes should update status of parent form", () => {
31+
const parent = new Form()
32+
const child = new Form({
33+
parent,
34+
name: "test",
35+
autonomic: true
36+
})
37+
38+
const parentState = useFormState(parent);
39+
const childState = useFormState(parent);
40+
41+
expect(parent.changed).toBe(false);
42+
expect(child.changed).toBe(false);
43+
44+
child.change({
45+
age: 18
46+
})
47+
48+
expect(parentState.changed).toBe(true);
49+
expect(childState.changed).toBe(true);
50+
})
51+
52+
test("", () => {
53+
const grandParent = new Form({name: '0'})
54+
const parent = new Form({name: '1', parent: grandParent})
55+
const child = new Form({name: '2', parent, autonomic: true})
56+
57+
const grandParentState = useFormState(grandParent)
58+
const parentState = useFormState(parent)
59+
const childState = useFormState(child)
60+
61+
child.change({name: 'Jack'})
62+
63+
expect(grandParent.changed).toBe(true)
64+
expect(parent.changed).toBe(true)
65+
expect(child.changed).toBe(true)
66+
67+
expect(grandParentState.changed).toBe(true)
68+
expect(parentState.changed).toBe(true)
69+
expect(childState.changed).toBe(true)
70+
71+
})
72+
2973
})

0 commit comments

Comments
 (0)