@arrai-innovations/reactive-helpers 10.4.2 → 11.0.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.
@@ -1,152 +1,64 @@
1
1
  import { useListFilters, useListSort } from "../../../use/index.js";
2
2
  import { doAwaitNot } from "../../../utils/watches.js";
3
- import { nextTick, reactive, ref } from "vue";
3
+ import { ref, unref, reactive } from "vue";
4
4
  import { deepUnref } from "vue-deepunref";
5
5
 
6
6
  describe("use/listFilter", () => {
7
- let useListInstance, useListFilter, setDefaultSearchOptions;
7
+ let useListInstance, useListFilter, useListCalculated, useListRelated;
8
8
  beforeEach(async () => {
9
9
  const listInstanceModule = await import("../../../use/listInstance");
10
10
  useListInstance = listInstanceModule.useListInstance;
11
11
  const listFilterModule = await import("../../../use/listFilter");
12
12
  useListFilter = listFilterModule.useListFilter;
13
- const searchModule = await import("../../../use/search");
14
- setDefaultSearchOptions = searchModule.setDefaultSearchOptions;
15
- setDefaultSearchOptions({
16
- throttle: 0,
17
- });
13
+ const listRelatedModule = await import("../../../use/listRelated");
14
+ useListRelated = listRelatedModule.useListRelated;
15
+ const listCalculatedModule = await import("../../../use/listCalculated");
16
+ useListCalculated = listCalculatedModule.useListCalculated;
18
17
  });
19
18
 
20
- it("should match an allowed values list", async () => {
21
- const list = useListInstance({ props: {} });
22
- const filter = useListFilter({
23
- parentState: list.state,
24
- allowedValues: reactive({
25
- 1: true,
26
- 3: true,
27
- }),
28
- });
29
- await nextTick();
30
- expect(filter.state.objects).toEqual({});
31
- list.addListObject({ id: 1, name: "one", has_things: true });
32
- await nextTick();
33
- expect(filter.state.objects).toEqual({
34
- 1: { id: 1, name: "one", has_things: true },
35
- });
36
- list.addListObject({ id: 2, name: "two", has_things: true });
37
- await nextTick();
38
- expect(filter.state.objects).toEqual({
39
- 1: { id: 1, name: "one", has_things: true },
40
- });
41
- list.addListObject({ id: 3, name: "three", has_things: true });
42
- await nextTick();
43
- expect(filter.state.objects).toEqual({
44
- 1: { id: 1, name: "one", has_things: true },
45
- 3: { id: 3, name: "three", has_things: true },
46
- });
47
- list.addListObject({ id: 4, name: "four", has_things: true });
48
- await nextTick();
49
- expect(filter.state.objects).toEqual({
50
- 1: { id: 1, name: "one", has_things: true },
51
- 3: { id: 3, name: "three", has_things: true },
52
- });
53
- });
54
19
  it("should match an allowed filter function", async () => {
55
20
  const list = useListInstance({ props: {} });
56
21
  const filter = useListFilter({
57
22
  parentState: list.state,
58
- allowedFilter: (object) => object.id == 1 || object.id == 3,
59
- });
60
- await nextTick();
61
- expect(filter.state.objects).toEqual({});
62
- list.addListObject({ id: 1, name: "one", has_things: true });
63
- await nextTick();
64
- expect(filter.state.objects).toEqual({
65
- 1: { id: 1, name: "one", has_things: true },
66
- });
67
- list.addListObject({ id: 2, name: "two", has_things: true });
68
- await nextTick();
69
- expect(filter.state.objects).toEqual({
70
- 1: { id: 1, name: "one", has_things: true },
71
- });
72
- list.addListObject({ id: 3, name: "three", has_things: true });
73
- await nextTick();
74
- expect(filter.state.objects).toEqual({
75
- 1: { id: 1, name: "one", has_things: true },
76
- 3: { id: 3, name: "three", has_things: true },
77
- });
78
- list.addListObject({ id: 4, name: "four", has_things: true });
79
- await nextTick();
80
- expect(filter.state.objects).toEqual({
81
- 1: { id: 1, name: "one", has_things: true },
82
- 3: { id: 3, name: "three", has_things: true },
83
- });
84
- });
85
- it("should match by search term", async () => {
86
- const textSearchValue = ref("one");
87
- const list = useListInstance({ props: {} });
88
- const filter = useListFilter({
89
- parentState: list.state,
90
- useTextSearch: true,
91
- textSearchRules: ["name"],
92
- textSearchValue,
23
+ allowedFilter: (object) => object.id === 1 || object.id === 3,
93
24
  });
94
- await nextTick();
95
- // todo: it would be nice to wait for all searches to finish, instead of awaiting the first one back.
96
- await doAwaitNot({
97
- obj: filter.state,
98
- prop: "searching",
99
- });
100
- await nextTick();
101
25
  expect(filter.state.objects).toEqual({});
102
26
  list.addListObject({ id: 1, name: "one", has_things: true });
103
- await nextTick();
104
27
  await doAwaitNot({
105
28
  obj: filter.state,
106
- prop: "searching",
29
+ prop: "running",
30
+ timeout: 100,
107
31
  });
108
- await nextTick();
109
32
  expect(filter.state.objects).toEqual({
110
33
  1: { id: 1, name: "one", has_things: true },
111
34
  });
112
35
  list.addListObject({ id: 2, name: "two", has_things: true });
113
- await nextTick();
114
36
  await doAwaitNot({
115
37
  obj: filter.state,
116
- prop: "searching",
38
+ prop: "running",
39
+ timeout: 100,
117
40
  });
118
- await nextTick();
119
41
  expect(filter.state.objects).toEqual({
120
42
  1: { id: 1, name: "one", has_things: true },
121
43
  });
122
44
  list.addListObject({ id: 3, name: "three", has_things: true });
123
- await nextTick();
124
45
  await doAwaitNot({
125
46
  obj: filter.state,
126
- prop: "searching",
47
+ prop: "running",
48
+ timeout: 100,
127
49
  });
128
- await nextTick();
129
50
  expect(filter.state.objects).toEqual({
130
51
  1: { id: 1, name: "one", has_things: true },
131
- });
132
- textSearchValue.value = "three";
133
- await nextTick();
134
- await doAwaitNot({
135
- obj: filter.state,
136
- prop: "searching",
137
- });
138
- await nextTick();
139
- expect(filter.state.objects).toEqual({
140
52
  3: { id: 3, name: "three", has_things: true },
141
53
  });
142
54
  list.addListObject({ id: 4, name: "four", has_things: true });
143
- await nextTick();
144
55
  await doAwaitNot({
145
56
  obj: filter.state,
146
- prop: "searching",
57
+ prop: "running",
58
+ timeout: 100,
147
59
  });
148
- await nextTick();
149
60
  expect(filter.state.objects).toEqual({
61
+ 1: { id: 1, name: "one", has_things: true },
150
62
  3: { id: 3, name: "three", has_things: true },
151
63
  });
152
64
  });
@@ -156,60 +68,41 @@ describe("use/listFilter", () => {
156
68
  parentState: list.state,
157
69
  excludedFilter: (object) => object.id == 2 || object.id == 4,
158
70
  });
159
- await nextTick();
160
71
  expect(filter.state.objects).toEqual({});
161
72
  list.addListObject({ id: 1, name: "one", has_things: true });
162
- await nextTick();
163
- expect(filter.state.objects).toEqual({
164
- 1: { id: 1, name: "one", has_things: true },
165
- });
166
- list.addListObject({ id: 2, name: "two", has_things: true });
167
- await nextTick();
168
- expect(filter.state.objects).toEqual({
169
- 1: { id: 1, name: "one", has_things: true },
170
- });
171
- list.addListObject({ id: 3, name: "three", has_things: true });
172
- await nextTick();
173
- expect(filter.state.objects).toEqual({
174
- 1: { id: 1, name: "one", has_things: true },
175
- 3: { id: 3, name: "three", has_things: true },
176
- });
177
- list.addListObject({ id: 4, name: "four", has_things: true });
178
- await nextTick();
179
- expect(filter.state.objects).toEqual({
180
- 1: { id: 1, name: "one", has_things: true },
181
- 3: { id: 3, name: "three", has_things: true },
182
- });
183
- });
184
- it("should exclude an excludedValues parameter", async () => {
185
- const list = useListInstance({ props: {} });
186
- const filter = useListFilter({
187
- parentState: list.state,
188
- excludedValues: reactive({
189
- 2: true,
190
- 4: true,
191
- }),
73
+ await doAwaitNot({
74
+ obj: filter.state,
75
+ prop: "running",
76
+ timeout: 100,
192
77
  });
193
- await nextTick();
194
- expect(filter.state.objects).toEqual({});
195
- list.addListObject({ id: 1, name: "one", has_things: true });
196
- await nextTick();
197
78
  expect(filter.state.objects).toEqual({
198
79
  1: { id: 1, name: "one", has_things: true },
199
80
  });
200
81
  list.addListObject({ id: 2, name: "two", has_things: true });
201
- await nextTick();
82
+ await doAwaitNot({
83
+ obj: filter.state,
84
+ prop: "running",
85
+ timeout: 100,
86
+ });
202
87
  expect(filter.state.objects).toEqual({
203
88
  1: { id: 1, name: "one", has_things: true },
204
89
  });
205
90
  list.addListObject({ id: 3, name: "three", has_things: true });
206
- await nextTick();
91
+ await doAwaitNot({
92
+ obj: filter.state,
93
+ prop: "running",
94
+ timeout: 100,
95
+ });
207
96
  expect(filter.state.objects).toEqual({
208
97
  1: { id: 1, name: "one", has_things: true },
209
98
  3: { id: 3, name: "three", has_things: true },
210
99
  });
211
100
  list.addListObject({ id: 4, name: "four", has_things: true });
212
- await nextTick();
101
+ await doAwaitNot({
102
+ obj: filter.state,
103
+ prop: "running",
104
+ timeout: 100,
105
+ });
213
106
  expect(filter.state.objects).toEqual({
214
107
  1: { id: 1, name: "one", has_things: true },
215
108
  3: { id: 3, name: "three", has_things: true },
@@ -228,9 +121,7 @@ describe("use/listFilter", () => {
228
121
  }
229
122
  const filter = useListFilter({
230
123
  parentState: listInstance.state,
231
- useTextSearch: true,
232
124
  });
233
- await nextTick();
234
125
  expect(filter.state.objects).toEqual(listInstance.state.objects);
235
126
  });
236
127
  describe("useListFilter operates on parentState modified by useListSort", () => {
@@ -259,9 +150,14 @@ describe("use/listFilter", () => {
259
150
  const filter = useListFilter({
260
151
  parentState: listSort.state,
261
152
  });
262
- await nextTick();
263
- expect(filter.state.order).toEqual(expectedOrder);
264
- expect(filter.state.objectsInOrder).toEqual(orderedObjects);
153
+ await doAwaitNot({
154
+ obj: filter.state,
155
+ prop: "running",
156
+ });
157
+ const unrefOrder = deepUnref(filter.state.order);
158
+ const unrefObjectsInOrder = deepUnref(filter.state.objectsInOrder);
159
+ expect(unrefOrder).toEqual(expectedOrder);
160
+ expect(unrefObjectsInOrder).toEqual(orderedObjects);
265
161
  });
266
162
  });
267
163
  describe("useListFilters accepts args and parentInstances", () => {
@@ -286,32 +182,22 @@ describe("use/listFilter", () => {
286
182
  },
287
183
  },
288
184
  });
185
+ const excludedFilter = (object) => object.id === 1 || object.name === "three";
186
+ const allowedFilter = (object) => object.id === 2 || object.name === "four";
289
187
  const listFilterA = useListFilter({
290
188
  parentState: listInstanceA.state,
291
- excludedValues: {
292
- id: 1,
293
- name: "three",
294
- },
189
+ excludedFilter,
295
190
  });
296
191
  const listFilterB = useListFilter({
297
192
  parentState: listInstanceB.state,
298
- allowedValues: {
299
- id: 2,
300
- name: "four",
301
- },
193
+ allowedFilter,
302
194
  });
303
195
  const listFilterArgs = {
304
196
  A: {
305
- excludedValues: {
306
- id: 1,
307
- name: "three",
308
- },
197
+ excludedFilter,
309
198
  },
310
199
  B: {
311
- allowedValues: {
312
- id: 2,
313
- name: "four",
314
- },
200
+ allowedFilter,
315
201
  },
316
202
  };
317
203
  const listInstances = {
@@ -320,12 +206,154 @@ describe("use/listFilter", () => {
320
206
  };
321
207
  const listFilters = useListFilters(listFilterArgs, listInstances);
322
208
 
323
- expect(listFilters.A.state.excludedValues).toEqual({ id: 1, name: "three" });
324
- expect(listFilters.B.state.allowedValues).toEqual({ id: 2, name: "four" });
325
- expect(deepUnref(listFilters.A.parentState)).toEqual(deepUnref(listFilterA.parentState));
326
- expect(deepUnref(listFilters.B.parentState)).toEqual(deepUnref(listFilterB.parentState));
209
+ expect(listFilters.A.state.excludedFilter).toEqual(listFilterArgs.A.excludedFilter);
210
+ expect(listFilters.B.state.allowedFilter).toEqual(listFilterArgs.B.allowedFilter);
211
+ expect(unref(listFilters.A.parentState)).toEqual(unref(listFilterA.parentState));
212
+ expect(unref(listFilters.B.parentState)).toEqual(unref(listFilterB.parentState));
327
213
  expect(deepUnref(listFilters.A.state)).toEqual(deepUnref(listFilterA.state));
328
214
  expect(deepUnref(listFilters.B.state)).toEqual(deepUnref(listFilterB.state));
329
215
  });
330
216
  });
217
+ describe("useListFilters updates index when", () => {
218
+ it("parentInstance.objects is updated", async () => {
219
+ const list = useListInstance({ props: {} });
220
+ const filter = useListFilter({
221
+ parentState: list.state,
222
+ allowedFilter: (object) => !!object.allowed?.every((e) => e),
223
+ });
224
+ await doAwaitNot({
225
+ obj: filter.state,
226
+ prop: "running",
227
+ timeout: 100,
228
+ });
229
+ expect(filter.state.objects).toEqual({});
230
+ list.addListObject({ id: 1, name: "one", has_things: true, allowed: [true, true] });
231
+ await doAwaitNot({
232
+ obj: filter.state,
233
+ prop: "running",
234
+ timeout: 100,
235
+ });
236
+ expect(filter.state.objects).toEqual({
237
+ 1: { id: 1, name: "one", has_things: true, allowed: [true, true] },
238
+ });
239
+ list.addListObject({ id: 2, name: "two", has_things: true, allowed: [true, false] });
240
+ await doAwaitNot({
241
+ obj: filter.state,
242
+ prop: "running",
243
+ timeout: 100,
244
+ });
245
+ expect(filter.state.objects).toEqual({
246
+ 1: { id: 1, name: "one", has_things: true, allowed: [true, true] },
247
+ });
248
+ list.state.objects[1].allowed[0] = false;
249
+ list.state.objects[2].allowed[1] = true;
250
+ await doAwaitNot({
251
+ obj: filter.state,
252
+ prop: "running",
253
+ timeout: 100,
254
+ });
255
+ expect(filter.state.objects).toEqual({
256
+ 2: { id: 2, name: "two", has_things: true, allowed: [true, true] },
257
+ });
258
+ });
259
+ it("parentInstance.relatedObjects is updated", async () => {
260
+ const list = useListInstance({ props: {} });
261
+ const relatedList = useListInstance({ props: {} });
262
+ const related = useListRelated({
263
+ parentState: list.state,
264
+ relatedObjectsRules: {
265
+ relatedRuleName: {
266
+ objects: relatedList.state.objects,
267
+ pkKey: "related_id",
268
+ },
269
+ },
270
+ });
271
+ const allowedFilter = ref();
272
+ allowedFilter.value = (object, relatedObject) =>
273
+ relatedObject.relatedRuleName.allowed && relatedObject.relatedRuleName.has_things && object.has_things;
274
+ const filter = useListFilter({
275
+ parentState: related.state,
276
+ allowedFilter,
277
+ });
278
+ await doAwaitNot({
279
+ obj: filter.state,
280
+ prop: "running",
281
+ timeout: 100,
282
+ });
283
+ expect(filter.state.objects).toEqual({});
284
+ relatedList.addListObject({ id: 2, name: "two", has_things: true, allowed: true });
285
+ list.addListObject({ id: 1, name: "one", has_things: true, related_id: 2 });
286
+ await doAwaitNot({
287
+ obj: filter.state,
288
+ prop: "running",
289
+ timeout: 100,
290
+ });
291
+ expect(filter.state.objects).toEqual({
292
+ 1: { id: 1, name: "one", has_things: true, related_id: 2 },
293
+ });
294
+ relatedList.addListObject({ id: 4, name: "four", has_things: true, allowed: false });
295
+ list.addListObject({ id: 3, name: "three", has_things: true, related_id: 4 });
296
+ await doAwaitNot({
297
+ obj: filter.state,
298
+ prop: "running",
299
+ timeout: 100,
300
+ });
301
+ expect(filter.state.objects).toEqual({
302
+ 1: { id: 1, name: "one", has_things: true, related_id: 2 },
303
+ });
304
+ relatedList.state.objects[2].allowed = false;
305
+ relatedList.state.objects[4].allowed = true;
306
+ await doAwaitNot({
307
+ obj: filter.state,
308
+ prop: "running",
309
+ timeout: 100,
310
+ });
311
+ expect(filter.state.objects).toEqual({
312
+ 3: { id: 3, name: "three", has_things: true, related_id: 4 },
313
+ });
314
+ });
315
+ it("parentInstance.calculatedObjects is updated", async () => {
316
+ const list = useListInstance({ props: {} });
317
+ const calculated = useListCalculated({
318
+ parentState: list.state,
319
+ calculatedObjectsRules: reactive({
320
+ calculatedRuleName: (object) => object.things_count + object.other_things_count,
321
+ }),
322
+ });
323
+ const allowedFilter = ref();
324
+ allowedFilter.value = (object, relatedObject, calculatedObject) => calculatedObject.calculatedRuleName > 5;
325
+ const filter = useListFilter({
326
+ parentState: calculated.state,
327
+ allowedFilter,
328
+ });
329
+ await doAwaitNot({
330
+ obj: filter.state,
331
+ prop: "running",
332
+ });
333
+ expect(filter.state.objects).toEqual({});
334
+ list.addListObject({ id: 1, name: "one", has_things: true, things_count: 2, other_things_count: 3 });
335
+ await doAwaitNot({
336
+ obj: filter.state,
337
+ prop: "running",
338
+ });
339
+ expect(filter.state.objects).toEqual({});
340
+ list.addListObject({ id: 2, name: "two", has_things: true, things_count: 2, other_things_count: 4 });
341
+ await doAwaitNot({
342
+ obj: filter.state,
343
+ prop: "running",
344
+ });
345
+ expect(filter.state.objects).toEqual({
346
+ 2: { id: 2, name: "two", has_things: true, things_count: 2, other_things_count: 4 },
347
+ });
348
+ list.state.objects[1].things_count = 4;
349
+ list.state.objects[2].other_things_count = 0;
350
+ await doAwaitNot({
351
+ obj: filter.state,
352
+ prop: "running",
353
+ });
354
+ expect(filter.state.objects).toEqual({
355
+ 1: { id: 1, name: "one", has_things: true, things_count: 4, other_things_count: 3 },
356
+ });
357
+ });
358
+ });
331
359
  });