@arrai-innovations/reactive-helpers 10.4.2 → 11.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/.circleci/config.yml +3 -3
- package/README.md +123 -146
- package/config/listCrud.js +0 -1
- package/docs.md +178 -34
- package/package.json +3 -1
- package/tests/unit/use/listFilter.spec.js +335 -165
- package/tests/unit/use/listInstance.spec.js +14 -1
- package/tests/unit/use/listSearch.spec.js +505 -0
- package/tests/unit/use/listSort.spec.js +17 -1
- package/tests/unit/use/listSubscription.spec.js +91 -108
- package/tests/unit/use/search.spec.js +217 -36
- package/tests/unit/utils/assignReactiveObject.spec.js +43 -1
- package/tests/unit/{use → utils}/watches.spec.js +27 -3
- package/use/cancellableIntent.js +8 -3
- package/use/index.js +2 -0
- package/use/list.js +41 -14
- package/use/listCalculated.js +22 -19
- package/use/listFilter.js +146 -152
- package/use/listInstance.js +26 -31
- package/use/listKeys.js +99 -0
- package/use/listRelated.js +22 -14
- package/use/listSearch.js +357 -0
- package/use/listSort.js +46 -49
- package/use/listSubscription.js +3 -13
- package/use/search.js +154 -64
- package/use/watchesRunning.js +1 -1
- package/utils/assignReactiveObject.js +58 -14
- package/utils/index.js +1 -0
- package/utils/keyDiff.js +13 -7
- package/utils/relatedCalculatedHelpers.js +17 -0
- package/utils/watches.js +14 -11
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
import { doAwaitNot, doAwaitTimeout } from "../../../utils/watches.js";
|
|
2
|
+
import { nextTick, reactive, ref, unref } from "vue";
|
|
3
|
+
import { deepUnref } from "vue-deepunref";
|
|
4
|
+
|
|
5
|
+
describe("use/listSearch", () => {
|
|
6
|
+
let useListInstance, useListSearch, useListSearches, useListSort, useListRelated, useListCalculated;
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
const listInstanceModule = await import("../../../use/listInstance");
|
|
9
|
+
useListInstance = listInstanceModule.useListInstance;
|
|
10
|
+
const listSearchModule = await import("../../../use/listSearch");
|
|
11
|
+
useListSearch = listSearchModule.useListSearch;
|
|
12
|
+
useListSearches = listSearchModule.useListSearches;
|
|
13
|
+
const listSortModule = await import("../../../use/listSort");
|
|
14
|
+
useListSort = listSortModule.useListSort;
|
|
15
|
+
const listRelatedModule = await import("../../../use/listRelated");
|
|
16
|
+
useListRelated = listRelatedModule.useListRelated;
|
|
17
|
+
const listCalculatedModule = await import("../../../use/listCalculated");
|
|
18
|
+
useListCalculated = listCalculatedModule.useListCalculated;
|
|
19
|
+
});
|
|
20
|
+
it("should match by search term", async () => {
|
|
21
|
+
const textSearchValue = ref("one");
|
|
22
|
+
// const textSearchValue = ref("");
|
|
23
|
+
const list = useListInstance({ props: {} });
|
|
24
|
+
const search = useListSearch({
|
|
25
|
+
parentState: list.state,
|
|
26
|
+
props: reactive({
|
|
27
|
+
textSearchRules: ["name"],
|
|
28
|
+
textSearchValue,
|
|
29
|
+
}),
|
|
30
|
+
throttle: 20,
|
|
31
|
+
});
|
|
32
|
+
await doAwaitNot({
|
|
33
|
+
obj: search.state,
|
|
34
|
+
prop: "running",
|
|
35
|
+
});
|
|
36
|
+
expect(search.state.objects).toEqual({});
|
|
37
|
+
list.addListObject({ id: 1, name: "one", has_things: true });
|
|
38
|
+
await doAwaitNot({
|
|
39
|
+
obj: search.state,
|
|
40
|
+
prop: "running",
|
|
41
|
+
});
|
|
42
|
+
await doAwaitTimeout(100);
|
|
43
|
+
expect(search.state.objects).toEqual({
|
|
44
|
+
1: { id: 1, name: "one", has_things: true },
|
|
45
|
+
});
|
|
46
|
+
list.addListObject({ id: 2, name: "two", has_things: true });
|
|
47
|
+
await doAwaitNot({
|
|
48
|
+
obj: search.state,
|
|
49
|
+
prop: "running",
|
|
50
|
+
});
|
|
51
|
+
expect(search.state.objects).toEqual({
|
|
52
|
+
1: { id: 1, name: "one", has_things: true },
|
|
53
|
+
});
|
|
54
|
+
list.addListObject({ id: 3, name: "three", has_things: true });
|
|
55
|
+
await doAwaitNot({
|
|
56
|
+
obj: search.state,
|
|
57
|
+
prop: "running",
|
|
58
|
+
});
|
|
59
|
+
expect(search.state.objects).toEqual({
|
|
60
|
+
1: { id: 1, name: "one", has_things: true },
|
|
61
|
+
});
|
|
62
|
+
textSearchValue.value = "three";
|
|
63
|
+
await doAwaitNot({
|
|
64
|
+
obj: search.state,
|
|
65
|
+
prop: "running",
|
|
66
|
+
});
|
|
67
|
+
expect(search.state.objects).toEqual({
|
|
68
|
+
3: { id: 3, name: "three", has_things: true },
|
|
69
|
+
});
|
|
70
|
+
list.addListObject({ id: 4, name: "four", has_things: true });
|
|
71
|
+
await doAwaitNot({
|
|
72
|
+
obj: search.state,
|
|
73
|
+
prop: "running",
|
|
74
|
+
});
|
|
75
|
+
expect(search.state.objects).toEqual({
|
|
76
|
+
3: { id: 3, name: "three", has_things: true },
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
it("no args: returns objects unsearched", async () => {
|
|
80
|
+
const listInstance = useListInstance({ props: {} });
|
|
81
|
+
const listItems = [
|
|
82
|
+
{ id: 4, name: "four", has_things: true },
|
|
83
|
+
{ id: 2, name: "two", has_things: true },
|
|
84
|
+
{ id: 3, name: "three", has_things: true },
|
|
85
|
+
{ id: 1, name: "one", has_things: true },
|
|
86
|
+
];
|
|
87
|
+
for (const item of listItems) {
|
|
88
|
+
listInstance.addListObject(item);
|
|
89
|
+
}
|
|
90
|
+
const search = useListSearch({
|
|
91
|
+
parentState: listInstance.state,
|
|
92
|
+
throttle: 20,
|
|
93
|
+
});
|
|
94
|
+
await nextTick();
|
|
95
|
+
await nextTick();
|
|
96
|
+
await nextTick();
|
|
97
|
+
expect(search.state.objects).toEqual(listInstance.state.objects);
|
|
98
|
+
});
|
|
99
|
+
describe("useListSearch operates on parentState modified by useListSort", () => {
|
|
100
|
+
it("computes state.order and state.objects in order", async () => {
|
|
101
|
+
vi.resetAllMocks();
|
|
102
|
+
const orderByRules = [{ key: "name", desc: true, localeCompare: false }];
|
|
103
|
+
const sortThrottleWait = 0;
|
|
104
|
+
const listInstance = useListInstance({ props: {} });
|
|
105
|
+
const listItems = [
|
|
106
|
+
{ id: 4, name: "four", has_things: true },
|
|
107
|
+
{ id: 2, name: "two", has_things: true },
|
|
108
|
+
{ id: 3, name: "three", has_things: true },
|
|
109
|
+
{ id: 1, name: "one", has_things: true },
|
|
110
|
+
];
|
|
111
|
+
const expectedOrder = ["2", "3", "1", "4"];
|
|
112
|
+
const orderedObjects = [
|
|
113
|
+
{ id: 2, name: "two", has_things: true },
|
|
114
|
+
{ id: 3, name: "three", has_things: true },
|
|
115
|
+
{ id: 1, name: "one", has_things: true },
|
|
116
|
+
{ id: 4, name: "four", has_things: true },
|
|
117
|
+
];
|
|
118
|
+
const listSort = useListSort({ parentState: listInstance.state, orderByRules, sortThrottleWait });
|
|
119
|
+
for (const item of listItems) {
|
|
120
|
+
listInstance.addListObject(item);
|
|
121
|
+
}
|
|
122
|
+
const search = useListSearch({
|
|
123
|
+
parentState: listSort.state,
|
|
124
|
+
throttle: 20,
|
|
125
|
+
});
|
|
126
|
+
await doAwaitNot({
|
|
127
|
+
obj: search.state,
|
|
128
|
+
prop: "running",
|
|
129
|
+
});
|
|
130
|
+
expect(search.state.order).toEqual(expectedOrder);
|
|
131
|
+
expect(deepUnref(search.state.objectsInOrder)).toEqual(orderedObjects);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe("useListSearches accepts args and parentStates", () => {
|
|
135
|
+
it("looks the same as individual useListSearch instances", async () => {
|
|
136
|
+
vi.resetAllMocks();
|
|
137
|
+
const fields = ["id", "__str__", "name"];
|
|
138
|
+
const listInstanceA = useListInstance({
|
|
139
|
+
props: {
|
|
140
|
+
crudArgs: { stream: "test_streamA" },
|
|
141
|
+
listArgs: { user: 1 },
|
|
142
|
+
retrieveArgs: {
|
|
143
|
+
fields,
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
const listInstanceB = useListInstance({
|
|
148
|
+
props: {
|
|
149
|
+
crudArgs: { stream: "test_streamB" },
|
|
150
|
+
listArgs: { user: 2 },
|
|
151
|
+
retrieveArgs: {
|
|
152
|
+
fields,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const textSearchValueMarkerA = { marker: "A" };
|
|
158
|
+
const textSearchValueA = ref(textSearchValueMarkerA);
|
|
159
|
+
const textSearchValueMarkerB = { marker: "B" };
|
|
160
|
+
const textSearchValueB = ref(textSearchValueMarkerB);
|
|
161
|
+
|
|
162
|
+
const listSearchA = useListSearch({
|
|
163
|
+
parentState: listInstanceA.state,
|
|
164
|
+
props: reactive({
|
|
165
|
+
textSearchRules: ["name"],
|
|
166
|
+
textSearchValue: textSearchValueA,
|
|
167
|
+
customSearchOptions: {
|
|
168
|
+
limit: 10,
|
|
169
|
+
},
|
|
170
|
+
customIndexOptions: {
|
|
171
|
+
tokenize: "full",
|
|
172
|
+
},
|
|
173
|
+
}),
|
|
174
|
+
throttle: 20,
|
|
175
|
+
});
|
|
176
|
+
const listSearchB = useListSearch({
|
|
177
|
+
parentState: listInstanceB.state,
|
|
178
|
+
props: reactive({
|
|
179
|
+
textSearchRules: ["code"],
|
|
180
|
+
textSearchValue: textSearchValueB,
|
|
181
|
+
customSearchOptions: {
|
|
182
|
+
limit: 30,
|
|
183
|
+
},
|
|
184
|
+
customIndexOptions: {
|
|
185
|
+
tokenize: "strict",
|
|
186
|
+
},
|
|
187
|
+
}),
|
|
188
|
+
throttle: 40,
|
|
189
|
+
});
|
|
190
|
+
const listSearchArgs = {
|
|
191
|
+
A: {
|
|
192
|
+
props: reactive({
|
|
193
|
+
textSearchRules: ["name"],
|
|
194
|
+
textSearchValue: textSearchValueA,
|
|
195
|
+
customSearchOptions: {
|
|
196
|
+
limit: 10,
|
|
197
|
+
},
|
|
198
|
+
customIndexOptions: {
|
|
199
|
+
tokenize: "full",
|
|
200
|
+
},
|
|
201
|
+
}),
|
|
202
|
+
throttle: 20,
|
|
203
|
+
},
|
|
204
|
+
B: {
|
|
205
|
+
props: reactive({
|
|
206
|
+
textSearchRules: ["code"],
|
|
207
|
+
textSearchValue: textSearchValueB,
|
|
208
|
+
customSearchOptions: {
|
|
209
|
+
limit: 30,
|
|
210
|
+
},
|
|
211
|
+
customIndexOptions: {
|
|
212
|
+
tokenize: "strict",
|
|
213
|
+
},
|
|
214
|
+
}),
|
|
215
|
+
throttle: 40,
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
const listInstances = {
|
|
219
|
+
A: listInstanceA,
|
|
220
|
+
B: listInstanceB,
|
|
221
|
+
};
|
|
222
|
+
const listSearches = useListSearches(listSearchArgs, listInstances);
|
|
223
|
+
|
|
224
|
+
expect(unref(listSearches.A.state.textSearchRules)).toEqual(unref(listSearchA.state.textSearchRules));
|
|
225
|
+
expect(unref(listSearches.B.state.textSearchRules)).toEqual(unref(listSearchB.state.textSearchRules));
|
|
226
|
+
expect(unref(listSearches.A.parentState)).toEqual(unref(listSearchA.parentState));
|
|
227
|
+
expect(unref(listSearches.B.parentState)).toEqual(unref(listSearchB.parentState));
|
|
228
|
+
expect(deepUnref(listSearches.A.state)).toEqual(deepUnref(listSearchA.state));
|
|
229
|
+
expect(deepUnref(listSearches.B.state)).toEqual(deepUnref(listSearchB.state));
|
|
230
|
+
expect(deepUnref(listSearches.A.textSearchIndex.state)).toEqual(
|
|
231
|
+
deepUnref(listSearchA.textSearchIndex.state)
|
|
232
|
+
);
|
|
233
|
+
expect(deepUnref(listSearches.B.textSearchIndex.state)).toEqual(
|
|
234
|
+
deepUnref(listSearchB.textSearchIndex.state)
|
|
235
|
+
);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
describe("useListSearch accepts relatedItem. and calculatedItem. rules", () => {
|
|
239
|
+
it("in textSearchRules", async () => {
|
|
240
|
+
const textSearchValue = ref("four");
|
|
241
|
+
const list = useListInstance({ props: {} });
|
|
242
|
+
const relatedList = useListInstance({ props: {} });
|
|
243
|
+
const related = useListRelated({
|
|
244
|
+
parentState: list.state,
|
|
245
|
+
relatedObjectsRules: {
|
|
246
|
+
relatedRuleName: {
|
|
247
|
+
objects: relatedList.state.objects,
|
|
248
|
+
pkKey: "related_id",
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
const calculated = useListCalculated({
|
|
253
|
+
parentState: related.state,
|
|
254
|
+
calculatedObjectsRules: {
|
|
255
|
+
calculatedRuleName: (object) => object.id + "calculated",
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
const search = useListSearch({
|
|
259
|
+
parentState: calculated.state,
|
|
260
|
+
props: reactive({
|
|
261
|
+
textSearchRules: ["relatedItem.relatedRuleName.name", "calculatedItem.calculatedRuleName"],
|
|
262
|
+
textSearchValue,
|
|
263
|
+
}),
|
|
264
|
+
throttle: 20,
|
|
265
|
+
});
|
|
266
|
+
await doAwaitNot({
|
|
267
|
+
obj: search.state,
|
|
268
|
+
prop: "running",
|
|
269
|
+
});
|
|
270
|
+
expect(search.state.objects).toEqual({});
|
|
271
|
+
relatedList.addListObject({ id: 2, name: "two", has_things: false });
|
|
272
|
+
list.addListObject({ id: 1, name: "one", has_things: true, related_id: 2 });
|
|
273
|
+
relatedList.addListObject({ id: 4, name: "four", has_things: false });
|
|
274
|
+
list.addListObject({ id: 3, name: "three", has_things: true, related_id: 4 });
|
|
275
|
+
await doAwaitNot({
|
|
276
|
+
obj: search.state,
|
|
277
|
+
prop: "running",
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
expect(search.state.objects).toEqual({
|
|
281
|
+
3: { id: 3, name: "three", has_things: true, related_id: 4 },
|
|
282
|
+
});
|
|
283
|
+
textSearchValue.value = "1calculated";
|
|
284
|
+
await doAwaitNot({
|
|
285
|
+
obj: search.state,
|
|
286
|
+
prop: "running",
|
|
287
|
+
});
|
|
288
|
+
expect(search.state.objects).toEqual({
|
|
289
|
+
1: { id: 1, name: "one", has_things: true, related_id: 2 },
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
describe("useListSearch updates index when", () => {
|
|
294
|
+
it("parentState.objects is updated", async () => {
|
|
295
|
+
const list = useListInstance({ props: {} });
|
|
296
|
+
const textSearchValue = ref("");
|
|
297
|
+
const search = useListSearch({
|
|
298
|
+
parentState: list.state,
|
|
299
|
+
props: reactive({
|
|
300
|
+
textSearchRules: ["name"],
|
|
301
|
+
textSearchValue,
|
|
302
|
+
}),
|
|
303
|
+
throttle: 20,
|
|
304
|
+
});
|
|
305
|
+
expect(search.state.objects).toEqual({});
|
|
306
|
+
list.addListObject({ id: 1, name: "one" });
|
|
307
|
+
list.addListObject({ id: 2, name: "two" });
|
|
308
|
+
|
|
309
|
+
await doAwaitNot({
|
|
310
|
+
obj: search.state,
|
|
311
|
+
prop: "running",
|
|
312
|
+
});
|
|
313
|
+
expect(search.state.objects).toEqual({
|
|
314
|
+
1: { id: 1, name: "one" },
|
|
315
|
+
2: { id: 2, name: "two" },
|
|
316
|
+
});
|
|
317
|
+
textSearchValue.value = "one";
|
|
318
|
+
await doAwaitNot({
|
|
319
|
+
obj: search.state,
|
|
320
|
+
prop: "running",
|
|
321
|
+
});
|
|
322
|
+
await doAwaitTimeout(500);
|
|
323
|
+
expect(search.state.objects).toEqual({
|
|
324
|
+
1: { id: 1, name: "one" },
|
|
325
|
+
});
|
|
326
|
+
list.state.objects[2].name = "one";
|
|
327
|
+
await doAwaitNot({
|
|
328
|
+
obj: search.state,
|
|
329
|
+
prop: "running",
|
|
330
|
+
});
|
|
331
|
+
expect(search.state.objects).toEqual({
|
|
332
|
+
1: { id: 1, name: "one" },
|
|
333
|
+
2: { id: 2, name: "one" },
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
it("parentState.relatedObjects is updated", async () => {
|
|
337
|
+
const list = useListInstance({ props: {} });
|
|
338
|
+
const relatedList = useListInstance({ props: {} });
|
|
339
|
+
const related = useListRelated({
|
|
340
|
+
parentState: list.state,
|
|
341
|
+
relatedObjectsRules: reactive({
|
|
342
|
+
relatedRuleName: {
|
|
343
|
+
objects: relatedList.state.objects,
|
|
344
|
+
pkKey: "related_id",
|
|
345
|
+
},
|
|
346
|
+
}),
|
|
347
|
+
});
|
|
348
|
+
const textSearchValue = ref("");
|
|
349
|
+
const search = useListSearch({
|
|
350
|
+
parentState: related.state,
|
|
351
|
+
props: reactive({
|
|
352
|
+
textSearchRules: ["relatedItem.relatedRuleName.name"],
|
|
353
|
+
textSearchValue,
|
|
354
|
+
}),
|
|
355
|
+
throttle: 20,
|
|
356
|
+
});
|
|
357
|
+
await nextTick();
|
|
358
|
+
expect(search.state.objects).toEqual({});
|
|
359
|
+
relatedList.addListObject({ id: 2, name: "two", has_things: false });
|
|
360
|
+
list.addListObject({ id: 1, name: "one", has_things: true, related_id: 2 });
|
|
361
|
+
relatedList.addListObject({ id: 4, name: "four", has_things: false });
|
|
362
|
+
list.addListObject({ id: 3, name: "three", has_things: true, related_id: 4 });
|
|
363
|
+
await doAwaitNot({
|
|
364
|
+
obj: search.state,
|
|
365
|
+
prop: "running",
|
|
366
|
+
});
|
|
367
|
+
expect(search.state.objects).toEqual({
|
|
368
|
+
1: { id: 1, name: "one", has_things: true, related_id: 2 },
|
|
369
|
+
3: { id: 3, name: "three", has_things: true, related_id: 4 },
|
|
370
|
+
});
|
|
371
|
+
textSearchValue.value = "four";
|
|
372
|
+
await doAwaitNot({
|
|
373
|
+
obj: search.state,
|
|
374
|
+
prop: "running",
|
|
375
|
+
});
|
|
376
|
+
expect(search.state.objects).toEqual({
|
|
377
|
+
3: { id: 3, name: "three", has_things: true, related_id: 4 },
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
it("parentState.calculatedObjects is updated", async () => {
|
|
381
|
+
const list = useListInstance({ props: {} });
|
|
382
|
+
const calculated = useListCalculated({
|
|
383
|
+
parentState: list.state,
|
|
384
|
+
calculatedObjectsRules: reactive({
|
|
385
|
+
calculatedRuleName: (object) => object.basis.split("").join("z"),
|
|
386
|
+
}),
|
|
387
|
+
});
|
|
388
|
+
const textSearchValue = ref("");
|
|
389
|
+
const search = useListSearch({
|
|
390
|
+
parentState: calculated.state,
|
|
391
|
+
props: reactive({
|
|
392
|
+
textSearchRules: ["calculatedItem.calculatedRuleName"],
|
|
393
|
+
textSearchValue,
|
|
394
|
+
}),
|
|
395
|
+
throttle: 20,
|
|
396
|
+
});
|
|
397
|
+
await nextTick();
|
|
398
|
+
expect(search.state.objects).toEqual({});
|
|
399
|
+
list.addListObject({ id: 1, name: "one", basis: "one" });
|
|
400
|
+
list.addListObject({ id: 2, name: "two", basis: "two" });
|
|
401
|
+
await doAwaitNot({
|
|
402
|
+
obj: search.state,
|
|
403
|
+
prop: "running",
|
|
404
|
+
});
|
|
405
|
+
expect(search.state.objects).toEqual({
|
|
406
|
+
1: { id: 1, name: "one", basis: "one" },
|
|
407
|
+
2: { id: 2, name: "two", basis: "two" },
|
|
408
|
+
});
|
|
409
|
+
textSearchValue.value = "oznze";
|
|
410
|
+
await doAwaitNot({
|
|
411
|
+
obj: search.state,
|
|
412
|
+
prop: "running",
|
|
413
|
+
});
|
|
414
|
+
expect(search.state.objects).toEqual({
|
|
415
|
+
1: { id: 1, name: "one", basis: "one" },
|
|
416
|
+
});
|
|
417
|
+
list.state.objects[2].basis = "one";
|
|
418
|
+
await doAwaitNot({
|
|
419
|
+
obj: search.state,
|
|
420
|
+
prop: "running",
|
|
421
|
+
});
|
|
422
|
+
expect(search.state.objects).toEqual({
|
|
423
|
+
1: { id: 1, name: "one", basis: "one" },
|
|
424
|
+
2: { id: 2, name: "two", basis: "one" },
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
it("textSearchRules is updated", async () => {
|
|
428
|
+
const list = useListInstance({ props: {} });
|
|
429
|
+
const textSearchValue = ref("");
|
|
430
|
+
const searchProps = reactive({
|
|
431
|
+
textSearchValue,
|
|
432
|
+
textSearchRules: ["name"],
|
|
433
|
+
});
|
|
434
|
+
const search = useListSearch({
|
|
435
|
+
parentState: list.state,
|
|
436
|
+
props: searchProps,
|
|
437
|
+
throttle: 20,
|
|
438
|
+
});
|
|
439
|
+
await nextTick();
|
|
440
|
+
expect(search.state.objects).toEqual({});
|
|
441
|
+
list.addListObject({ id: 1, name: "one", code: "eno" });
|
|
442
|
+
list.addListObject({ id: 2, name: "two", code: "owt" });
|
|
443
|
+
await doAwaitNot({
|
|
444
|
+
obj: search.state,
|
|
445
|
+
prop: "running",
|
|
446
|
+
});
|
|
447
|
+
expect(search.state.objects).toEqual({
|
|
448
|
+
1: { id: 1, name: "one", code: "eno" },
|
|
449
|
+
2: { id: 2, name: "two", code: "owt" },
|
|
450
|
+
});
|
|
451
|
+
textSearchValue.value = "one";
|
|
452
|
+
await doAwaitNot({
|
|
453
|
+
obj: search.state,
|
|
454
|
+
prop: "running",
|
|
455
|
+
});
|
|
456
|
+
expect(search.state.objects).toEqual({
|
|
457
|
+
1: { id: 1, name: "one", code: "eno" },
|
|
458
|
+
});
|
|
459
|
+
searchProps.textSearchRules = ["code"];
|
|
460
|
+
await doAwaitNot({
|
|
461
|
+
obj: search.state,
|
|
462
|
+
prop: "running",
|
|
463
|
+
});
|
|
464
|
+
expect(search.state.objects).toEqual({});
|
|
465
|
+
textSearchValue.value = "eno";
|
|
466
|
+
await doAwaitNot({
|
|
467
|
+
obj: search.state,
|
|
468
|
+
prop: "running",
|
|
469
|
+
});
|
|
470
|
+
expect(search.state.objects).toEqual({
|
|
471
|
+
1: { id: 1, name: "one", code: "eno" },
|
|
472
|
+
});
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
it("does not pass through when showAllWhenEmpty is false", async () => {
|
|
476
|
+
const list = useListInstance({ props: {} });
|
|
477
|
+
const textSearchValue = ref("");
|
|
478
|
+
const search = useListSearch({
|
|
479
|
+
parentState: list.state,
|
|
480
|
+
props: reactive({
|
|
481
|
+
textSearchRules: ["name"],
|
|
482
|
+
textSearchValue,
|
|
483
|
+
}),
|
|
484
|
+
throttle: 20,
|
|
485
|
+
showAllWhenEmpty: false,
|
|
486
|
+
});
|
|
487
|
+
await doAwaitNot({
|
|
488
|
+
obj: search.state,
|
|
489
|
+
prop: "running",
|
|
490
|
+
});
|
|
491
|
+
expect(search.state.objects).toEqual({});
|
|
492
|
+
list.addListObject({ id: 1, name: "one" });
|
|
493
|
+
list.addListObject({ id: 2, name: "two" });
|
|
494
|
+
await doAwaitNot({
|
|
495
|
+
obj: search.state,
|
|
496
|
+
prop: "running",
|
|
497
|
+
});
|
|
498
|
+
expect(search.state.objects).toEqual({});
|
|
499
|
+
textSearchValue.value = "one";
|
|
500
|
+
await doAwaitNot({
|
|
501
|
+
obj: search.state,
|
|
502
|
+
prop: "running",
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
});
|
|
@@ -85,7 +85,6 @@ describe("use/useListSort", () => {
|
|
|
85
85
|
expect(listSort.state.order).toEqual([]);
|
|
86
86
|
expect(listSort.state.objectsInOrder).toEqual([]);
|
|
87
87
|
expect(listSort.state.sortCriteria).toEqual({});
|
|
88
|
-
expect(listSort.state.sortCriteriaEffectScopes).toEqual({});
|
|
89
88
|
expect(listSort.state.orderByDesc).toEqual([true, false]);
|
|
90
89
|
});
|
|
91
90
|
describe("addSortCriteria and removeSortCriteria", () => {
|
|
@@ -108,13 +107,16 @@ describe("use/useListSort", () => {
|
|
|
108
107
|
const listSort = useListSort({ parentState: listInstance.state, orderByRules });
|
|
109
108
|
// sorts immediately
|
|
110
109
|
expect(listSort.state.order).toEqual(testOrder1);
|
|
110
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder1.map((id) => listInstance.state.objects[id]));
|
|
111
111
|
await waitForListSort(listSort);
|
|
112
112
|
listInstance.addListObject(addObject);
|
|
113
113
|
await waitForListSort(listSort);
|
|
114
114
|
expect(listSort.state.order).toEqual(testOrder2);
|
|
115
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder2.map((id) => listInstance.state.objects[id]));
|
|
115
116
|
listInstance.deleteListObject(12);
|
|
116
117
|
await waitForListSort(listSort);
|
|
117
118
|
expect(listSort.state.order).toEqual(testOrder3);
|
|
119
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder3.map((id) => listInstance.state.objects[id]));
|
|
118
120
|
});
|
|
119
121
|
});
|
|
120
122
|
describe("sortWatch sifts various criteria", () => {
|
|
@@ -133,18 +135,22 @@ describe("use/useListSort", () => {
|
|
|
133
135
|
listSort.state.orderByRules.pop();
|
|
134
136
|
listSort.state.orderByRules.push({ key: "lexical_name", desc: false, localeCompare: true });
|
|
135
137
|
expect(listSort.state.order).toEqual(testOrder1);
|
|
138
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder1.map((id) => listInstance.state.objects[id]));
|
|
136
139
|
await waitForListSort(listSort);
|
|
137
140
|
expect(listSort.state.order).toEqual(testOrder2);
|
|
138
141
|
listSort.state.orderByRules.pop();
|
|
139
142
|
listSort.state.orderByRules.push({ key: "organization", desc: true, localeCompare: true });
|
|
140
143
|
await waitForListSort(listSort);
|
|
141
144
|
expect(listSort.state.order).toEqual(testOrder3);
|
|
145
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder3.map((id) => listInstance.state.objects[id]));
|
|
142
146
|
listSort.state.orderByRules.pop();
|
|
143
147
|
await waitForListSort(listSort);
|
|
144
148
|
expect(listSort.state.order).toEqual(testOrder4);
|
|
149
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder4.map((id) => listInstance.state.objects[id]));
|
|
145
150
|
listSort.state.orderByRules.push({ key: "organization", desc: false, localeCompare: false });
|
|
146
151
|
await waitForListSort(listSort);
|
|
147
152
|
expect(listSort.state.order).toEqual(testOrder2);
|
|
153
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder2.map((id) => listInstance.state.objects[id]));
|
|
148
154
|
});
|
|
149
155
|
});
|
|
150
156
|
it("useListSorts & useListInstances", async function () {
|
|
@@ -270,13 +276,16 @@ describe("use/useListSort", () => {
|
|
|
270
276
|
}
|
|
271
277
|
await waitForListSort(listSort);
|
|
272
278
|
expect(listSort.state.order).toEqual(["4", "3", "2", "1"]);
|
|
279
|
+
expect(listSort.state.objectsInOrder.map((obj) => obj.id)).toEqual([4, 3, 2, 1]);
|
|
273
280
|
orderByRules[0].key = "relatedItemName.name";
|
|
274
281
|
await waitForListSort(listSort);
|
|
275
282
|
expect(listSort.state.order).toEqual(["1", "2", "3", "4"]);
|
|
283
|
+
expect(listSort.state.objectsInOrder.map((obj) => obj.id)).toEqual([1, 2, 3, 4]);
|
|
276
284
|
orderByRules[0].key = "relatedItemName.sameValue";
|
|
277
285
|
orderByRules[1] = { key: "calculatedItem.calculatedItemName", desc: false, localeCompare: false };
|
|
278
286
|
await waitForListSort(listSort);
|
|
279
287
|
expect(listSort.state.order).toEqual(["4", "3", "2", "1"]);
|
|
288
|
+
expect(listSort.state.objectsInOrder.map((obj) => obj.id)).toEqual([4, 3, 2, 1]);
|
|
280
289
|
});
|
|
281
290
|
describe("useListSort/sortThrottleWait", () => {
|
|
282
291
|
it("respects throttle time prior to triggering", async () => {
|
|
@@ -302,25 +311,32 @@ describe("use/useListSort", () => {
|
|
|
302
311
|
|
|
303
312
|
const listSort = useListSort({ parentState: listInstance.state, orderByRules, sortThrottleWait });
|
|
304
313
|
expect(listSort.state.order).toEqual(testOrder1);
|
|
314
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder1.map((id) => listInstance.state.objects[id]));
|
|
305
315
|
|
|
306
316
|
// wait for the original throttle to finish
|
|
307
317
|
await doAwaitTimeout(250);
|
|
308
318
|
|
|
309
319
|
expect(listSort.state.order).toEqual(testOrder2);
|
|
320
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder2.map((id) => listInstance.state.objects[id]));
|
|
310
321
|
listInstance.addListObject(addObject);
|
|
311
322
|
expect(listSort.state.order).toEqual(testOrder2);
|
|
323
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder2.map((id) => listInstance.state.objects[id]));
|
|
312
324
|
// trigger the leading edge of the throttle
|
|
313
325
|
await doAwaitTimeout(10);
|
|
314
326
|
expect(listSort.state.order).toEqual(testOrder3);
|
|
327
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder3.map((id) => listInstance.state.objects[id]));
|
|
315
328
|
// trigger again before the 200ms throttle
|
|
316
329
|
listInstance.deleteListObject(12);
|
|
317
330
|
expect(listSort.state.order).toEqual(testOrder3);
|
|
331
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder3.map((id) => listInstance.state.objects[id]));
|
|
318
332
|
// this should trigger before the 200ms throttle
|
|
319
333
|
await doAwaitTimeout(100);
|
|
320
334
|
expect(listSort.state.order).toEqual(testOrder3);
|
|
335
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder3.map((id) => listInstance.state.objects[id]));
|
|
321
336
|
// this should trigger after the 200ms throttle
|
|
322
337
|
await doAwaitTimeout(200);
|
|
323
338
|
expect(listSort.state.order).toEqual(testOrder4);
|
|
339
|
+
expect(listSort.state.objectsInOrder).toEqual(testOrder4.map((id) => listInstance.state.objects[id]));
|
|
324
340
|
});
|
|
325
341
|
});
|
|
326
342
|
});
|