@inglorious/web 3.0.0 → 3.0.1
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/README.md +21 -15
- package/package.json +7 -4
- package/src/form/form.test.js +0 -372
- package/src/list/list.test.js +0 -228
- package/src/router/router.test.js +0 -208
- package/src/select/select.test.js +0 -415
- package/src/table/table.test.js +0 -393
package/README.md
CHANGED
|
@@ -371,7 +371,8 @@ To enable the router, add it to your store's types and create a `router` entity.
|
|
|
371
371
|
|
|
372
372
|
```javascript
|
|
373
373
|
// store.js
|
|
374
|
-
import { createStore, html
|
|
374
|
+
import { createStore, html } from "@inglorious/web"
|
|
375
|
+
import { router } from "@inglorious/web/router"
|
|
375
376
|
|
|
376
377
|
const types = {
|
|
377
378
|
// 1. Add the router type to your store's types
|
|
@@ -520,7 +521,8 @@ export const requireAuth = (type) => ({
|
|
|
520
521
|
|
|
521
522
|
```javascript
|
|
522
523
|
// store.js
|
|
523
|
-
import { createStore
|
|
524
|
+
import { createStore } from "@inglorious/web"
|
|
525
|
+
import { router } from "@inglorious/web/router"
|
|
524
526
|
import { requireAuth } from "./guards/require-auth.js"
|
|
525
527
|
import { adminPage } from "./pages/admin.js"
|
|
526
528
|
import { loginPage } from "./pages/login.js"
|
|
@@ -646,7 +648,7 @@ To use it, import the `table` type and its CSS, then create an entity for your t
|
|
|
646
648
|
|
|
647
649
|
```javascript
|
|
648
650
|
// In your entity definition file
|
|
649
|
-
import { table } from "@inglorious/web"
|
|
651
|
+
import { table } from "@inglorious/web/table"
|
|
650
652
|
|
|
651
653
|
// Import base styles and a theme. You can create your own theme.
|
|
652
654
|
import "@inglorious/web/table/base.css"
|
|
@@ -673,7 +675,7 @@ You can customize how data is rendered in the table cells by overriding the `ren
|
|
|
673
675
|
The example below from `examples/apps/web-table/src/product-table/product-table.js` shows how to format values based on a `formatter` property in the column definition.
|
|
674
676
|
|
|
675
677
|
```javascript
|
|
676
|
-
import { table } from "@inglorious/web"
|
|
678
|
+
import { table } from "@inglorious/web/table"
|
|
677
679
|
import { format } from "date-fns"
|
|
678
680
|
|
|
679
681
|
const formatters = {
|
|
@@ -705,7 +707,8 @@ The table comes with a base stylesheet (`@inglorious/web/table/base.css`) and a
|
|
|
705
707
|
Import the `select` type and its CSS, then create an entity.
|
|
706
708
|
|
|
707
709
|
```javascript
|
|
708
|
-
import { createStore
|
|
710
|
+
import { createStore } from "@inglorious/web"
|
|
711
|
+
import { select } from "@inglorious/web/select"
|
|
709
712
|
// Import base styles and theme
|
|
710
713
|
import "@inglorious/web/select/base.css"
|
|
711
714
|
import "@inglorious/web/select/theme.css"
|
|
@@ -765,7 +768,8 @@ It listens to internal events like `#<id>:toggle`, `#<id>:optionSelect`, etc. Yo
|
|
|
765
768
|
Include `form` in your `types` and create an entity for the form (use any id you like — `form` is used below for clarity):
|
|
766
769
|
|
|
767
770
|
```javascript
|
|
768
|
-
import { createStore
|
|
771
|
+
import { createStore } from "@inglorious/web"
|
|
772
|
+
import { form } from "@inglorious/web/form"
|
|
769
773
|
|
|
770
774
|
const types = { form }
|
|
771
775
|
|
|
@@ -866,7 +870,8 @@ It also expects the item type to export `renderItem(item, index, api)` so each v
|
|
|
866
870
|
Minimal example showing how to extend the `list` type to create a domain-specific list (e.g. `productList`) and provide a `renderItem(item, index, api)` helper.
|
|
867
871
|
|
|
868
872
|
```javascript
|
|
869
|
-
import { createStore, html
|
|
873
|
+
import { createStore, html } from "@inglorious/web"
|
|
874
|
+
import { list } from "@inglorious/web/list"
|
|
870
875
|
|
|
871
876
|
// Extend the built-in list type to render product items
|
|
872
877
|
const productList = {
|
|
@@ -952,18 +957,19 @@ import {
|
|
|
952
957
|
styleMap,
|
|
953
958
|
unsafeHTML,
|
|
954
959
|
when,
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
// form stuff
|
|
960
|
+
} from "@inglorious/web"
|
|
961
|
+
|
|
962
|
+
// Subpath imports for tree-shaking
|
|
963
|
+
import {
|
|
960
964
|
form,
|
|
961
965
|
getFieldError,
|
|
962
966
|
getFieldValue,
|
|
963
967
|
isFieldTouched,
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
} from "@inglorious/web"
|
|
968
|
+
} from "@inglorious/web/form"
|
|
969
|
+
import { list } from "@inglorious/web/list"
|
|
970
|
+
import { router } from "@inglorious/web/router"
|
|
971
|
+
import { select } from "@inglorious/web/select"
|
|
972
|
+
import { table } from "@inglorious/web/table"
|
|
967
973
|
```
|
|
968
974
|
|
|
969
975
|
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/web",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "A new web framework that leverages the power of the Inglorious Store combined with the performance and simplicity of lit-html.",
|
|
5
5
|
"author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,16 +53,19 @@
|
|
|
53
53
|
},
|
|
54
54
|
"files": [
|
|
55
55
|
"src",
|
|
56
|
+
"!src/**/*.test.js",
|
|
56
57
|
"types"
|
|
57
58
|
],
|
|
58
59
|
"publishConfig": {
|
|
59
60
|
"access": "public"
|
|
60
61
|
},
|
|
61
|
-
"sideEffects":
|
|
62
|
+
"sideEffects": [
|
|
63
|
+
"**/*.css"
|
|
64
|
+
],
|
|
62
65
|
"dependencies": {
|
|
63
66
|
"lit-html": "^3.3.1",
|
|
64
|
-
"@inglorious/
|
|
65
|
-
"@inglorious/
|
|
67
|
+
"@inglorious/store": "8.0.1",
|
|
68
|
+
"@inglorious/utils": "3.7.1"
|
|
66
69
|
},
|
|
67
70
|
"devDependencies": {
|
|
68
71
|
"prettier": "^3.6.2",
|
package/src/form/form.test.js
DELETED
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @vitest-environment jsdom
|
|
3
|
-
*/
|
|
4
|
-
import { beforeEach, describe, expect, it, vi } from "vitest"
|
|
5
|
-
|
|
6
|
-
import { form, getFieldError, getFieldValue, isFieldTouched } from "."
|
|
7
|
-
|
|
8
|
-
describe("form", () => {
|
|
9
|
-
let entity
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
entity = {
|
|
13
|
-
id: "test-form",
|
|
14
|
-
initialValues: {
|
|
15
|
-
name: "John Doe",
|
|
16
|
-
contact: {
|
|
17
|
-
email: "john.doe@example.com",
|
|
18
|
-
},
|
|
19
|
-
tags: ["a", "b"],
|
|
20
|
-
},
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
describe("init()", () => {
|
|
25
|
-
it("should add global event listeners for click and submit", () => {
|
|
26
|
-
const spy = vi.spyOn(document, "addEventListener")
|
|
27
|
-
form.init(entity)
|
|
28
|
-
expect(spy).toHaveBeenCalledWith("click", expect.any(Function))
|
|
29
|
-
expect(spy).toHaveBeenCalledWith("submit", expect.any(Function))
|
|
30
|
-
spy.mockRestore()
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
describe("create()", () => {
|
|
35
|
-
it("should initialize the form", () => {
|
|
36
|
-
entity.values = {}
|
|
37
|
-
form.create(entity)
|
|
38
|
-
expect(entity.values).toEqual(entity.initialValues)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it("should reset the form to its initial state", () => {
|
|
42
|
-
// mess up the state first
|
|
43
|
-
entity.values = {}
|
|
44
|
-
entity.isPristine = false
|
|
45
|
-
|
|
46
|
-
form.create(entity)
|
|
47
|
-
|
|
48
|
-
expect(entity.values).toEqual(entity.initialValues)
|
|
49
|
-
expect(entity.values).not.toBe(entity.initialValues) // should be a clone
|
|
50
|
-
expect(entity.isPristine).toBe(true)
|
|
51
|
-
expect(entity.isValid).toBe(true)
|
|
52
|
-
expect(entity.errors).toEqual({
|
|
53
|
-
name: null,
|
|
54
|
-
contact: { email: null },
|
|
55
|
-
tags: [null, null],
|
|
56
|
-
})
|
|
57
|
-
expect(entity.touched).toEqual({
|
|
58
|
-
name: null,
|
|
59
|
-
contact: { email: null },
|
|
60
|
-
tags: [null, null],
|
|
61
|
-
})
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
describe("reset()", () => {
|
|
66
|
-
it("should reset the form to its initial state", () => {
|
|
67
|
-
form.create(entity)
|
|
68
|
-
entity.values.name = "Jane Doe"
|
|
69
|
-
entity.isPristine = false
|
|
70
|
-
|
|
71
|
-
form.reset(entity)
|
|
72
|
-
|
|
73
|
-
expect(entity.values).toEqual(entity.initialValues)
|
|
74
|
-
expect(entity.isPristine).toBe(true)
|
|
75
|
-
})
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
describe("fieldChange()", () => {
|
|
79
|
-
beforeEach(() => {
|
|
80
|
-
form.create(entity)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it("should update a field's value, mark it as touched, and set form to dirty", () => {
|
|
84
|
-
form.fieldChange(entity, { path: "name", value: "Jane Doe" })
|
|
85
|
-
|
|
86
|
-
expect(entity.values.name).toBe("Jane Doe")
|
|
87
|
-
expect(entity.touched.name).toBe(true)
|
|
88
|
-
expect(entity.isPristine).toBe(false)
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
it("should update a nested field's value", () => {
|
|
92
|
-
form.fieldChange(entity, {
|
|
93
|
-
path: "contact.email",
|
|
94
|
-
value: "jane.doe@example.com",
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
expect(entity.values.contact.email).toBe("jane.doe@example.com")
|
|
98
|
-
expect(entity.touched.contact.email).toBe(true)
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it("should validate the field if a validate function is provided", () => {
|
|
102
|
-
const validate = (value) => (value.length < 10 ? "Too short" : null)
|
|
103
|
-
form.fieldChange(entity, { path: "name", value: "Jane", validate })
|
|
104
|
-
|
|
105
|
-
expect(entity.errors.name).toBe("Too short")
|
|
106
|
-
expect(entity.isValid).toBe(false)
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it("should clear a field's error when it becomes valid", () => {
|
|
110
|
-
const validate = (value) => (value.length < 10 ? "Too short" : null)
|
|
111
|
-
form.fieldChange(entity, { path: "name", value: "Jane", validate })
|
|
112
|
-
expect(entity.isValid).toBe(false)
|
|
113
|
-
|
|
114
|
-
form.fieldChange(entity, {
|
|
115
|
-
path: "name",
|
|
116
|
-
value: "Jane Doe The Great",
|
|
117
|
-
validate,
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
expect(entity.errors.name).toBe(null)
|
|
121
|
-
expect(entity.isValid).toBe(true)
|
|
122
|
-
})
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
describe("fieldBlur()", () => {
|
|
126
|
-
beforeEach(() => {
|
|
127
|
-
form.create(entity)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it("should mark a field as touched", () => {
|
|
131
|
-
form.fieldBlur(entity, { path: "name" })
|
|
132
|
-
expect(entity.touched.name).toBe(true)
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
it("should validate the field if a validate function is provided", () => {
|
|
136
|
-
const validate = (value) =>
|
|
137
|
-
value === "John Doe" ? "Cannot be John" : null
|
|
138
|
-
form.fieldBlur(entity, { path: "name", validate })
|
|
139
|
-
|
|
140
|
-
expect(entity.errors.name).toBe("Cannot be John")
|
|
141
|
-
expect(entity.isValid).toBe(false)
|
|
142
|
-
})
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
describe("field array operations", () => {
|
|
146
|
-
beforeEach(() => {
|
|
147
|
-
form.create(entity)
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
it("fieldArrayAppend: should append a value and metadata", () => {
|
|
151
|
-
form.fieldArrayAppend(entity, { path: "tags", value: "c" })
|
|
152
|
-
|
|
153
|
-
expect(entity.values.tags).toEqual(["a", "b", "c"])
|
|
154
|
-
expect(entity.errors.tags).toEqual([null, null, null])
|
|
155
|
-
expect(entity.touched.tags).toEqual([null, null, null])
|
|
156
|
-
expect(entity.isPristine).toBe(false)
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
it("fieldArrayRemove: should remove a value and metadata at an index", () => {
|
|
160
|
-
form.fieldArrayRemove(entity, { path: "tags", index: 0 })
|
|
161
|
-
|
|
162
|
-
expect(entity.values.tags).toEqual(["b"])
|
|
163
|
-
expect(entity.errors.tags).toEqual([null])
|
|
164
|
-
expect(entity.touched.tags).toEqual([null])
|
|
165
|
-
expect(entity.isPristine).toBe(false)
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
it("fieldArrayInsert: should insert a value and metadata at an index", () => {
|
|
169
|
-
form.fieldArrayInsert(entity, { path: "tags", index: 1, value: "c" })
|
|
170
|
-
|
|
171
|
-
expect(entity.values.tags).toEqual(["a", "c", "b"])
|
|
172
|
-
expect(entity.errors.tags).toEqual([null, null, null])
|
|
173
|
-
expect(entity.touched.tags).toEqual([null, null, null])
|
|
174
|
-
expect(entity.isPristine).toBe(false)
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it("fieldArrayMove: should move a value and metadata", () => {
|
|
178
|
-
entity.errors.tags[0] = "Error on A"
|
|
179
|
-
entity.touched.tags[0] = true
|
|
180
|
-
|
|
181
|
-
form.fieldArrayMove(entity, { path: "tags", fromIndex: 0, toIndex: 1 })
|
|
182
|
-
|
|
183
|
-
expect(entity.values.tags).toEqual(["b", "a"])
|
|
184
|
-
expect(entity.errors.tags).toEqual([null, "Error on A"])
|
|
185
|
-
expect(entity.touched.tags).toEqual([null, true])
|
|
186
|
-
expect(entity.isPristine).toBe(false)
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
it("fieldArray operations should warn if path is not an array", () => {
|
|
190
|
-
const spy = vi.spyOn(console, "warn").mockImplementation(() => {})
|
|
191
|
-
|
|
192
|
-
form.fieldArrayAppend(entity, { path: "name", value: "c" })
|
|
193
|
-
expect(spy).toHaveBeenCalledWith("Field at path 'name' is not an array")
|
|
194
|
-
|
|
195
|
-
spy.mockRestore()
|
|
196
|
-
})
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
describe("validate()", () => {
|
|
200
|
-
beforeEach(() => {
|
|
201
|
-
form.create(entity)
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
it("should set errors and isValid based on the validation function", () => {
|
|
205
|
-
const validate = (values) => {
|
|
206
|
-
const errors = {}
|
|
207
|
-
if (values.name !== "Jane Doe") {
|
|
208
|
-
errors.name = "Name must be Jane Doe"
|
|
209
|
-
}
|
|
210
|
-
return errors
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
form.validate(entity, { validate })
|
|
214
|
-
|
|
215
|
-
expect(entity.errors.name).toBe("Name must be Jane Doe")
|
|
216
|
-
expect(entity.isValid).toBe(false)
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
it("should set isValid to true if there are no errors", () => {
|
|
220
|
-
const validate = () => ({})
|
|
221
|
-
|
|
222
|
-
entity.isValid = false
|
|
223
|
-
form.validate(entity, { validate })
|
|
224
|
-
|
|
225
|
-
expect(entity.errors).toEqual({})
|
|
226
|
-
expect(entity.isValid).toBe(true)
|
|
227
|
-
})
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
describe("validateAsync()", () => {
|
|
231
|
-
let api
|
|
232
|
-
|
|
233
|
-
beforeEach(() => {
|
|
234
|
-
form.create(entity)
|
|
235
|
-
api = { notify: vi.fn() }
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
it("should set isValidating to true and call the validation function", async () => {
|
|
239
|
-
const validate = vi.fn().mockResolvedValue({})
|
|
240
|
-
await form.validateAsync(entity, { validate }, api)
|
|
241
|
-
expect(entity.isValidating).toBe(true)
|
|
242
|
-
expect(validate).toHaveBeenCalledWith(entity.values)
|
|
243
|
-
})
|
|
244
|
-
|
|
245
|
-
it("should notify 'validationComplete' on successful validation", async () => {
|
|
246
|
-
const errors = { name: "Required" }
|
|
247
|
-
const validate = async () => errors
|
|
248
|
-
await form.validateAsync(entity, { validate }, api)
|
|
249
|
-
|
|
250
|
-
expect(api.notify).toHaveBeenCalledWith(
|
|
251
|
-
`#${entity.id}:validationComplete`,
|
|
252
|
-
{
|
|
253
|
-
errors,
|
|
254
|
-
isValid: false,
|
|
255
|
-
},
|
|
256
|
-
)
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
it("should notify 'validationError' on validation failure", async () => {
|
|
260
|
-
const error = new Error("Validation failed")
|
|
261
|
-
const validate = async () => {
|
|
262
|
-
throw error
|
|
263
|
-
}
|
|
264
|
-
await form.validateAsync(entity, { validate }, api)
|
|
265
|
-
|
|
266
|
-
expect(api.notify).toHaveBeenCalledWith(`#${entity.id}:validationError`, {
|
|
267
|
-
error: "Validation failed",
|
|
268
|
-
})
|
|
269
|
-
})
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
describe("validationComplete()", () => {
|
|
273
|
-
it("should update form state after async validation", () => {
|
|
274
|
-
form.create(entity)
|
|
275
|
-
entity.isValidating = true
|
|
276
|
-
const errors = { name: "Error" }
|
|
277
|
-
|
|
278
|
-
form.validationComplete(entity, { errors, isValid: false })
|
|
279
|
-
|
|
280
|
-
expect(entity.isValidating).toBe(false)
|
|
281
|
-
expect(entity.errors).toBe(errors)
|
|
282
|
-
expect(entity.isValid).toBe(false)
|
|
283
|
-
})
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
describe("validationError()", () => {
|
|
287
|
-
it("should update form state after an async validation error", () => {
|
|
288
|
-
form.create(entity)
|
|
289
|
-
entity.isValidating = true
|
|
290
|
-
|
|
291
|
-
form.validationError(entity, { error: "Network Error" })
|
|
292
|
-
|
|
293
|
-
expect(entity.isValidating).toBe(false)
|
|
294
|
-
expect(entity.submitError).toBe("Network Error")
|
|
295
|
-
})
|
|
296
|
-
})
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
describe("form helpers", () => {
|
|
300
|
-
let testForm
|
|
301
|
-
|
|
302
|
-
beforeEach(() => {
|
|
303
|
-
testForm = {
|
|
304
|
-
values: {
|
|
305
|
-
user: { name: "Alex" },
|
|
306
|
-
tags: ["one", "two"],
|
|
307
|
-
},
|
|
308
|
-
errors: {
|
|
309
|
-
user: { name: "Too short" },
|
|
310
|
-
tags: [null, "Invalid tag"],
|
|
311
|
-
},
|
|
312
|
-
touched: {
|
|
313
|
-
user: { name: true },
|
|
314
|
-
tags: [true, false],
|
|
315
|
-
},
|
|
316
|
-
}
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
describe("getFieldValue()", () => {
|
|
320
|
-
it("should return the value of a field at a given path", () => {
|
|
321
|
-
expect(getFieldValue(testForm, "user.name")).toBe("Alex")
|
|
322
|
-
})
|
|
323
|
-
|
|
324
|
-
it("should return an array value", () => {
|
|
325
|
-
expect(getFieldValue(testForm, "tags")).toEqual(["one", "two"])
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
it("should return a default value if path does not exist", () => {
|
|
329
|
-
expect(getFieldValue(testForm, "user.age", 30)).toBe(30)
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
it("should return undefined if path does not exist and no default is provided", () => {
|
|
333
|
-
expect(getFieldValue(testForm, "user.age")).toBeUndefined()
|
|
334
|
-
})
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
describe("getFieldError()", () => {
|
|
338
|
-
it("should return the error of a field at a given path", () => {
|
|
339
|
-
expect(getFieldError(testForm, "user.name")).toBe("Too short")
|
|
340
|
-
})
|
|
341
|
-
|
|
342
|
-
it("should return the error of a field in an array", () => {
|
|
343
|
-
expect(getFieldError(testForm, "tags.1")).toBe("Invalid tag")
|
|
344
|
-
})
|
|
345
|
-
|
|
346
|
-
it("should return null for a valid field in an array", () => {
|
|
347
|
-
expect(getFieldError(testForm, "tags.0")).toBeNull()
|
|
348
|
-
})
|
|
349
|
-
|
|
350
|
-
it("should return undefined if path does not exist", () => {
|
|
351
|
-
expect(getFieldError(testForm, "user.age")).toBe(undefined)
|
|
352
|
-
})
|
|
353
|
-
})
|
|
354
|
-
|
|
355
|
-
describe("isFieldTouched()", () => {
|
|
356
|
-
it("should return true if a field has been touched", () => {
|
|
357
|
-
expect(isFieldTouched(testForm, "user.name")).toBe(true)
|
|
358
|
-
})
|
|
359
|
-
|
|
360
|
-
it("should return true for a touched field in an array", () => {
|
|
361
|
-
expect(isFieldTouched(testForm, "tags.0")).toBe(true)
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
it("should return false for an untouched field in an array", () => {
|
|
365
|
-
expect(isFieldTouched(testForm, "tags.1")).toBe(false)
|
|
366
|
-
})
|
|
367
|
-
|
|
368
|
-
it("should return false if path does not exist", () => {
|
|
369
|
-
expect(isFieldTouched(testForm, "user.age")).toBe(false)
|
|
370
|
-
})
|
|
371
|
-
})
|
|
372
|
-
})
|