@teamnovu/kit-vue-forms 0.1.22 → 0.1.24
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/composables/useFieldArray.d.ts +1 -1
- package/dist/index.js +217 -212
- package/dist/types/form.d.ts +12 -11
- package/package.json +1 -1
- package/src/composables/useFieldArray.ts +47 -19
- package/src/types/form.ts +13 -11
- package/tests/useFieldArray.test.ts +237 -268
|
@@ -1,297 +1,185 @@
|
|
|
1
|
-
import { describe, expect, it } from
|
|
2
|
-
import { nextTick } from
|
|
3
|
-
import { useForm } from
|
|
4
|
-
import { HashStore, useFieldArray } from
|
|
5
|
-
|
|
6
|
-
describe(
|
|
7
|
-
describe(
|
|
8
|
-
it(
|
|
9
|
-
const store = new HashStore<string[]>()
|
|
10
|
-
|
|
11
|
-
store.set(5, [
|
|
12
|
-
expect(store.has(5)).toBe(true)
|
|
13
|
-
expect(store.get(5)).toEqual([
|
|
14
|
-
|
|
15
|
-
store.set(10, [
|
|
16
|
-
expect(store.get(10)).toEqual([
|
|
17
|
-
expect(store.get(5)).toEqual([
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it(
|
|
21
|
-
const store = new HashStore<string[]>()
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { nextTick } from "vue";
|
|
3
|
+
import { useForm } from "../src/composables/useForm";
|
|
4
|
+
import { HashStore, useFieldArray } from "../src/composables/useFieldArray";
|
|
5
|
+
|
|
6
|
+
describe("useFieldArray", () => {
|
|
7
|
+
describe("HashStore", () => {
|
|
8
|
+
it("should store and retrieve primitive values with identity hash", () => {
|
|
9
|
+
const store = new HashStore<string[]>();
|
|
10
|
+
|
|
11
|
+
store.set(5, ["id-1"]);
|
|
12
|
+
expect(store.has(5)).toBe(true);
|
|
13
|
+
expect(store.get(5)).toEqual(["id-1"]);
|
|
14
|
+
|
|
15
|
+
store.set(10, ["id-2"]);
|
|
16
|
+
expect(store.get(10)).toEqual(["id-2"]);
|
|
17
|
+
expect(store.get(5)).toEqual(["id-1"]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should store objects by reference with identity hash", () => {
|
|
21
|
+
const store = new HashStore<string[]>();
|
|
22
22
|
const obj1 = {
|
|
23
23
|
id: 1,
|
|
24
|
-
name:
|
|
25
|
-
}
|
|
24
|
+
name: "A",
|
|
25
|
+
};
|
|
26
26
|
const obj2 = {
|
|
27
27
|
id: 1,
|
|
28
|
-
name:
|
|
29
|
-
} // Same content, different reference
|
|
28
|
+
name: "A",
|
|
29
|
+
}; // Same content, different reference
|
|
30
30
|
|
|
31
|
-
store.set(obj1, [
|
|
31
|
+
store.set(obj1, ["uuid-1"]);
|
|
32
32
|
|
|
33
|
-
expect(store.has(obj1)).toBe(true)
|
|
34
|
-
expect(store.has(obj2)).toBe(false)
|
|
35
|
-
expect(store.get(obj1)).toEqual([
|
|
36
|
-
expect(store.get(obj2)).toBeUndefined()
|
|
37
|
-
})
|
|
33
|
+
expect(store.has(obj1)).toBe(true);
|
|
34
|
+
expect(store.has(obj2)).toBe(false);
|
|
35
|
+
expect(store.get(obj1)).toEqual(["uuid-1"]);
|
|
36
|
+
expect(store.get(obj2)).toBeUndefined();
|
|
37
|
+
});
|
|
38
38
|
|
|
39
|
-
it(
|
|
40
|
-
const store = new HashStore<string[], { id: number }>(item => item.id)
|
|
39
|
+
it("should use custom hash function for semantic equality", () => {
|
|
40
|
+
const store = new HashStore<string[], { id: number }>((item) => item.id);
|
|
41
41
|
const obj1 = {
|
|
42
42
|
id: 1,
|
|
43
|
-
name:
|
|
44
|
-
}
|
|
43
|
+
name: "A",
|
|
44
|
+
};
|
|
45
45
|
const obj2 = {
|
|
46
46
|
id: 1,
|
|
47
|
-
name:
|
|
48
|
-
} // Same ID, different name
|
|
47
|
+
name: "B",
|
|
48
|
+
}; // Same ID, different name
|
|
49
49
|
const obj3 = {
|
|
50
50
|
id: 2,
|
|
51
|
-
name:
|
|
52
|
-
}
|
|
51
|
+
name: "A",
|
|
52
|
+
};
|
|
53
53
|
|
|
54
|
-
store.set(obj1, [
|
|
54
|
+
store.set(obj1, ["uuid-1"]);
|
|
55
55
|
|
|
56
|
-
expect(store.has(obj2)).toBe(true)
|
|
57
|
-
expect(store.get(obj2)).toEqual([
|
|
58
|
-
expect(store.has(obj3)).toBe(false)
|
|
59
|
-
})
|
|
56
|
+
expect(store.has(obj2)).toBe(true);
|
|
57
|
+
expect(store.get(obj2)).toEqual(["uuid-1"]);
|
|
58
|
+
expect(store.has(obj3)).toBe(false);
|
|
59
|
+
});
|
|
60
60
|
|
|
61
|
-
it(
|
|
62
|
-
const store = new HashStore<string[]>()
|
|
63
|
-
const item = { id: 1 }
|
|
61
|
+
it("should overwrite value on subsequent set calls", () => {
|
|
62
|
+
const store = new HashStore<string[]>();
|
|
63
|
+
const item = { id: 1 };
|
|
64
64
|
|
|
65
|
-
store.set(item, [
|
|
66
|
-
expect(store.get(item)).toEqual([
|
|
65
|
+
store.set(item, ["id-1"]);
|
|
66
|
+
expect(store.get(item)).toEqual(["id-1"]);
|
|
67
67
|
|
|
68
|
-
store.set(item, [
|
|
69
|
-
expect(store.get(item)).toEqual([
|
|
70
|
-
})
|
|
71
|
-
})
|
|
68
|
+
store.set(item, ["id-1", "id-2"]);
|
|
69
|
+
expect(store.get(item)).toEqual(["id-1", "id-2"]);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
72
|
|
|
73
|
-
describe(
|
|
74
|
-
it(
|
|
73
|
+
describe("ID Persistence", () => {
|
|
74
|
+
it("should maintain IDs when items are reordered", async () => {
|
|
75
75
|
const form = useForm({
|
|
76
76
|
initialData: {
|
|
77
77
|
items: [
|
|
78
78
|
{
|
|
79
79
|
id: 1,
|
|
80
|
-
name:
|
|
80
|
+
name: "First",
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
id: 2,
|
|
84
|
-
name:
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
},
|
|
88
|
-
})
|
|
89
|
-
const fieldArray = useFieldArray(form, 'items')
|
|
90
|
-
|
|
91
|
-
expect(fieldArray.fields.value).toHaveLength(2)
|
|
92
|
-
expect(fieldArray.fields.value[0]).toHaveProperty('id')
|
|
93
|
-
expect(fieldArray.fields.value[0]).toHaveProperty('item')
|
|
94
|
-
expect(fieldArray.fields.value[0].item).toEqual({
|
|
95
|
-
id: 1,
|
|
96
|
-
name: 'Item 1',
|
|
97
|
-
})
|
|
98
|
-
expect(typeof fieldArray.fields.value[0].id).toBe('string')
|
|
99
|
-
expect(fieldArray.errors.value).toEqual([])
|
|
100
|
-
expect(fieldArray.dirty.value).toBe(false)
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('should push new items to the array', async () => {
|
|
104
|
-
const form = useForm({
|
|
105
|
-
initialData: {
|
|
106
|
-
items: [
|
|
107
|
-
{
|
|
108
|
-
id: 1,
|
|
109
|
-
name: 'First',
|
|
110
|
-
},
|
|
111
|
-
],
|
|
112
|
-
},
|
|
113
|
-
})
|
|
114
|
-
const fieldArray = useFieldArray(form, 'items')
|
|
115
|
-
|
|
116
|
-
expect(fieldArray.fields.value).toHaveLength(1)
|
|
117
|
-
|
|
118
|
-
fieldArray.push({
|
|
119
|
-
id: 2,
|
|
120
|
-
name: 'Second',
|
|
121
|
-
})
|
|
122
|
-
await nextTick()
|
|
123
|
-
|
|
124
|
-
expect(fieldArray.fields.value).toHaveLength(2)
|
|
125
|
-
expect(fieldArray.fields.value[1].item).toEqual({
|
|
126
|
-
id: 2,
|
|
127
|
-
name: 'Second',
|
|
128
|
-
})
|
|
129
|
-
expect(fieldArray.dirty.value).toBe(true)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
it('should remove item by reference', async () => {
|
|
133
|
-
const form = useForm({
|
|
134
|
-
initialData: {
|
|
135
|
-
items: [
|
|
136
|
-
{
|
|
137
|
-
id: 1,
|
|
138
|
-
name: 'Keep',
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
id: 2,
|
|
142
|
-
name: 'Remove',
|
|
143
|
-
},
|
|
144
|
-
],
|
|
145
|
-
},
|
|
146
|
-
})
|
|
147
|
-
const fieldArray = useFieldArray(form, 'items')
|
|
148
|
-
const itemToRemove = fieldArray.fields.value[1].item
|
|
149
|
-
|
|
150
|
-
fieldArray.remove(itemToRemove)
|
|
151
|
-
await nextTick()
|
|
152
|
-
|
|
153
|
-
expect(fieldArray.fields.value).toHaveLength(1)
|
|
154
|
-
expect(fieldArray.fields.value[0].item.name).toBe('Keep')
|
|
155
|
-
expect(fieldArray.dirty.value).toBe(true)
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
it('should remove item by index', async () => {
|
|
159
|
-
const form = useForm({
|
|
160
|
-
initialData: {
|
|
161
|
-
items: [
|
|
162
|
-
{
|
|
163
|
-
id: 1,
|
|
164
|
-
name: 'First',
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
id: 2,
|
|
168
|
-
name: 'Second',
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
id: 3,
|
|
172
|
-
name: 'Third',
|
|
173
|
-
},
|
|
174
|
-
],
|
|
175
|
-
},
|
|
176
|
-
})
|
|
177
|
-
const fieldArray = useFieldArray(form, 'items')
|
|
178
|
-
|
|
179
|
-
fieldArray.removeByIndex(1)
|
|
180
|
-
await nextTick()
|
|
181
|
-
|
|
182
|
-
expect(fieldArray.fields.value).toHaveLength(2)
|
|
183
|
-
expect(fieldArray.fields.value[0].item.name).toBe('First')
|
|
184
|
-
expect(fieldArray.fields.value[1].item.name).toBe('Third')
|
|
185
|
-
})
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
describe('ID Persistence', () => {
|
|
189
|
-
it('should maintain IDs when items are reordered', async () => {
|
|
190
|
-
const form = useForm({
|
|
191
|
-
initialData: {
|
|
192
|
-
items: [
|
|
193
|
-
{
|
|
194
|
-
id: 1,
|
|
195
|
-
name: 'First',
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
id: 2,
|
|
199
|
-
name: 'Second',
|
|
84
|
+
name: "Second",
|
|
200
85
|
},
|
|
201
86
|
{
|
|
202
87
|
id: 3,
|
|
203
|
-
name:
|
|
88
|
+
name: "Third",
|
|
204
89
|
},
|
|
205
90
|
],
|
|
206
91
|
},
|
|
207
|
-
})
|
|
208
|
-
const fieldArray = useFieldArray(form,
|
|
92
|
+
});
|
|
93
|
+
const fieldArray = useFieldArray(form, "items", {
|
|
209
94
|
hashFn: (item: { id: number }) => item.id,
|
|
210
|
-
})
|
|
95
|
+
});
|
|
211
96
|
|
|
212
97
|
// Capture initial IDs
|
|
213
|
-
const id1 = fieldArray.
|
|
214
|
-
const id2 = fieldArray.
|
|
215
|
-
const id3 = fieldArray.
|
|
98
|
+
const id1 = fieldArray.items.value[0].id;
|
|
99
|
+
const id2 = fieldArray.items.value[1].id;
|
|
100
|
+
const id3 = fieldArray.items.value[2].id;
|
|
216
101
|
|
|
217
102
|
// Reverse the array
|
|
218
|
-
const arrayField = form.getField(
|
|
219
|
-
arrayField.setData([...arrayField.data.value].reverse())
|
|
220
|
-
await nextTick()
|
|
103
|
+
const arrayField = form.getField("items");
|
|
104
|
+
arrayField.setData([...arrayField.data.value].reverse());
|
|
105
|
+
await nextTick();
|
|
221
106
|
|
|
222
107
|
// Verify order changed but IDs followed the items
|
|
223
|
-
expect(fieldArray.
|
|
224
|
-
expect(fieldArray.
|
|
225
|
-
expect(fieldArray.
|
|
226
|
-
expect(fieldArray.
|
|
227
|
-
expect(fieldArray.
|
|
228
|
-
expect(fieldArray.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
108
|
+
expect(fieldArray.items.value[0].item.name).toBe("Third");
|
|
109
|
+
expect(fieldArray.items.value[0].id).toBe(id3);
|
|
110
|
+
expect(fieldArray.items.value[0].path).toBe("items.0");
|
|
111
|
+
expect(fieldArray.items.value[1].item.name).toBe("Second");
|
|
112
|
+
expect(fieldArray.items.value[1].id).toBe(id2);
|
|
113
|
+
expect(fieldArray.items.value[1].path).toBe("items.1");
|
|
114
|
+
expect(fieldArray.items.value[2].item.name).toBe("First");
|
|
115
|
+
expect(fieldArray.items.value[2].id).toBe(id1);
|
|
116
|
+
expect(fieldArray.items.value[2].path).toBe("items.2");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("should maintain IDs based on custom hash function", async () => {
|
|
232
120
|
const form = useForm({
|
|
233
121
|
initialData: {
|
|
234
122
|
products: [
|
|
235
123
|
{
|
|
236
|
-
sku:
|
|
237
|
-
name:
|
|
124
|
+
sku: "ABC",
|
|
125
|
+
name: "Widget",
|
|
238
126
|
price: 10,
|
|
239
127
|
},
|
|
240
128
|
{
|
|
241
|
-
sku:
|
|
242
|
-
name:
|
|
129
|
+
sku: "DEF",
|
|
130
|
+
name: "Gadget",
|
|
243
131
|
price: 20,
|
|
244
132
|
},
|
|
245
133
|
],
|
|
246
134
|
},
|
|
247
|
-
})
|
|
248
|
-
const fieldArray = useFieldArray(form,
|
|
135
|
+
});
|
|
136
|
+
const fieldArray = useFieldArray(form, "products", {
|
|
249
137
|
hashFn: (item: { sku: string }) => item.sku,
|
|
250
|
-
})
|
|
138
|
+
});
|
|
251
139
|
|
|
252
|
-
const idABC = fieldArray.
|
|
253
|
-
const idDEF = fieldArray.
|
|
140
|
+
const idABC = fieldArray.items.value[0].id;
|
|
141
|
+
const idDEF = fieldArray.items.value[1].id;
|
|
254
142
|
|
|
255
143
|
// Update price and swap order
|
|
256
|
-
const arrayField = form.getField(
|
|
144
|
+
const arrayField = form.getField("products");
|
|
257
145
|
arrayField.setData([
|
|
258
146
|
{
|
|
259
|
-
sku:
|
|
260
|
-
name:
|
|
147
|
+
sku: "DEF",
|
|
148
|
+
name: "Gadget",
|
|
261
149
|
price: 25,
|
|
262
150
|
},
|
|
263
151
|
{
|
|
264
|
-
sku:
|
|
265
|
-
name:
|
|
152
|
+
sku: "ABC",
|
|
153
|
+
name: "Widget",
|
|
266
154
|
price: 15,
|
|
267
155
|
},
|
|
268
|
-
])
|
|
269
|
-
await nextTick()
|
|
156
|
+
]);
|
|
157
|
+
await nextTick();
|
|
270
158
|
|
|
271
159
|
// IDs should persist because SKUs didn't change
|
|
272
|
-
expect(fieldArray.
|
|
273
|
-
expect(fieldArray.
|
|
160
|
+
expect(fieldArray.items.value[0].id).toBe(idDEF);
|
|
161
|
+
expect(fieldArray.items.value[1].id).toBe(idABC);
|
|
274
162
|
|
|
275
163
|
// Change SKU - should get new ID
|
|
276
164
|
arrayField.setData([
|
|
277
165
|
{
|
|
278
|
-
sku:
|
|
279
|
-
name:
|
|
166
|
+
sku: "XYZ",
|
|
167
|
+
name: "Widget",
|
|
280
168
|
price: 15,
|
|
281
169
|
},
|
|
282
170
|
{
|
|
283
|
-
sku:
|
|
284
|
-
name:
|
|
171
|
+
sku: "DEF",
|
|
172
|
+
name: "Gadget",
|
|
285
173
|
price: 25,
|
|
286
174
|
},
|
|
287
|
-
])
|
|
288
|
-
await nextTick()
|
|
175
|
+
]);
|
|
176
|
+
await nextTick();
|
|
289
177
|
|
|
290
|
-
expect(fieldArray.
|
|
291
|
-
expect(fieldArray.
|
|
292
|
-
})
|
|
178
|
+
expect(fieldArray.items.value[0].id).not.toBe(idABC);
|
|
179
|
+
expect(fieldArray.items.value[1].id).toBe(idDEF);
|
|
180
|
+
});
|
|
293
181
|
|
|
294
|
-
it(
|
|
182
|
+
it("should assign IDs in order for items with same hash", async () => {
|
|
295
183
|
// When multiple items share the same hash, IDs are assigned in order
|
|
296
184
|
// from the stored ID list. This means reordering items with same hash
|
|
297
185
|
// will NOT preserve ID-to-item mapping (IDs follow position, not identity).
|
|
@@ -299,83 +187,164 @@ describe('useFieldArray', () => {
|
|
|
299
187
|
initialData: {
|
|
300
188
|
items: [
|
|
301
189
|
{
|
|
302
|
-
type:
|
|
303
|
-
value:
|
|
190
|
+
type: "tag",
|
|
191
|
+
value: "vue",
|
|
304
192
|
},
|
|
305
193
|
{
|
|
306
|
-
type:
|
|
307
|
-
value:
|
|
194
|
+
type: "tag",
|
|
195
|
+
value: "react",
|
|
308
196
|
},
|
|
309
197
|
{
|
|
310
|
-
type:
|
|
311
|
-
value:
|
|
198
|
+
type: "tag",
|
|
199
|
+
value: "svelte",
|
|
312
200
|
},
|
|
313
201
|
],
|
|
314
202
|
},
|
|
315
|
-
})
|
|
203
|
+
});
|
|
316
204
|
// Hash by type only - all items have same hash 'tag'
|
|
317
|
-
const fieldArray = useFieldArray(form,
|
|
205
|
+
const fieldArray = useFieldArray(form, "items", {
|
|
318
206
|
hashFn: (item: { type: string }) => item.type,
|
|
319
|
-
})
|
|
207
|
+
});
|
|
320
208
|
|
|
321
209
|
// All items get unique IDs despite same hash
|
|
322
|
-
const [id1, id2, id3] = fieldArray.
|
|
323
|
-
expect(new Set([id1, id2, id3]).size).toBe(3)
|
|
210
|
+
const [id1, id2, id3] = fieldArray.items.value.map((f) => f.id);
|
|
211
|
+
expect(new Set([id1, id2, id3]).size).toBe(3);
|
|
324
212
|
|
|
325
213
|
// Reorder: move last item to first position
|
|
326
|
-
const arrayField = form.getField(
|
|
214
|
+
const arrayField = form.getField("items");
|
|
327
215
|
arrayField.setData([
|
|
328
216
|
{
|
|
329
|
-
type:
|
|
330
|
-
value:
|
|
217
|
+
type: "tag",
|
|
218
|
+
value: "svelte",
|
|
331
219
|
},
|
|
332
220
|
{
|
|
333
|
-
type:
|
|
334
|
-
value:
|
|
221
|
+
type: "tag",
|
|
222
|
+
value: "vue",
|
|
335
223
|
},
|
|
336
224
|
{
|
|
337
|
-
type:
|
|
338
|
-
value:
|
|
225
|
+
type: "tag",
|
|
226
|
+
value: "react",
|
|
339
227
|
},
|
|
340
|
-
])
|
|
341
|
-
await nextTick()
|
|
228
|
+
]);
|
|
229
|
+
await nextTick();
|
|
342
230
|
|
|
343
231
|
// IDs are assigned in order from stored list, NOT following items
|
|
344
232
|
// This is expected behavior with hash collisions
|
|
345
|
-
expect(fieldArray.
|
|
346
|
-
expect(fieldArray.
|
|
347
|
-
expect(fieldArray.
|
|
233
|
+
expect(fieldArray.items.value[0].id).toBe(id1); // svelte gets id1 (was vue's)
|
|
234
|
+
expect(fieldArray.items.value[1].id).toBe(id2); // vue gets id2 (was react's)
|
|
235
|
+
expect(fieldArray.items.value[2].id).toBe(id3); // react gets id3 (was svelte's)
|
|
348
236
|
|
|
349
237
|
// The values confirm the reorder happened
|
|
350
|
-
expect(fieldArray.
|
|
351
|
-
expect(fieldArray.
|
|
352
|
-
expect(fieldArray.
|
|
353
|
-
})
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
describe('Form Integration', () => {
|
|
357
|
-
it('should track dirty state correctly', async () => {
|
|
238
|
+
expect(fieldArray.items.value[0].item.value).toBe("svelte");
|
|
239
|
+
expect(fieldArray.items.value[1].item.value).toBe("vue");
|
|
240
|
+
expect(fieldArray.items.value[2].item.value).toBe("react");
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("should push an item to the array", async () => {
|
|
358
244
|
const form = useForm({
|
|
359
|
-
initialData: {
|
|
360
|
-
|
|
361
|
-
|
|
245
|
+
initialData: {
|
|
246
|
+
items: [
|
|
247
|
+
{
|
|
248
|
+
id: 1,
|
|
249
|
+
name: "First",
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
const fieldArray = useFieldArray(form, "items", {
|
|
255
|
+
hashFn: (item: { id: number }) => item.id,
|
|
256
|
+
});
|
|
362
257
|
|
|
363
|
-
|
|
364
|
-
|
|
258
|
+
// Capture initial IDs
|
|
259
|
+
const id1 = fieldArray.items.value[0].id;
|
|
365
260
|
|
|
366
|
-
//
|
|
367
|
-
fieldArray.push({
|
|
368
|
-
|
|
261
|
+
// Push a new item
|
|
262
|
+
const newItem = fieldArray.push({
|
|
263
|
+
id: 2,
|
|
264
|
+
name: "Second",
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
expect(newItem.item.name).toBe("Second");
|
|
268
|
+
expect(newItem.path).toBe("items.1");
|
|
269
|
+
expect(newItem.id).toBeDefined();
|
|
369
270
|
|
|
370
|
-
|
|
371
|
-
expect(fieldArray.dirty.value).toBe(true)
|
|
271
|
+
await nextTick();
|
|
372
272
|
|
|
373
|
-
//
|
|
374
|
-
|
|
375
|
-
|
|
273
|
+
// Verify existing item's ID is unchanged
|
|
274
|
+
expect(fieldArray.items.value[0].id).toBe(id1);
|
|
275
|
+
expect(fieldArray.items.value[1].id).toBe(newItem.id);
|
|
276
|
+
});
|
|
376
277
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
278
|
+
it("should remove an item from the array", async () => {
|
|
279
|
+
const form = useForm({
|
|
280
|
+
initialData: {
|
|
281
|
+
items: [
|
|
282
|
+
{
|
|
283
|
+
id: 1,
|
|
284
|
+
name: "First",
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: 2,
|
|
288
|
+
name: "Second",
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
const fieldArray = useFieldArray(form, "items", {
|
|
294
|
+
hashFn: (item: { id: number }) => item.id,
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// Capture initial IDs
|
|
298
|
+
const id1 = fieldArray.items.value[0].id;
|
|
299
|
+
|
|
300
|
+
// Remove an item
|
|
301
|
+
fieldArray.remove(id1);
|
|
302
|
+
|
|
303
|
+
await nextTick();
|
|
304
|
+
|
|
305
|
+
// Verify the correct item was removed
|
|
306
|
+
expect(fieldArray.items.value.length).toBe(1);
|
|
307
|
+
expect(fieldArray.items.value[0].item.name).toBe("Second");
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it("should insert an item into the array", async () => {
|
|
311
|
+
const form = useForm({
|
|
312
|
+
initialData: {
|
|
313
|
+
items: [
|
|
314
|
+
{
|
|
315
|
+
id: 1,
|
|
316
|
+
name: "First",
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
id: 3,
|
|
320
|
+
name: "Third",
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
const fieldArray = useFieldArray(form, "items", {
|
|
326
|
+
hashFn: (item: { id: number }) => item.id,
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Capture initial IDs
|
|
330
|
+
const id1 = fieldArray.items.value[0].id;
|
|
331
|
+
const id3 = fieldArray.items.value[1].id;
|
|
332
|
+
|
|
333
|
+
// Insert an item
|
|
334
|
+
const insertedItem = fieldArray.insert({ id: 2, name: "Second" }, 1);
|
|
335
|
+
expect(insertedItem.item.name).toBe("Second");
|
|
336
|
+
expect(insertedItem.path).toBe("items.1");
|
|
337
|
+
expect(insertedItem.id).toBeDefined();
|
|
338
|
+
|
|
339
|
+
await nextTick();
|
|
340
|
+
|
|
341
|
+
// Verify the item was inserted correctly
|
|
342
|
+
expect(fieldArray.items.value.length).toBe(3);
|
|
343
|
+
expect(fieldArray.items.value[0].id).toBe(id1);
|
|
344
|
+
expect(fieldArray.items.value[0].item.name).toBe("First");
|
|
345
|
+
expect(fieldArray.items.value[1].item.name).toBe("Second");
|
|
346
|
+
expect(fieldArray.items.value[2].id).toBe(id3);
|
|
347
|
+
expect(fieldArray.items.value[2].item.name).toBe("Third");
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
});
|