@homebound/form-state 2.19.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FormStateApp.d.ts +2 -3
- package/dist/FormStateApp.js +8 -47
- package/dist/FormStateApp.test.js +14 -14
- package/dist/config.d.ts +6 -6
- package/dist/fields/fragmentField.js +3 -3
- package/dist/fields/listField.js +12 -12
- package/dist/fields/objectField.d.ts +4 -4
- package/dist/fields/objectField.js +10 -10
- package/dist/fields/valueField.d.ts +13 -0
- package/dist/fields/valueField.js +48 -14
- package/dist/formState.stories.d.ts +2 -4
- package/dist/formState.stories.js +1 -1
- package/dist/formState.test.js +146 -79
- package/dist/formStateDomain.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/proxies.d.ts +5 -0
- package/dist/proxies.js +21 -0
- package/dist/rules.d.ts +1 -1
- package/dist/rules.js +1 -1
- package/dist/setupTests.js +2 -2
- package/dist/useFormState.d.ts +4 -4
- package/dist/useFormState.js +13 -13
- package/dist/useFormState.test.js +141 -169
- package/dist/useFormStates.d.ts +3 -3
- package/dist/useFormStates.js +7 -7
- package/dist/useFormStates.test.js +56 -63
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +8 -8
- package/dist/utils.test.js +49 -49
- package/package.json +44 -39
package/dist/formState.test.js
CHANGED
|
@@ -4,24 +4,61 @@ const mobx_1 = require("mobx");
|
|
|
4
4
|
const objectField_1 = require("./fields/objectField");
|
|
5
5
|
const formStateDomain_1 = require("./formStateDomain");
|
|
6
6
|
const rules_1 = require("./rules");
|
|
7
|
-
describe("
|
|
7
|
+
describe("mobx behavior", () => {
|
|
8
|
+
it("mobx batches if in actions", () => {
|
|
9
|
+
const a = (0, mobx_1.observable)({ name: "a1" });
|
|
10
|
+
const b = (0, mobx_1.observable)({ name: "b1" });
|
|
11
|
+
const map = new mobx_1.ObservableMap();
|
|
12
|
+
map.set("a", a);
|
|
13
|
+
map.set("b", b);
|
|
14
|
+
let runs = 0;
|
|
15
|
+
(0, mobx_1.autorun)(() => {
|
|
16
|
+
noop([...map.values()].filter((v) => v.name.includes("1")));
|
|
17
|
+
runs++;
|
|
18
|
+
});
|
|
19
|
+
expect(runs).toBe(1);
|
|
20
|
+
// When we change both a and b
|
|
21
|
+
(0, mobx_1.runInAction)(() => {
|
|
22
|
+
a.name = "a11";
|
|
23
|
+
b.name = "b2";
|
|
24
|
+
});
|
|
25
|
+
// Then the reaction waited and only ran once
|
|
26
|
+
expect(runs).toBe(2);
|
|
27
|
+
});
|
|
28
|
+
it("mobx can watch undefined keys", () => {
|
|
29
|
+
const a = new ObservableObject();
|
|
30
|
+
const b = new ObservableObject();
|
|
31
|
+
const map = new mobx_1.ObservableMap();
|
|
32
|
+
map.set("a", a);
|
|
33
|
+
map.set("b", b);
|
|
34
|
+
let runs = 0;
|
|
35
|
+
(0, mobx_1.autorun)(() => {
|
|
36
|
+
noop([...map.values()].map((a) => a.age));
|
|
37
|
+
runs++;
|
|
38
|
+
});
|
|
39
|
+
expect(runs).toBe(1);
|
|
40
|
+
b.age = 1;
|
|
41
|
+
expect(runs).toBe(2);
|
|
42
|
+
});
|
|
8
43
|
it("mobx lists maintain observable identity", () => {
|
|
9
44
|
// given a parent observable
|
|
10
|
-
const a = mobx_1.observable({ list: [] });
|
|
45
|
+
const a = (0, mobx_1.observable)({ list: [] });
|
|
11
46
|
// if we observable-ize a value being pushing it on the list
|
|
12
|
-
const c1 = mobx_1.observable({});
|
|
47
|
+
const c1 = (0, mobx_1.observable)({});
|
|
13
48
|
a.list.push(c1);
|
|
14
49
|
// then we get identify equality on the list lookups
|
|
15
50
|
expect(a.list[0] === c1).toEqual(true);
|
|
16
51
|
});
|
|
52
|
+
});
|
|
53
|
+
describe("formState", () => {
|
|
17
54
|
it("can create a simple object", () => {
|
|
18
|
-
const a = objectField_1.createObjectState({ title: { type: "value", rules: [rules_1.required] } }, {});
|
|
55
|
+
const a = (0, objectField_1.createObjectState)({ title: { type: "value", rules: [rules_1.required] } }, {});
|
|
19
56
|
expect(a.valid).toBeFalsy();
|
|
20
57
|
});
|
|
21
58
|
it("can validate a simple input", () => {
|
|
22
|
-
const a = objectField_1.createObjectState({ title: { type: "value", rules: [rules_1.required] } }, { title: "b1" });
|
|
59
|
+
const a = (0, objectField_1.createObjectState)({ title: { type: "value", rules: [rules_1.required] } }, { title: "b1" });
|
|
23
60
|
let numErrors = 0;
|
|
24
|
-
mobx_1.autorun(() => {
|
|
61
|
+
(0, mobx_1.autorun)(() => {
|
|
25
62
|
numErrors = a.title.errors.length;
|
|
26
63
|
});
|
|
27
64
|
expect(a.valid).toBeTruthy();
|
|
@@ -33,7 +70,7 @@ describe("formState", () => {
|
|
|
33
70
|
expect(a.errors).toEqual(["title: Required"]);
|
|
34
71
|
});
|
|
35
72
|
it("can tell what is required", () => {
|
|
36
|
-
const a = objectField_1.createObjectState({
|
|
73
|
+
const a = (0, objectField_1.createObjectState)({
|
|
37
74
|
title: { type: "value", rules: [rules_1.required] },
|
|
38
75
|
isPublished: { type: "value" },
|
|
39
76
|
}, {});
|
|
@@ -41,9 +78,9 @@ describe("formState", () => {
|
|
|
41
78
|
expect(a.isPublished.required).toBeFalsy();
|
|
42
79
|
});
|
|
43
80
|
it("trims whitespace within the required rule", () => {
|
|
44
|
-
const a = objectField_1.createObjectState({ title: { type: "value", rules: [rules_1.required] } }, { title: "initial valid title" });
|
|
81
|
+
const a = (0, objectField_1.createObjectState)({ title: { type: "value", rules: [rules_1.required] } }, { title: "initial valid title" });
|
|
45
82
|
let numErrors = 0;
|
|
46
|
-
mobx_1.autorun(() => {
|
|
83
|
+
(0, mobx_1.autorun)(() => {
|
|
47
84
|
numErrors = a.title.errors.length;
|
|
48
85
|
});
|
|
49
86
|
expect(a.valid).toBeTruthy();
|
|
@@ -56,16 +93,16 @@ describe("formState", () => {
|
|
|
56
93
|
expect(a.errors).toEqual(["title: Required"]);
|
|
57
94
|
});
|
|
58
95
|
it("can set values", () => {
|
|
59
|
-
const a = objectField_1.createObjectState({ title: { type: "value" } }, { title: "b1" });
|
|
96
|
+
const a = (0, objectField_1.createObjectState)({ title: { type: "value" } }, { title: "b1" });
|
|
60
97
|
expect(a.title.value).toEqual("b1");
|
|
61
98
|
});
|
|
62
99
|
it("can read values", () => {
|
|
63
|
-
const a = objectField_1.createObjectState({ title: { type: "value" } }, { title: "b1" });
|
|
100
|
+
const a = (0, objectField_1.createObjectState)({ title: { type: "value" } }, { title: "b1" });
|
|
64
101
|
expect(a.value.title).toEqual("b1");
|
|
65
102
|
expect(a.title.value).toEqual("b1");
|
|
66
103
|
});
|
|
67
104
|
it("can set dates", () => {
|
|
68
|
-
const a = objectField_1.createObjectState({
|
|
105
|
+
const a = (0, objectField_1.createObjectState)({
|
|
69
106
|
birthday: {
|
|
70
107
|
type: "value",
|
|
71
108
|
rules: [({ value }) => ((value === null || value === void 0 ? void 0 : value.getTime()) === formStateDomain_1.jan2.getTime() ? "cannot be born on jan2" : undefined)],
|
|
@@ -86,6 +123,35 @@ describe("formState", () => {
|
|
|
86
123
|
const a = createAuthorWithAddressInputState({ address: { city: "b1" } });
|
|
87
124
|
expect(a.address.city.value).toEqual("b1");
|
|
88
125
|
});
|
|
126
|
+
it("can adapt values", () => {
|
|
127
|
+
// Given an author where `delete` is normally a boolean
|
|
128
|
+
const a = (0, objectField_1.createObjectState)({
|
|
129
|
+
delete: { type: "value" },
|
|
130
|
+
}, { delete: true });
|
|
131
|
+
const boolField = a.delete;
|
|
132
|
+
// But we adapt it to a string
|
|
133
|
+
const stringField = a.delete.adapt({
|
|
134
|
+
toValue: (b) => String(b),
|
|
135
|
+
fromValue: (s) => Boolean(s),
|
|
136
|
+
});
|
|
137
|
+
// Then we can read it as a string
|
|
138
|
+
expect(stringField.value).toEqual("true");
|
|
139
|
+
// And we can set it as a string
|
|
140
|
+
stringField.value = "";
|
|
141
|
+
expect(boolField.value).toBe(false);
|
|
142
|
+
// And the originalValue is maintained
|
|
143
|
+
expect(boolField.originalValue).toBe(true);
|
|
144
|
+
expect(stringField.originalValue).toBe("true");
|
|
145
|
+
// As well as the dirty.
|
|
146
|
+
expect(boolField.dirty).toBe(true);
|
|
147
|
+
expect(stringField.dirty).toBe(true);
|
|
148
|
+
// And reverting works
|
|
149
|
+
stringField.revertChanges();
|
|
150
|
+
expect(boolField.dirty).toBe(false);
|
|
151
|
+
expect(stringField.dirty).toBe(false);
|
|
152
|
+
expect(boolField.value).toBe(true);
|
|
153
|
+
expect(stringField.value).toBe("true");
|
|
154
|
+
});
|
|
89
155
|
it("maintains object identity", () => {
|
|
90
156
|
const a1 = { firstName: "a1" };
|
|
91
157
|
const state = createAuthorInputState(a1);
|
|
@@ -113,7 +179,7 @@ describe("formState", () => {
|
|
|
113
179
|
const state = createAuthorInputState(a1);
|
|
114
180
|
let numBooks;
|
|
115
181
|
let ticks = 0;
|
|
116
|
-
mobx_1.autorun(() => {
|
|
182
|
+
(0, mobx_1.autorun)(() => {
|
|
117
183
|
numBooks = state.books.rows.length;
|
|
118
184
|
ticks++;
|
|
119
185
|
});
|
|
@@ -135,7 +201,7 @@ describe("formState", () => {
|
|
|
135
201
|
const state = createAuthorInputState(a1);
|
|
136
202
|
let books;
|
|
137
203
|
let ticks = 0;
|
|
138
|
-
mobx_1.autorun(() => {
|
|
204
|
+
(0, mobx_1.autorun)(() => {
|
|
139
205
|
books = state.books.value;
|
|
140
206
|
ticks++;
|
|
141
207
|
});
|
|
@@ -150,7 +216,7 @@ describe("formState", () => {
|
|
|
150
216
|
};
|
|
151
217
|
// And we initially have ids in the input
|
|
152
218
|
const a1 = { id: "1", firstName: "a1", books: [{ id: "2", title: "t1" }] };
|
|
153
|
-
const state = objectField_1.createObjectState(config, a1);
|
|
219
|
+
const state = (0, objectField_1.createObjectState)(config, a1);
|
|
154
220
|
// And we edit a few things
|
|
155
221
|
state.firstName.set("a2");
|
|
156
222
|
state.books.add({ title: "t2" });
|
|
@@ -168,7 +234,7 @@ describe("formState", () => {
|
|
|
168
234
|
expect(a1.valid).toBeTruthy();
|
|
169
235
|
let lastValid = undefined;
|
|
170
236
|
let ticks = 0;
|
|
171
|
-
mobx_1.autorun(() => {
|
|
237
|
+
(0, mobx_1.autorun)(() => {
|
|
172
238
|
lastValid = a1.valid;
|
|
173
239
|
ticks++;
|
|
174
240
|
});
|
|
@@ -271,7 +337,7 @@ describe("formState", () => {
|
|
|
271
337
|
const a1 = createAuthorInputState({ firstName: "a1", books: [] });
|
|
272
338
|
let ticks = 0;
|
|
273
339
|
let numErrors = 0;
|
|
274
|
-
mobx_1.autorun(() => {
|
|
340
|
+
(0, mobx_1.autorun)(() => {
|
|
275
341
|
numErrors = a1.books.errors.length;
|
|
276
342
|
ticks++;
|
|
277
343
|
});
|
|
@@ -287,7 +353,7 @@ describe("formState", () => {
|
|
|
287
353
|
expect(numErrors).toEqual(0);
|
|
288
354
|
});
|
|
289
355
|
it("can validate across fields", () => {
|
|
290
|
-
const a = objectField_1.createObjectState({
|
|
356
|
+
const a = (0, objectField_1.createObjectState)({
|
|
291
357
|
firstName: { type: "value", rules: [] },
|
|
292
358
|
lastName: { type: "value" },
|
|
293
359
|
}, {});
|
|
@@ -304,7 +370,7 @@ describe("formState", () => {
|
|
|
304
370
|
it("passes sanitized values to validation rules", () => {
|
|
305
371
|
// Given a field with a validation rule
|
|
306
372
|
const rule = jest.fn().mockReturnValue("Required");
|
|
307
|
-
const a = objectField_1.createObjectState({ firstName: { type: "value", rules: [rule] } }, {});
|
|
373
|
+
const a = (0, objectField_1.createObjectState)({ firstName: { type: "value", rules: [rule] } }, {});
|
|
308
374
|
expect(rule).toHaveBeenCalledTimes(0);
|
|
309
375
|
// When the field is set to empty string
|
|
310
376
|
a.firstName.value = "";
|
|
@@ -321,7 +387,7 @@ describe("formState", () => {
|
|
|
321
387
|
it("passes trimmed values to validation rules on maybeAutoSave", () => {
|
|
322
388
|
// Given we have a required rule
|
|
323
389
|
const rule = jest.fn().mockReturnValue("Required");
|
|
324
|
-
const a = objectField_1.createObjectState({ firstName: { type: "value", rules: [rule] } }, {});
|
|
390
|
+
const a = (0, objectField_1.createObjectState)({ firstName: { type: "value", rules: [rule] } }, {});
|
|
325
391
|
expect(rule).toHaveBeenCalledTimes(0);
|
|
326
392
|
// When the user initially sets an empty string value
|
|
327
393
|
a.firstName.focus();
|
|
@@ -348,12 +414,12 @@ describe("formState", () => {
|
|
|
348
414
|
});
|
|
349
415
|
});
|
|
350
416
|
it("simple value changes trigger observers", () => {
|
|
351
|
-
const a = objectField_1.createObjectState({
|
|
417
|
+
const a = (0, objectField_1.createObjectState)({
|
|
352
418
|
title: { type: "value", rules: [rules_1.required] },
|
|
353
419
|
}, { title: "t2" });
|
|
354
420
|
let lastTitle = undefined;
|
|
355
421
|
let ticks = 0;
|
|
356
|
-
mobx_1.autorun(() => {
|
|
422
|
+
(0, mobx_1.autorun)(() => {
|
|
357
423
|
lastTitle = a.title.value;
|
|
358
424
|
ticks++;
|
|
359
425
|
});
|
|
@@ -466,7 +532,7 @@ describe("formState", () => {
|
|
|
466
532
|
expect(maybeAutoSave).toBeCalledTimes(0);
|
|
467
533
|
});
|
|
468
534
|
it("knows list of primitives are dirty", () => {
|
|
469
|
-
const a1 = objectField_1.createObjectState({ favoriteColors: { type: "value" } }, {});
|
|
535
|
+
const a1 = (0, objectField_1.createObjectState)({ favoriteColors: { type: "value" } }, {});
|
|
470
536
|
expect(a1.favoriteColors.dirty).toBeFalsy();
|
|
471
537
|
a1.favoriteColors.set([formStateDomain_1.Color.Blue]);
|
|
472
538
|
expect(a1.dirty).toBeTruthy();
|
|
@@ -477,7 +543,7 @@ describe("formState", () => {
|
|
|
477
543
|
expect(a1.dirty).toBeFalsy();
|
|
478
544
|
});
|
|
479
545
|
it("knows list of primitives are dirty with initialized as empty list", () => {
|
|
480
|
-
const a1 = objectField_1.createObjectState({ favoriteColors: { type: "value" } }, { favoriteColors: [] });
|
|
546
|
+
const a1 = (0, objectField_1.createObjectState)({ favoriteColors: { type: "value" } }, { favoriteColors: [] });
|
|
481
547
|
expect(a1.favoriteColors.dirty).toBeFalsy();
|
|
482
548
|
a1.favoriteColors.set([formStateDomain_1.Color.Blue]);
|
|
483
549
|
expect(a1.dirty).toBeTruthy();
|
|
@@ -489,7 +555,7 @@ describe("formState", () => {
|
|
|
489
555
|
});
|
|
490
556
|
it("can evaluate arrays to be equal even if order of options are different from original when strictOrder = false", () => {
|
|
491
557
|
// Given an array field value where we define `strictOrder` as false
|
|
492
|
-
const a1 = objectField_1.createObjectState({ favoriteColors: { type: "value", strictOrder: false } }, { favoriteColors: [formStateDomain_1.Color.Red, formStateDomain_1.Color.Blue] });
|
|
558
|
+
const a1 = (0, objectField_1.createObjectState)({ favoriteColors: { type: "value", strictOrder: false } }, { favoriteColors: [formStateDomain_1.Color.Red, formStateDomain_1.Color.Blue] });
|
|
493
559
|
expect(a1.favoriteColors.dirty).toBeFalsy();
|
|
494
560
|
// When changing the order of the values
|
|
495
561
|
a1.favoriteColors.set([formStateDomain_1.Color.Blue, formStateDomain_1.Color.Red]);
|
|
@@ -498,7 +564,7 @@ describe("formState", () => {
|
|
|
498
564
|
});
|
|
499
565
|
it("evaluates arrays to be equal based on order by default", () => {
|
|
500
566
|
// Given an array field value
|
|
501
|
-
const a1 = objectField_1.createObjectState({ favoriteColors: { type: "value" } }, { favoriteColors: [formStateDomain_1.Color.Red, formStateDomain_1.Color.Blue] });
|
|
567
|
+
const a1 = (0, objectField_1.createObjectState)({ favoriteColors: { type: "value" } }, { favoriteColors: [formStateDomain_1.Color.Red, formStateDomain_1.Color.Blue] });
|
|
502
568
|
expect(a1.favoriteColors.dirty).toBeFalsy();
|
|
503
569
|
// When we change the order of the values
|
|
504
570
|
a1.favoriteColors.set([formStateDomain_1.Color.Blue, formStateDomain_1.Color.Red]);
|
|
@@ -675,7 +741,7 @@ describe("formState", () => {
|
|
|
675
741
|
expect(a1.value.firstName).toBeNull();
|
|
676
742
|
});
|
|
677
743
|
it("can map properties to other types", () => {
|
|
678
|
-
const a1 = objectField_1.createObjectState({
|
|
744
|
+
const a1 = (0, objectField_1.createObjectState)({
|
|
679
745
|
person: { type: "value" },
|
|
680
746
|
}, { person: { firstName: "a1", lastName: "b1" } });
|
|
681
747
|
a1.person.set({ firstName: "a2", lastName: "b2" });
|
|
@@ -701,7 +767,7 @@ describe("formState", () => {
|
|
|
701
767
|
});
|
|
702
768
|
it("maintain field readOnly state when form is readOnly", () => {
|
|
703
769
|
// Given a formState
|
|
704
|
-
const formState = objectField_1.createObjectState({ title: { type: "value", rules: [rules_1.required], readOnly: true } }, {});
|
|
770
|
+
const formState = (0, objectField_1.createObjectState)({ title: { type: "value", rules: [rules_1.required], readOnly: true } }, {});
|
|
705
771
|
// Then expect form
|
|
706
772
|
expect(formState.title.readOnly).toBeTruthy();
|
|
707
773
|
});
|
|
@@ -776,7 +842,7 @@ describe("formState", () => {
|
|
|
776
842
|
expect(a1.firstName.loading).toBeTruthy();
|
|
777
843
|
});
|
|
778
844
|
it("canSave returns dirty and touches", () => {
|
|
779
|
-
const a1 = objectField_1.createObjectState({
|
|
845
|
+
const a1 = (0, objectField_1.createObjectState)({
|
|
780
846
|
firstName: { type: "value", rules: [rules_1.required] },
|
|
781
847
|
}, {});
|
|
782
848
|
expect(a1.firstName.touched).toBeFalsy();
|
|
@@ -784,7 +850,7 @@ describe("formState", () => {
|
|
|
784
850
|
expect(a1.firstName.touched).toBeTruthy();
|
|
785
851
|
});
|
|
786
852
|
it("uses toJSON if available for dirty checks", () => {
|
|
787
|
-
const a1 = objectField_1.createObjectState({
|
|
853
|
+
const a1 = (0, objectField_1.createObjectState)({
|
|
788
854
|
birthday: { type: "value" },
|
|
789
855
|
}, { birthday: new formStateDomain_1.DateOnly(formStateDomain_1.jan1) });
|
|
790
856
|
a1.birthday.set(new formStateDomain_1.DateOnly(formStateDomain_1.jan1));
|
|
@@ -799,7 +865,7 @@ describe("formState", () => {
|
|
|
799
865
|
expect(a.valid).toBeTruthy();
|
|
800
866
|
});
|
|
801
867
|
it("can validate a list input", () => {
|
|
802
|
-
const a = objectField_1.createObjectState({
|
|
868
|
+
const a = (0, objectField_1.createObjectState)({
|
|
803
869
|
books: {
|
|
804
870
|
type: "list",
|
|
805
871
|
config: { title: { type: "value", rules: [rules_1.required] } },
|
|
@@ -807,7 +873,7 @@ describe("formState", () => {
|
|
|
807
873
|
},
|
|
808
874
|
}, {});
|
|
809
875
|
let lastErrors = "";
|
|
810
|
-
mobx_1.autorun(() => {
|
|
876
|
+
(0, mobx_1.autorun)(() => {
|
|
811
877
|
lastErrors = a.books.errors.join(", ");
|
|
812
878
|
});
|
|
813
879
|
a.books.add({ title: "t1" });
|
|
@@ -816,7 +882,7 @@ describe("formState", () => {
|
|
|
816
882
|
expect(lastErrors).toEqual("");
|
|
817
883
|
});
|
|
818
884
|
it("can ignore a deleted list entry", () => {
|
|
819
|
-
const a = objectField_1.createObjectState({
|
|
885
|
+
const a = (0, objectField_1.createObjectState)({
|
|
820
886
|
books: {
|
|
821
887
|
type: "list",
|
|
822
888
|
config: {
|
|
@@ -835,7 +901,7 @@ describe("formState", () => {
|
|
|
835
901
|
expect(a.books.valid).toBeTruthy();
|
|
836
902
|
});
|
|
837
903
|
it("can treat a list entry as read-only", () => {
|
|
838
|
-
const a = objectField_1.createObjectState({
|
|
904
|
+
const a = (0, objectField_1.createObjectState)({
|
|
839
905
|
books: {
|
|
840
906
|
type: "list",
|
|
841
907
|
config: {
|
|
@@ -864,13 +930,13 @@ describe("formState", () => {
|
|
|
864
930
|
a.address.city.value = "b1";
|
|
865
931
|
expect(a.address.city.value).toEqual("b1");
|
|
866
932
|
expect(a.address.value).toMatchInlineSnapshot(`
|
|
867
|
-
|
|
933
|
+
{
|
|
868
934
|
"city": "b1",
|
|
869
935
|
}
|
|
870
936
|
`);
|
|
871
937
|
expect(a.value).toMatchInlineSnapshot(`
|
|
872
|
-
|
|
873
|
-
"address":
|
|
938
|
+
{
|
|
939
|
+
"address": {
|
|
874
940
|
"city": "b1",
|
|
875
941
|
},
|
|
876
942
|
}
|
|
@@ -879,12 +945,12 @@ describe("formState", () => {
|
|
|
879
945
|
it("can wrap an existing list observable", () => {
|
|
880
946
|
// Given an array observable that is already created
|
|
881
947
|
const b1 = { title: "b1" };
|
|
882
|
-
const books = mobx_1.observable([b1]);
|
|
948
|
+
const books = (0, mobx_1.observable)([b1]);
|
|
883
949
|
// When we create a form state around it
|
|
884
950
|
const formState = createAuthorInputState({ books });
|
|
885
951
|
// Then the initial book was copied over
|
|
886
952
|
let lastLength = 0;
|
|
887
|
-
mobx_1.autorun(() => {
|
|
953
|
+
(0, mobx_1.autorun)(() => {
|
|
888
954
|
lastLength = formState.books.rows.length;
|
|
889
955
|
});
|
|
890
956
|
expect(lastLength).toEqual(1);
|
|
@@ -903,7 +969,7 @@ describe("formState", () => {
|
|
|
903
969
|
expect(config).toBeDefined();
|
|
904
970
|
});
|
|
905
971
|
it("can reset observable objects with computeds", () => {
|
|
906
|
-
const formState = objectField_1.createObjectState({
|
|
972
|
+
const formState = (0, objectField_1.createObjectState)({
|
|
907
973
|
firstName: { type: "value" },
|
|
908
974
|
lastName: { type: "value" },
|
|
909
975
|
fullName: { type: "value", computed: true },
|
|
@@ -918,7 +984,7 @@ describe("formState", () => {
|
|
|
918
984
|
it("can observe observable objects being mutated directly", () => {
|
|
919
985
|
// Given a mobx class with a computed
|
|
920
986
|
const instance = new ObservableObject();
|
|
921
|
-
const formState = objectField_1.createObjectState({
|
|
987
|
+
const formState = (0, objectField_1.createObjectState)({
|
|
922
988
|
firstName: { type: "value" },
|
|
923
989
|
lastName: { type: "value" },
|
|
924
990
|
fullName: { type: "value", computed: true },
|
|
@@ -927,7 +993,7 @@ describe("formState", () => {
|
|
|
927
993
|
expect(formState.fullName.value).toEqual("first last");
|
|
928
994
|
// And we hook up reactivity to the computed
|
|
929
995
|
let numCalcs = 0;
|
|
930
|
-
mobx_1.autorun(() => {
|
|
996
|
+
(0, mobx_1.autorun)(() => {
|
|
931
997
|
numCalcs++;
|
|
932
998
|
noop(formState.fullName.value);
|
|
933
999
|
});
|
|
@@ -943,7 +1009,7 @@ describe("formState", () => {
|
|
|
943
1009
|
expect(formState.fullName.value).toEqual("undefined last");
|
|
944
1010
|
});
|
|
945
1011
|
it("can set computeds that have setters", () => {
|
|
946
|
-
const formState = objectField_1.createObjectState({
|
|
1012
|
+
const formState = (0, objectField_1.createObjectState)({
|
|
947
1013
|
firstName: { type: "value" },
|
|
948
1014
|
lastName: { type: "value" },
|
|
949
1015
|
fullName: { type: "value", computed: true },
|
|
@@ -956,7 +1022,7 @@ describe("formState", () => {
|
|
|
956
1022
|
expect(formState.firstName.value).toEqual("first");
|
|
957
1023
|
});
|
|
958
1024
|
it("can mark fields as read only", () => {
|
|
959
|
-
const formState = objectField_1.createObjectState({
|
|
1025
|
+
const formState = (0, objectField_1.createObjectState)({
|
|
960
1026
|
firstName: { type: "value" },
|
|
961
1027
|
lastName: { type: "value" },
|
|
962
1028
|
fullName: { type: "value", readOnly: true },
|
|
@@ -970,7 +1036,7 @@ describe("formState", () => {
|
|
|
970
1036
|
});
|
|
971
1037
|
it("can return only changed primitive fields", () => {
|
|
972
1038
|
// Given an author
|
|
973
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, {
|
|
1039
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, {
|
|
974
1040
|
id: "a:1",
|
|
975
1041
|
firstName: "f",
|
|
976
1042
|
lastName: "l",
|
|
@@ -988,7 +1054,7 @@ describe("formState", () => {
|
|
|
988
1054
|
});
|
|
989
1055
|
it("can return only changed object fields", () => {
|
|
990
1056
|
// Given an author with an address object
|
|
991
|
-
const formState = objectField_1.createObjectState(authorWithAddressConfig, {
|
|
1057
|
+
const formState = (0, objectField_1.createObjectState)(authorWithAddressConfig, {
|
|
992
1058
|
id: "a:1",
|
|
993
1059
|
firstName: "f",
|
|
994
1060
|
address: { city: "c1", street: "s1" },
|
|
@@ -1005,7 +1071,7 @@ describe("formState", () => {
|
|
|
1005
1071
|
});
|
|
1006
1072
|
it("changedValue skips empty nested fields", () => {
|
|
1007
1073
|
// Given a new author with an address object
|
|
1008
|
-
const formState = objectField_1.createObjectState(authorWithAddressConfig, {
|
|
1074
|
+
const formState = (0, objectField_1.createObjectState)(authorWithAddressConfig, {
|
|
1009
1075
|
firstName: "f",
|
|
1010
1076
|
// And nothing is in the address
|
|
1011
1077
|
address: {},
|
|
@@ -1016,7 +1082,7 @@ describe("formState", () => {
|
|
|
1016
1082
|
});
|
|
1017
1083
|
it("changedValue skips effectively empty nested fields", () => {
|
|
1018
1084
|
// Given a new author with an address object
|
|
1019
|
-
const formState = objectField_1.createObjectState(authorWithAddressConfig, {
|
|
1085
|
+
const formState = (0, objectField_1.createObjectState)(authorWithAddressConfig, {
|
|
1020
1086
|
firstName: "f",
|
|
1021
1087
|
// And only undefined keys are in the address
|
|
1022
1088
|
address: { city: undefined },
|
|
@@ -1027,7 +1093,7 @@ describe("formState", () => {
|
|
|
1027
1093
|
});
|
|
1028
1094
|
it("can return only changed list fields", () => {
|
|
1029
1095
|
// Given an author with some books
|
|
1030
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, {
|
|
1096
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, {
|
|
1031
1097
|
id: "a:1",
|
|
1032
1098
|
firstName: "f",
|
|
1033
1099
|
books: [
|
|
@@ -1048,7 +1114,7 @@ describe("formState", () => {
|
|
|
1048
1114
|
});
|
|
1049
1115
|
it("can return only changed but incremental list fields", () => {
|
|
1050
1116
|
// Given an author
|
|
1051
|
-
const formState = objectField_1.createObjectState({
|
|
1117
|
+
const formState = (0, objectField_1.createObjectState)({
|
|
1052
1118
|
id: { type: "value" },
|
|
1053
1119
|
// And the books collection is marked as incremental (i.e. line items)
|
|
1054
1120
|
books: {
|
|
@@ -1079,7 +1145,7 @@ describe("formState", () => {
|
|
|
1079
1145
|
});
|
|
1080
1146
|
it("uses the op key as a hint to use incremental list behavior", () => {
|
|
1081
1147
|
// Given an author
|
|
1082
|
-
const formState = objectField_1.createObjectState({
|
|
1148
|
+
const formState = (0, objectField_1.createObjectState)({
|
|
1083
1149
|
id: { type: "value" },
|
|
1084
1150
|
// And the books collection is not explicitly marked as incremental
|
|
1085
1151
|
books: {
|
|
@@ -1112,7 +1178,7 @@ describe("formState", () => {
|
|
|
1112
1178
|
});
|
|
1113
1179
|
it("defaults the incremental op key to included when not set", () => {
|
|
1114
1180
|
// Given an author
|
|
1115
|
-
const formState = objectField_1.createObjectState({
|
|
1181
|
+
const formState = (0, objectField_1.createObjectState)({
|
|
1116
1182
|
id: { type: "value" },
|
|
1117
1183
|
// And the books collection is not explicitly marked as incremental
|
|
1118
1184
|
books: {
|
|
@@ -1153,9 +1219,9 @@ describe("formState", () => {
|
|
|
1153
1219
|
});
|
|
1154
1220
|
});
|
|
1155
1221
|
it("can observe value changes", () => {
|
|
1156
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, { firstName: "f" });
|
|
1222
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, { firstName: "f" });
|
|
1157
1223
|
let ticks = 0;
|
|
1158
|
-
mobx_1.reaction(() => formState.value, () => ticks++, { equals: () => false });
|
|
1224
|
+
(0, mobx_1.reaction)(() => formState.value, () => ticks++, { equals: () => false });
|
|
1159
1225
|
expect(ticks).toEqual(0);
|
|
1160
1226
|
formState.firstName.value = "f";
|
|
1161
1227
|
expect(ticks).toEqual(0);
|
|
@@ -1163,9 +1229,9 @@ describe("formState", () => {
|
|
|
1163
1229
|
expect(ticks).toEqual(1);
|
|
1164
1230
|
});
|
|
1165
1231
|
it("can observe value changes on lists", () => {
|
|
1166
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, { books: [{ title: "b1" }] });
|
|
1232
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, { books: [{ title: "b1" }] });
|
|
1167
1233
|
let ticks = 0;
|
|
1168
|
-
mobx_1.reaction(() => formState.books.value, () => ticks++, { equals: () => false });
|
|
1234
|
+
(0, mobx_1.reaction)(() => formState.books.value, () => ticks++, { equals: () => false });
|
|
1169
1235
|
expect(ticks).toEqual(0);
|
|
1170
1236
|
formState.books.rows[0].title.value = "b1";
|
|
1171
1237
|
expect(ticks).toEqual(0);
|
|
@@ -1175,7 +1241,7 @@ describe("formState", () => {
|
|
|
1175
1241
|
expect(ticks).toEqual(2);
|
|
1176
1242
|
});
|
|
1177
1243
|
it("does not override a focused, changed field", () => {
|
|
1178
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1244
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1179
1245
|
// Given first name is focused
|
|
1180
1246
|
formState.firstName.focus();
|
|
1181
1247
|
// And they have wip edits
|
|
@@ -1190,7 +1256,7 @@ describe("formState", () => {
|
|
|
1190
1256
|
expect(formState.firstName.value).toEqual("fff");
|
|
1191
1257
|
});
|
|
1192
1258
|
it("does update a focused, unchanged field", () => {
|
|
1193
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1259
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1194
1260
|
// Given first name is focused, but has not changed
|
|
1195
1261
|
formState.firstName.focus();
|
|
1196
1262
|
// When a mutation result sets both firstName and lastName
|
|
@@ -1199,7 +1265,7 @@ describe("formState", () => {
|
|
|
1199
1265
|
expect(formState.firstName.value).toEqual("f2");
|
|
1200
1266
|
});
|
|
1201
1267
|
it("trims string values on blur", () => {
|
|
1202
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1268
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1203
1269
|
// Given the user is typing with spaces
|
|
1204
1270
|
formState.firstName.focus();
|
|
1205
1271
|
formState.firstName.set("f ");
|
|
@@ -1211,7 +1277,7 @@ describe("formState", () => {
|
|
|
1211
1277
|
expect(formState.firstName.value).toEqual("f");
|
|
1212
1278
|
});
|
|
1213
1279
|
it("trims string values on maybeAutoSave", () => {
|
|
1214
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1280
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1215
1281
|
// Given the user is typing with spaces
|
|
1216
1282
|
formState.firstName.focus();
|
|
1217
1283
|
formState.firstName.set("f ");
|
|
@@ -1225,7 +1291,7 @@ describe("formState", () => {
|
|
|
1225
1291
|
expect(formState.firstName.touched).toEqual(true);
|
|
1226
1292
|
});
|
|
1227
1293
|
it("trims empty values to undefined on blur", () => {
|
|
1228
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1294
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, { firstName: "f", lastName: "l" });
|
|
1229
1295
|
// Given the user is typing with only spaces
|
|
1230
1296
|
formState.firstName.focus();
|
|
1231
1297
|
formState.firstName.set(" ");
|
|
@@ -1243,7 +1309,7 @@ describe("formState", () => {
|
|
|
1243
1309
|
});
|
|
1244
1310
|
it("can work with both required inputs and optional fields", () => {
|
|
1245
1311
|
// And we drop it in a form.
|
|
1246
|
-
const form = objectField_1.createObjectState({
|
|
1312
|
+
const form = (0, objectField_1.createObjectState)({
|
|
1247
1313
|
id: { type: "value" },
|
|
1248
1314
|
firstName: { type: "value" },
|
|
1249
1315
|
}, { id: "a:1" });
|
|
@@ -1264,7 +1330,7 @@ describe("formState", () => {
|
|
|
1264
1330
|
});
|
|
1265
1331
|
it("can have child object states passed in as field states", () => {
|
|
1266
1332
|
// Given an author
|
|
1267
|
-
const a = objectField_1.createObjectState({
|
|
1333
|
+
const a = (0, objectField_1.createObjectState)({
|
|
1268
1334
|
id: { type: "value" },
|
|
1269
1335
|
// And address is modeled as a value object
|
|
1270
1336
|
address: { type: "value" },
|
|
@@ -1281,7 +1347,7 @@ describe("formState", () => {
|
|
|
1281
1347
|
});
|
|
1282
1348
|
it("provides isNewEntity", () => {
|
|
1283
1349
|
// Given an author without an id
|
|
1284
|
-
const formState = objectField_1.createObjectState(authorWithAddressConfig, {
|
|
1350
|
+
const formState = (0, objectField_1.createObjectState)(authorWithAddressConfig, {
|
|
1285
1351
|
firstName: "f",
|
|
1286
1352
|
address: { city: "c1", street: "s1" },
|
|
1287
1353
|
});
|
|
@@ -1296,7 +1362,7 @@ describe("formState", () => {
|
|
|
1296
1362
|
});
|
|
1297
1363
|
it("isNewEntity is false if there is no id field", () => {
|
|
1298
1364
|
// Given an author without an id field defined
|
|
1299
|
-
const formState = objectField_1.createObjectState({
|
|
1365
|
+
const formState = (0, objectField_1.createObjectState)({
|
|
1300
1366
|
firstName: { type: "value" },
|
|
1301
1367
|
address: { type: "object", config: { street: { type: "value" } } },
|
|
1302
1368
|
}, {});
|
|
@@ -1306,7 +1372,7 @@ describe("formState", () => {
|
|
|
1306
1372
|
});
|
|
1307
1373
|
it("provides isNewEntity for lists", () => {
|
|
1308
1374
|
// Given an author & books without an id
|
|
1309
|
-
const formState = objectField_1.createObjectState(authorWithBooksConfig, {
|
|
1375
|
+
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, {
|
|
1310
1376
|
books: [{ title: "t1" }, { title: "t2" }],
|
|
1311
1377
|
});
|
|
1312
1378
|
// Then both books know they are new
|
|
@@ -1365,7 +1431,7 @@ describe("formState", () => {
|
|
|
1365
1431
|
});
|
|
1366
1432
|
it("can optionally ignore the order of list state rows when determining dirty state", () => {
|
|
1367
1433
|
// Given a list state in a specific order, and the `strictOrder` option set to `false`
|
|
1368
|
-
const a = objectField_1.createObjectState({
|
|
1434
|
+
const a = (0, objectField_1.createObjectState)({
|
|
1369
1435
|
books: {
|
|
1370
1436
|
type: "list",
|
|
1371
1437
|
strictOrder: false,
|
|
@@ -1384,14 +1450,14 @@ describe("formState", () => {
|
|
|
1384
1450
|
});
|
|
1385
1451
|
describe("fragments", () => {
|
|
1386
1452
|
it("ignores changes within fragments", () => {
|
|
1387
|
-
const a = objectField_1.createObjectState({ title: { type: "value" }, data: { type: "fragment" } }, { title: "b1", data: objectField_1.fragment({ foo: "1" }) });
|
|
1453
|
+
const a = (0, objectField_1.createObjectState)({ title: { type: "value" }, data: { type: "fragment" } }, { title: "b1", data: (0, objectField_1.fragment)({ foo: "1" }) });
|
|
1388
1454
|
let numCalcs = 0;
|
|
1389
|
-
mobx_1.autorun(() => {
|
|
1455
|
+
(0, mobx_1.autorun)(() => {
|
|
1390
1456
|
numCalcs++;
|
|
1391
1457
|
noop(a.value);
|
|
1392
1458
|
});
|
|
1393
1459
|
expect(a.data.value).toEqual({ foo: "1" });
|
|
1394
|
-
expect(mobx_1.isObservable(a.data.value)).toBe(false);
|
|
1460
|
+
expect((0, mobx_1.isObservable)(a.data.value)).toBe(false);
|
|
1395
1461
|
expect(numCalcs).toEqual(1);
|
|
1396
1462
|
a.data.value = { foo: "2" };
|
|
1397
1463
|
expect(numCalcs).toEqual(2);
|
|
@@ -1399,19 +1465,19 @@ describe("formState", () => {
|
|
|
1399
1465
|
expect(numCalcs).toEqual(2);
|
|
1400
1466
|
});
|
|
1401
1467
|
it("ignores fragments in changedValue", () => {
|
|
1402
|
-
const a = objectField_1.createObjectState({ title: { type: "value" }, data: { type: "fragment" } }, { title: "b1", data: objectField_1.fragment({ foo: "1" }) });
|
|
1468
|
+
const a = (0, objectField_1.createObjectState)({ title: { type: "value" }, data: { type: "fragment" } }, { title: "b1", data: (0, objectField_1.fragment)({ foo: "1" }) });
|
|
1403
1469
|
a.title.value = "b2";
|
|
1404
|
-
a.data.value = objectField_1.fragment({ foo: "2" });
|
|
1470
|
+
a.data.value = (0, objectField_1.fragment)({ foo: "2" });
|
|
1405
1471
|
expect(a.changedValue).toMatchInlineSnapshot(`
|
|
1406
|
-
|
|
1472
|
+
{
|
|
1407
1473
|
"title": "b2",
|
|
1408
1474
|
}
|
|
1409
1475
|
`);
|
|
1410
1476
|
});
|
|
1411
1477
|
it("ignores fragments in value", () => {
|
|
1412
|
-
const a = objectField_1.createObjectState({ title: { type: "value" }, data: { type: "fragment" } }, { title: "b1", data: objectField_1.fragment({ foo: "1" }) });
|
|
1478
|
+
const a = (0, objectField_1.createObjectState)({ title: { type: "value" }, data: { type: "fragment" } }, { title: "b1", data: (0, objectField_1.fragment)({ foo: "1" }) });
|
|
1413
1479
|
expect(a.value).toMatchInlineSnapshot(`
|
|
1414
|
-
|
|
1480
|
+
{
|
|
1415
1481
|
"title": "b1",
|
|
1416
1482
|
}
|
|
1417
1483
|
`);
|
|
@@ -1419,7 +1485,7 @@ describe("formState", () => {
|
|
|
1419
1485
|
});
|
|
1420
1486
|
it("sets id key correctly", () => {
|
|
1421
1487
|
// Given an author
|
|
1422
|
-
const a = objectField_1.createObjectState({
|
|
1488
|
+
const a = (0, objectField_1.createObjectState)({
|
|
1423
1489
|
id: { type: "value" },
|
|
1424
1490
|
otherId: { type: "value", isIdKey: true },
|
|
1425
1491
|
}, {});
|
|
@@ -1431,7 +1497,8 @@ class ObservableObject {
|
|
|
1431
1497
|
constructor() {
|
|
1432
1498
|
this.firstName = "first";
|
|
1433
1499
|
this.lastName = "last";
|
|
1434
|
-
|
|
1500
|
+
this.age = undefined;
|
|
1501
|
+
(0, mobx_1.makeAutoObservable)(this);
|
|
1435
1502
|
}
|
|
1436
1503
|
get fullName() {
|
|
1437
1504
|
return `${this.firstName} ${this.lastName}`;
|
|
@@ -1459,7 +1526,7 @@ const authorWithBooksConfig = {
|
|
|
1459
1526
|
},
|
|
1460
1527
|
};
|
|
1461
1528
|
function createAuthorInputState(input, maybeAutoSave) {
|
|
1462
|
-
return objectField_1.createObjectState(authorWithBooksConfig, input, { maybeAutoSave });
|
|
1529
|
+
return (0, objectField_1.createObjectState)(authorWithBooksConfig, input, { maybeAutoSave });
|
|
1463
1530
|
}
|
|
1464
1531
|
const authorWithAddressConfig = {
|
|
1465
1532
|
id: { type: "value" },
|
|
@@ -1495,6 +1562,6 @@ const authorWithAddressAndBooksConfig = {
|
|
|
1495
1562
|
},
|
|
1496
1563
|
};
|
|
1497
1564
|
function createAuthorWithAddressInputState(input) {
|
|
1498
|
-
return objectField_1.createObjectState(authorWithAddressConfig, input);
|
|
1565
|
+
return (0, objectField_1.createObjectState)(authorWithAddressConfig, input);
|
|
1499
1566
|
}
|
|
1500
1567
|
function noop(t) { }
|