@daiso-tech/core 0.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.
Files changed (176) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +11 -0
  3. package/.changeset/sweet-peas-beg.md +5 -0
  4. package/.eslintignore +3 -0
  5. package/.eslintrc.json +50 -0
  6. package/.gitattributes +6 -0
  7. package/.github/workflows/main.yaml +54 -0
  8. package/.github/workflows/release.yaml +31 -0
  9. package/.prettierignore +4 -0
  10. package/.prettierrc.json +4 -0
  11. package/.vscode/settings.json +46 -0
  12. package/LICENSE.md +194 -0
  13. package/docs-api/.nojekyll +1 -0
  14. package/docs-api/assets/highlight.css +92 -0
  15. package/docs-api/assets/icons.js +18 -0
  16. package/docs-api/assets/icons.svg +1 -0
  17. package/docs-api/assets/main.js +60 -0
  18. package/docs-api/assets/navigation.js +1 -0
  19. package/docs-api/assets/search.js +1 -0
  20. package/docs-api/assets/style.css +1448 -0
  21. package/docs-api/classes/AsyncIterableCollection.html +437 -0
  22. package/docs-api/classes/CollectionError.html +12 -0
  23. package/docs-api/classes/IndexOverflowError.html +12 -0
  24. package/docs-api/classes/ItemNotFoundError.html +12 -0
  25. package/docs-api/classes/IterableCollection.html +434 -0
  26. package/docs-api/classes/ListCollection.html +434 -0
  27. package/docs-api/classes/MultipleItemsFoundError.html +12 -0
  28. package/docs-api/classes/UnexpectedCollectionError.html +12 -0
  29. package/docs-api/functions/isAsyncIterable.html +1 -0
  30. package/docs-api/functions/isIterable.html +1 -0
  31. package/docs-api/functions/range.html +4 -0
  32. package/docs-api/hierarchy.html +1 -0
  33. package/docs-api/index.html +1 -0
  34. package/docs-api/modules.html +60 -0
  35. package/docs-api/types/AsyncCollapse.html +1 -0
  36. package/docs-api/types/AsyncFilter.html +1 -0
  37. package/docs-api/types/AsyncFilter_.html +1 -0
  38. package/docs-api/types/AsyncFindOrSettings.html +1 -0
  39. package/docs-api/types/AsyncFindSettings.html +1 -0
  40. package/docs-api/types/AsyncForEach.html +1 -0
  41. package/docs-api/types/AsyncForEach_.html +1 -0
  42. package/docs-api/types/AsyncGroupBySettings.html +1 -0
  43. package/docs-api/types/AsyncIterableValue.html +1 -0
  44. package/docs-api/types/AsyncLazyable.html +1 -0
  45. package/docs-api/types/AsyncLazyable_.html +1 -0
  46. package/docs-api/types/AsyncMap.html +1 -0
  47. package/docs-api/types/AsyncMap_.html +1 -0
  48. package/docs-api/types/AsyncModifier.html +1 -0
  49. package/docs-api/types/AsyncModifier_.html +1 -0
  50. package/docs-api/types/AsyncReduce.html +1 -0
  51. package/docs-api/types/AsyncReduceSettings.html +1 -0
  52. package/docs-api/types/AsyncReduce_.html +1 -0
  53. package/docs-api/types/AsyncTap.html +1 -0
  54. package/docs-api/types/AsyncTap_.html +1 -0
  55. package/docs-api/types/AsyncTransform.html +1 -0
  56. package/docs-api/types/AsyncTransform_.html +1 -0
  57. package/docs-api/types/Collapse.html +1 -0
  58. package/docs-api/types/Comparator.html +1 -0
  59. package/docs-api/types/EnsureType.html +1 -0
  60. package/docs-api/types/Filter.html +1 -0
  61. package/docs-api/types/FilterGuard.html +1 -0
  62. package/docs-api/types/Filter_.html +1 -0
  63. package/docs-api/types/FindOrSettings.html +1 -0
  64. package/docs-api/types/FindSettings.html +1 -0
  65. package/docs-api/types/ForEach.html +1 -0
  66. package/docs-api/types/GroupBySettings.html +1 -0
  67. package/docs-api/types/IAsyncCollection.html +357 -0
  68. package/docs-api/types/ICollection.html +357 -0
  69. package/docs-api/types/JoinSettings.html +1 -0
  70. package/docs-api/types/Lazyable.html +1 -0
  71. package/docs-api/types/Map.html +1 -0
  72. package/docs-api/types/Modifier.html +1 -0
  73. package/docs-api/types/PageSettings.html +1 -0
  74. package/docs-api/types/RecordItem.html +1 -0
  75. package/docs-api/types/Reduce.html +1 -0
  76. package/docs-api/types/ReduceSettings.html +1 -0
  77. package/docs-api/types/ReverseSettings.html +1 -0
  78. package/docs-api/types/SliceSettings.html +1 -0
  79. package/docs-api/types/SlidingSettings.html +1 -0
  80. package/docs-api/types/Tap.html +1 -0
  81. package/docs-api/types/Transform.html +1 -0
  82. package/docs-api/types/UpdatedItem.html +1 -0
  83. package/package.json +47 -0
  84. package/src/_module.ts +2 -0
  85. package/src/collection/_module.ts +4 -0
  86. package/src/collection/_shared.ts +45 -0
  87. package/src/collection/async-iterable-collection/_module.ts +1 -0
  88. package/src/collection/async-iterable-collection/async-iterable-collection.test.ts +3195 -0
  89. package/src/collection/async-iterable-collection/async-iterable-collection.ts +1276 -0
  90. package/src/collection/async-iterable-collection/async-iterable-helpers/_module.ts +35 -0
  91. package/src/collection/async-iterable-collection/async-iterable-helpers/async-abort-iterable.ts +25 -0
  92. package/src/collection/async-iterable-collection/async-iterable-helpers/async-chunk-iterable.ts +57 -0
  93. package/src/collection/async-iterable-collection/async-iterable-helpers/async-chunk-whilte-iterable.ts +54 -0
  94. package/src/collection/async-iterable-collection/async-iterable-helpers/async-collapse-iterable.ts +40 -0
  95. package/src/collection/async-iterable-collection/async-iterable-helpers/async-count-by-iterable.ts +58 -0
  96. package/src/collection/async-iterable-collection/async-iterable-helpers/async-cross-join-iterable.ts +69 -0
  97. package/src/collection/async-iterable-collection/async-iterable-helpers/async-delay-iterable.ts +19 -0
  98. package/src/collection/async-iterable-collection/async-iterable-helpers/async-entries-iterable.ts +28 -0
  99. package/src/collection/async-iterable-collection/async-iterable-helpers/async-filter-iterable.ts +42 -0
  100. package/src/collection/async-iterable-collection/async-iterable-helpers/async-flat-map-iterable.ts +44 -0
  101. package/src/collection/async-iterable-collection/async-iterable-helpers/async-group-by-iterable.ts +48 -0
  102. package/src/collection/async-iterable-collection/async-iterable-helpers/async-insert-after-iterable.ts +57 -0
  103. package/src/collection/async-iterable-collection/async-iterable-helpers/async-insert-before-iterable.ts +57 -0
  104. package/src/collection/async-iterable-collection/async-iterable-helpers/async-map-iterable.ts +40 -0
  105. package/src/collection/async-iterable-collection/async-iterable-helpers/async-merge-iterable.ts +35 -0
  106. package/src/collection/async-iterable-collection/async-iterable-helpers/async-pad-end-iterable.ts +41 -0
  107. package/src/collection/async-iterable-collection/async-iterable-helpers/async-pad-start-iterable.ts +41 -0
  108. package/src/collection/async-iterable-collection/async-iterable-helpers/async-partion-iterable.ts +63 -0
  109. package/src/collection/async-iterable-collection/async-iterable-helpers/async-repeat-iterable.ts +40 -0
  110. package/src/collection/async-iterable-collection/async-iterable-helpers/async-reverse-iterable.ts +35 -0
  111. package/src/collection/async-iterable-collection/async-iterable-helpers/async-shuffle-iterable.ts +23 -0
  112. package/src/collection/async-iterable-collection/async-iterable-helpers/async-skip-iterable.ts +41 -0
  113. package/src/collection/async-iterable-collection/async-iterable-helpers/async-skip-until-iterable.ts +55 -0
  114. package/src/collection/async-iterable-collection/async-iterable-helpers/async-slice-iterable.ts +33 -0
  115. package/src/collection/async-iterable-collection/async-iterable-helpers/async-sliding-iterable.ts +54 -0
  116. package/src/collection/async-iterable-collection/async-iterable-helpers/async-sort-iterable.ts +18 -0
  117. package/src/collection/async-iterable-collection/async-iterable-helpers/async-split-iterable.ts +64 -0
  118. package/src/collection/async-iterable-collection/async-iterable-helpers/async-take-iterable.ts +41 -0
  119. package/src/collection/async-iterable-collection/async-iterable-helpers/async-take-until-iterable.ts +41 -0
  120. package/src/collection/async-iterable-collection/async-iterable-helpers/async-tap-iterable.ts +34 -0
  121. package/src/collection/async-iterable-collection/async-iterable-helpers/async-timeout-iterable.ts +20 -0
  122. package/src/collection/async-iterable-collection/async-iterable-helpers/async-unique-iterable.ts +49 -0
  123. package/src/collection/async-iterable-collection/async-iterable-helpers/async-update-iterable.ts +64 -0
  124. package/src/collection/async-iterable-collection/async-iterable-helpers/async-when-iterable.ts +43 -0
  125. package/src/collection/async-iterable-collection/async-iterable-helpers/async-zip-iterable.ts +45 -0
  126. package/src/collection/iterable-collection/_module.ts +1 -0
  127. package/src/collection/iterable-collection/iterable-collection.test.ts +2379 -0
  128. package/src/collection/iterable-collection/iterable-collection.ts +1317 -0
  129. package/src/collection/iterable-collection/iterable-helpers/_module.ts +32 -0
  130. package/src/collection/iterable-collection/iterable-helpers/chunk-iterable.ts +49 -0
  131. package/src/collection/iterable-collection/iterable-helpers/chunk-whilte-iterable.ts +51 -0
  132. package/src/collection/iterable-collection/iterable-helpers/collapse-iterable.ts +35 -0
  133. package/src/collection/iterable-collection/iterable-helpers/count-by-iterable.ts +49 -0
  134. package/src/collection/iterable-collection/iterable-helpers/cross-join-iterable.ts +57 -0
  135. package/src/collection/iterable-collection/iterable-helpers/entries-iterable.ts +42 -0
  136. package/src/collection/iterable-collection/iterable-helpers/filter-iterable.ts +39 -0
  137. package/src/collection/iterable-collection/iterable-helpers/flat-map-iterable.ts +35 -0
  138. package/src/collection/iterable-collection/iterable-helpers/group-by-iterable.ts +52 -0
  139. package/src/collection/iterable-collection/iterable-helpers/insert-after-iterable.ts +43 -0
  140. package/src/collection/iterable-collection/iterable-helpers/insert-before-iterable.ts +43 -0
  141. package/src/collection/iterable-collection/iterable-helpers/map-iterable.ts +35 -0
  142. package/src/collection/iterable-collection/iterable-helpers/merge-iterable.ts +31 -0
  143. package/src/collection/iterable-collection/iterable-helpers/pad-end-iterable.ts +52 -0
  144. package/src/collection/iterable-collection/iterable-helpers/pad-start-iterable.ts +52 -0
  145. package/src/collection/iterable-collection/iterable-helpers/partion-iterable.ts +46 -0
  146. package/src/collection/iterable-collection/iterable-helpers/repeat-iterable.ts +36 -0
  147. package/src/collection/iterable-collection/iterable-helpers/reverse-iterable.ts +46 -0
  148. package/src/collection/iterable-collection/iterable-helpers/shuffle-iterable.ts +36 -0
  149. package/src/collection/iterable-collection/iterable-helpers/skip-iterable.ts +37 -0
  150. package/src/collection/iterable-collection/iterable-helpers/skip-until-iterable.ts +41 -0
  151. package/src/collection/iterable-collection/iterable-helpers/slice-iterable.ts +47 -0
  152. package/src/collection/iterable-collection/iterable-helpers/sliding-iterable.ts +49 -0
  153. package/src/collection/iterable-collection/iterable-helpers/sort-iterable.ts +29 -0
  154. package/src/collection/iterable-collection/iterable-helpers/split-iterable.ts +58 -0
  155. package/src/collection/iterable-collection/iterable-helpers/take-iterable.ts +37 -0
  156. package/src/collection/iterable-collection/iterable-helpers/take-until-iterable.ts +38 -0
  157. package/src/collection/iterable-collection/iterable-helpers/tap-iterable.ts +31 -0
  158. package/src/collection/iterable-collection/iterable-helpers/unique-iterable.ts +43 -0
  159. package/src/collection/iterable-collection/iterable-helpers/update-iterable.ts +50 -0
  160. package/src/collection/iterable-collection/iterable-helpers/when-iterable.ts +37 -0
  161. package/src/collection/iterable-collection/iterable-helpers/zip-iterable.ts +41 -0
  162. package/src/collection/list-collection/_module.ts +1 -0
  163. package/src/collection/list-collection/list-collection.test.ts +2280 -0
  164. package/src/collection/list-collection/list-collection.ts +1883 -0
  165. package/src/contracts/_module.ts +1 -0
  166. package/src/contracts/collection/_module.ts +3 -0
  167. package/src/contracts/collection/_shared.ts +346 -0
  168. package/src/contracts/collection/async-collection.contract.ts +1028 -0
  169. package/src/contracts/collection/collection.contract.ts +978 -0
  170. package/src/types.ts +2 -0
  171. package/tsconfig.base.json +31 -0
  172. package/tsconfig.cjs.json +12 -0
  173. package/tsconfig.esm.json +12 -0
  174. package/tsconfig.json +10 -0
  175. package/tsconfig.types.json +12 -0
  176. package/vite.config.ts +6 -0
@@ -0,0 +1,2379 @@
1
+ import { describe, expect, test } from "vitest";
2
+
3
+ import {
4
+ CollectionError,
5
+ ItemNotFoundError,
6
+ MultipleItemsFoundError,
7
+ RecordItem,
8
+ } from "@/contracts/collection/_module";
9
+ import { IterableCollection } from "@/collection/iterable-collection/_module";
10
+
11
+ describe("class: IterableCollection", () => {
12
+ describe("method: filter", () => {
13
+ test(`Should filter out all "a" of ["a", "bc", "c", "a", "d", "a"]`, () => {
14
+ const arr = ["a", "bc", "c", "a", "d", "a"],
15
+ collection = new IterableCollection(arr),
16
+ filterFunction = (item: string): boolean => item === "a",
17
+ newCollection = collection.filter(filterFunction);
18
+ expect(newCollection.toArray()).toEqual(arr.filter(filterFunction));
19
+ });
20
+ test("Should input correct indexes to filter function", () => {
21
+ const collection = new IterableCollection([
22
+ "a",
23
+ "bc",
24
+ "c",
25
+ "a",
26
+ "d",
27
+ "a",
28
+ ]),
29
+ indexes: number[] = [],
30
+ filterFunction = (item: string, index: number): boolean => {
31
+ indexes.push(index);
32
+ return item === "a";
33
+ };
34
+ collection.filter(filterFunction).toArray();
35
+ expect(indexes).toEqual([0, 1, 2, 3, 4, 5]);
36
+ });
37
+ });
38
+ describe("method: map", () => {
39
+ test("Should apply power by 2 for all items", () => {
40
+ const arr = [2, 3, 4, 5],
41
+ collection = new IterableCollection(arr),
42
+ mapFunction = (item: number): number => item ** 2,
43
+ newCollection = collection.map(mapFunction);
44
+ expect(newCollection.toArray()).toEqual(arr.map(mapFunction));
45
+ });
46
+ test("Should input correct indexes to map function", () => {
47
+ const collection = new IterableCollection([2, 3, 4, 5]),
48
+ indexes: number[] = [],
49
+ mapFunction = (item: number, index: number): number => {
50
+ indexes.push(index);
51
+ return item ** 2;
52
+ };
53
+ collection.map(mapFunction).toArray();
54
+ expect(indexes).toEqual([0, 1, 2, 3]);
55
+ });
56
+ });
57
+ describe("method: reduce", () => {
58
+ test("Should join all string items without initial values", () => {
59
+ const arr = ["a", "b", "c", "d"],
60
+ collection = new IterableCollection(arr),
61
+ seperator = "_#_",
62
+ result = collection.reduce({
63
+ reduceFn(firstItem, item) {
64
+ return firstItem + seperator + item;
65
+ },
66
+ });
67
+ expect(result).toBe(arr.join(seperator));
68
+ });
69
+ test(`Should join all string items initial value "_#_"`, () => {
70
+ const arr = ["a", "b", "c", "d"],
71
+ collection = new IterableCollection(arr),
72
+ initialValue = "!",
73
+ result = collection.reduce({
74
+ reduceFn(initialValue, item) {
75
+ return initialValue + item;
76
+ },
77
+ initialValue,
78
+ });
79
+ expect(result).toBe(initialValue + arr.join(""));
80
+ });
81
+ test("Should input correct indexes to reduce function", () => {
82
+ const arr = ["a", "b", "c", "d"],
83
+ collection = new IterableCollection(arr),
84
+ initialValue = "!",
85
+ indexes: number[] = [];
86
+ collection.reduce({
87
+ reduceFn(initialValue, item, index) {
88
+ indexes.push(index);
89
+ return initialValue + item;
90
+ },
91
+ initialValue,
92
+ });
93
+ expect(indexes).toEqual([0, 1, 2, 3]);
94
+ });
95
+ test("Should throw TypeError when given an empty array without initial value", () => {
96
+ const collection = new IterableCollection<string>([]);
97
+ expect(() => {
98
+ collection.reduce({
99
+ reduceFn: (a, b) => a + b,
100
+ });
101
+ }).toThrowError(TypeError);
102
+ });
103
+ test("Should return the same value when called more than 1 times", () => {
104
+ const arr = ["a", "b", "c", "d"],
105
+ collection = new IterableCollection(arr),
106
+ seperator = "_#_";
107
+ expect(
108
+ collection.reduce({
109
+ reduceFn(firstItem, item) {
110
+ return firstItem + seperator + item;
111
+ },
112
+ }),
113
+ ).toBe(arr.join(seperator));
114
+ expect(
115
+ collection.reduce({
116
+ reduceFn(firstItem, item) {
117
+ return firstItem + seperator + item;
118
+ },
119
+ }),
120
+ ).toBe(arr.join(seperator));
121
+ });
122
+ });
123
+ describe("method: join", () => {
124
+ test(`Should join iterable of ["a", "b", "c"] to "a,b,c"`, () => {
125
+ const collection = new IterableCollection(["a", "b", "c"]);
126
+ expect(collection.join()).toBe("a,b,c");
127
+ });
128
+ test(`Should join iterable of ["a", "b", "c"] to "a,b,c" with seperator "_#_"`, () => {
129
+ const collection = new IterableCollection(["a", "b", "c"]);
130
+ expect(
131
+ collection.join({
132
+ seperator: "_#_",
133
+ }),
134
+ ).toBe("a_#_b_#_c");
135
+ });
136
+ test("Should return the same value when called more than 1 times", () => {
137
+ const collection = new IterableCollection(["a", "b", "c"]);
138
+ expect(collection.join()).toBe("a,b,c");
139
+ expect(collection.join()).toBe("a,b,c");
140
+ });
141
+ });
142
+ describe("method: flatMap", () => {
143
+ test("Should apply flatmap", () => {
144
+ const collection = new IterableCollection(["a", "ab", "b", "ba"]),
145
+ newCollection = collection.flatMap((item, index) => [
146
+ index,
147
+ item,
148
+ item.length,
149
+ ]);
150
+ expect(newCollection.toArray()).toEqual([
151
+ 0,
152
+ "a",
153
+ 1,
154
+ 1,
155
+ "ab",
156
+ 2,
157
+ 2,
158
+ "b",
159
+ 1,
160
+ 3,
161
+ "ba",
162
+ 2,
163
+ ]);
164
+ });
165
+ test("Should input correct indexes to map function", () => {
166
+ const collection = new IterableCollection(["a", "ab", "b", "ba"]),
167
+ indexes: number[] = [],
168
+ mapFunction = (
169
+ item: string,
170
+ index: number,
171
+ ): [number, string, number] => {
172
+ indexes.push(index);
173
+ return [index, item, item.length];
174
+ };
175
+ collection.flatMap(mapFunction).toArray();
176
+ expect(indexes).toEqual([0, 1, 2, 3]);
177
+ });
178
+ });
179
+ describe("method: update", () => {
180
+ test("Should change all the items that match the filter function", () => {
181
+ const collection = new IterableCollection([
182
+ "a",
183
+ "aa",
184
+ "b",
185
+ "bbb",
186
+ "c",
187
+ "cccc",
188
+ ]),
189
+ newCollection = collection.update(
190
+ (item) => item.length >= 2,
191
+ (item) => item.slice(0, -1),
192
+ );
193
+ expect(newCollection.toArray()).toEqual([
194
+ "a",
195
+ "a",
196
+ "b",
197
+ "bb",
198
+ "c",
199
+ "ccc",
200
+ ]);
201
+ });
202
+ test("Should input correct indexes to filter function", () => {
203
+ const collection = new IterableCollection([
204
+ "a",
205
+ "aa",
206
+ "b",
207
+ "bbb",
208
+ "c",
209
+ "cccc",
210
+ ]),
211
+ indexes: number[] = [];
212
+ collection
213
+ .update(
214
+ (item, index) => {
215
+ indexes.push(index);
216
+ return item.length >= 2;
217
+ },
218
+ (item) => item.slice(0, -1),
219
+ )
220
+ .toArray();
221
+ expect(indexes).toEqual([0, 1, 2, 3, 4, 5]);
222
+ });
223
+ test("Should input correct indexes to map function", () => {
224
+ const collection = new IterableCollection([
225
+ "a",
226
+ "aa",
227
+ "b",
228
+ "bbb",
229
+ "c",
230
+ "cccc",
231
+ ]),
232
+ indexes: number[] = [];
233
+ collection
234
+ .update(
235
+ (item) => item.length >= 2,
236
+ (item, index) => {
237
+ indexes.push(index);
238
+ return item.slice(0, -1);
239
+ },
240
+ )
241
+ .toArray();
242
+ expect(indexes).toEqual([1, 3, 5]);
243
+ });
244
+ });
245
+ describe("method: page", () => {
246
+ test("Should return the first 4 items when page is 1 and pageSize 4", () => {
247
+ const arr = ["a", "b", "c", "d", "e", "f", "g", "h"],
248
+ collection = new IterableCollection(arr),
249
+ newCollection = collection.page({
250
+ page: 1,
251
+ pageSize: 4,
252
+ });
253
+ expect(newCollection.toArray()).toEqual(arr.slice(0, 4));
254
+ });
255
+ test("Should return the last 4 items when page is 2 and pageSize 4", () => {
256
+ const arr = ["a", "b", "c", "d", "e", "f", "g", "h"],
257
+ collection = new IterableCollection(arr),
258
+ newCollection = collection.page({
259
+ page: 2,
260
+ pageSize: 4,
261
+ });
262
+ expect(newCollection.toArray()).toEqual(arr.slice(-4));
263
+ });
264
+ test("Should return the last 4 items when page is -1 and pageSize 4", () => {
265
+ const arr = ["a", "b", "c", "d", "e", "f", "g", "h"],
266
+ collection = new IterableCollection(arr),
267
+ newCollection = collection.page({
268
+ page: -1,
269
+ pageSize: 4,
270
+ });
271
+ expect(newCollection.toArray()).toEqual(arr.slice(-4));
272
+ });
273
+ test("Should return the first 2 items when page is 1 and pageSize 2", () => {
274
+ const arr = ["a", "b", "c", "d", "e", "f", "g", "h"],
275
+ collection = new IterableCollection(arr),
276
+ newCollection = collection.page({
277
+ page: 1,
278
+ pageSize: 2,
279
+ });
280
+ expect(newCollection.toArray()).toEqual(arr.slice(0, 2));
281
+ });
282
+ test("Should return the last 2 items when page is 4 and pageSize 2", () => {
283
+ const arr = ["a", "b", "c", "d", "e", "f", "g", "h"],
284
+ collection = new IterableCollection(arr),
285
+ newCollection = collection.page({
286
+ page: 4,
287
+ pageSize: 2,
288
+ });
289
+ expect(newCollection.toArray()).toEqual(arr.slice(-2));
290
+ });
291
+ test("Should return the last 2 items when page is -1 and pageSize 2", () => {
292
+ const arr = ["a", "b", "c", "d", "e", "f", "g", "h"],
293
+ collection = new IterableCollection(arr),
294
+ newCollection = collection.page({
295
+ page: -1,
296
+ pageSize: 2,
297
+ });
298
+ expect(newCollection.toArray()).toEqual(arr.slice(-2));
299
+ });
300
+ test("Should return the last 2 items when page is -4 and pageSize -2", () => {
301
+ const arr = ["a", "b", "c", "d", "e", "f", "g", "h"],
302
+ collection = new IterableCollection(arr),
303
+ newCollection = collection.page({
304
+ page: -2,
305
+ pageSize: 2,
306
+ });
307
+ expect(newCollection.toArray()).toEqual(arr.slice(-4, -2));
308
+ });
309
+ });
310
+ describe("method: sum", () => {
311
+ test("Should calculate sum iterable of [1, 2, 3, 4] to 10", () => {
312
+ const collection = new IterableCollection([1, 2, 3, 4]);
313
+ expect(collection.sum()).toBe(10);
314
+ });
315
+ test("Should throw TypeError when containg a none number item", () => {
316
+ const collection = new IterableCollection([1, 2, 3, 4, "a"]);
317
+ expect(() => {
318
+ collection.sum();
319
+ }).toThrowError(TypeError);
320
+ });
321
+ test("Should return the same value when called more than 1 times", () => {
322
+ const collection = new IterableCollection([1, 2, 3, 4]);
323
+ expect(collection.sum()).toBe(10);
324
+ expect(collection.sum()).toBe(10);
325
+ });
326
+ });
327
+ describe("method: average", () => {
328
+ test("Should calculate average iterable of [1, 2, 3, 4] to 2.5", () => {
329
+ const collection = new IterableCollection([1, 2, 3, 4]);
330
+ expect(collection.average()).toBe(2.5);
331
+ });
332
+ test("Should throw TypeError when containg a none number item", () => {
333
+ const collection = new IterableCollection([1, 2, 3, 4, "a"]);
334
+ expect(() => {
335
+ collection.average();
336
+ }).toThrowError(TypeError);
337
+ });
338
+ test("Should return the same value when called more than 1 times", () => {
339
+ const collection = new IterableCollection([1, 2, 3, 4]);
340
+ expect(collection.average()).toBe(2.5);
341
+ expect(collection.average()).toBe(2.5);
342
+ });
343
+ });
344
+ describe("method: median", () => {
345
+ test("Should calculate median iterable of [1, 2, 3, 4, 5] to 3", () => {
346
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
347
+ expect(collection.median()).toBe(3);
348
+ });
349
+ test("Should calculate median iterable of [1, 2, 4, 5] to 3", () => {
350
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
351
+ expect(collection.median()).toBe(3);
352
+ });
353
+ test("Should throw TypeError when containg a none number item", () => {
354
+ const collection = new IterableCollection([1, 2, 3, 4, "a"]);
355
+ expect(() => {
356
+ collection.median();
357
+ }).toThrowError(TypeError);
358
+ });
359
+ test("Should return the same value when called more than 1 times", () => {
360
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
361
+ expect(collection.median()).toBe(3);
362
+ expect(collection.median()).toBe(3);
363
+ });
364
+ });
365
+ describe("method: min", () => {
366
+ test("Should return the smallest number", () => {
367
+ const collection = new IterableCollection([2, 1, 3, -2, 4]);
368
+ expect(collection.min()).toBe(-2);
369
+ });
370
+ test("Should throw TypeError when containg a none number item", () => {
371
+ const collection = new IterableCollection([2, 1, 3, -2, 4, "-4"]);
372
+ expect(() => {
373
+ collection.min();
374
+ }).toThrowError(TypeError);
375
+ });
376
+ test("Should return the same value when called more than 1 times", () => {
377
+ const collection = new IterableCollection([2, 1, 3, -2, 4]);
378
+ expect(collection.min()).toBe(-2);
379
+ expect(collection.min()).toBe(-2);
380
+ });
381
+ });
382
+ describe("method: max", () => {
383
+ test("Should return the largest number", () => {
384
+ const collection = new IterableCollection([2, 1, 3, -2, 4]);
385
+ expect(collection.max()).toBe(4);
386
+ });
387
+ test("Should throw TypeError when containg a none number item", () => {
388
+ const collection = new IterableCollection([2, 1, 3, -2, 4, "-4"]);
389
+ expect(() => {
390
+ collection.max();
391
+ }).toThrowError(TypeError);
392
+ });
393
+ test("Should return the same value when called more than 1 times", () => {
394
+ const collection = new IterableCollection([2, 1, 3, -2, 4]);
395
+ expect(collection.max()).toBe(4);
396
+ expect(collection.max()).toBe(4);
397
+ });
398
+ });
399
+ describe("method: percentage", () => {
400
+ test(`Should return 50 when filtering "a" of ["a", "b", "a", "c"]`, () => {
401
+ const collection = new IterableCollection(["a", "b", "a", "b"]);
402
+ expect(collection.percentage((item) => item === "a")).toBe(50);
403
+ });
404
+ test("Should input correct indexes to filter function", () => {
405
+ const collection = new IterableCollection([
406
+ "a",
407
+ "bc",
408
+ "c",
409
+ "a",
410
+ "d",
411
+ "a",
412
+ ]),
413
+ indexes: number[] = [],
414
+ filterFunction = (item: string, index: number): boolean => {
415
+ indexes.push(index);
416
+ return item === "a";
417
+ };
418
+ collection.percentage(filterFunction);
419
+ expect(indexes).toEqual([0, 1, 2, 3, 4, 5]);
420
+ });
421
+ test("Should return the same value when called more than 1 times", () => {
422
+ const collection = new IterableCollection(["a", "b", "a", "b"]);
423
+ expect(collection.percentage((item) => item === "a")).toBe(50);
424
+ expect(collection.percentage((item) => item === "a")).toBe(50);
425
+ });
426
+ });
427
+ describe("method: some", () => {
428
+ test("Should return true when at least 1 item match the filter function", () => {
429
+ const collection = new IterableCollection([
430
+ "a",
431
+ "b",
432
+ "c",
433
+ "c",
434
+ "a",
435
+ ]);
436
+ expect(collection.some((item) => item === "b")).toBe(true);
437
+ });
438
+ test("Should return false when all of the items does not match the filter function", () => {
439
+ const collection = new IterableCollection([
440
+ "a",
441
+ "b",
442
+ "c",
443
+ "c",
444
+ "a",
445
+ ]);
446
+ expect(collection.some((item) => item === "d")).toBe(false);
447
+ });
448
+ test("Should input correct indexes to filter function", () => {
449
+ const collection = new IterableCollection([
450
+ "a",
451
+ "bc",
452
+ "c",
453
+ "a",
454
+ "d",
455
+ "a",
456
+ ]),
457
+ indexes: number[] = [],
458
+ filterFunction = (item: string, index: number): boolean => {
459
+ indexes.push(index);
460
+ return item === "a";
461
+ };
462
+ collection.some(filterFunction);
463
+ expect(indexes).toEqual([0]);
464
+ });
465
+ test("Should return the same value when called more than 1 times", () => {
466
+ const collection = new IterableCollection([
467
+ "a",
468
+ "b",
469
+ "c",
470
+ "c",
471
+ "a",
472
+ ]);
473
+ expect(collection.some((item) => item === "b")).toBe(true);
474
+ expect(collection.some((item) => item === "b")).toBe(true);
475
+ });
476
+ });
477
+ describe("method: every", () => {
478
+ test("Should return true when all items match the filter function", () => {
479
+ const collection = new IterableCollection([
480
+ "a",
481
+ "b",
482
+ "c",
483
+ "c",
484
+ "a",
485
+ ]);
486
+ expect(collection.every((item) => item.length === 1)).toBe(true);
487
+ });
488
+ test("Should return false when one item does not match the filter function", () => {
489
+ const collection = new IterableCollection([
490
+ "a",
491
+ "b",
492
+ "c",
493
+ "c",
494
+ "aa",
495
+ ]);
496
+ expect(collection.every((item) => item.length === 1)).toBe(false);
497
+ });
498
+ test("Should input correct indexes to filter function", () => {
499
+ const collection = new IterableCollection([
500
+ "a",
501
+ "b",
502
+ "c",
503
+ "c",
504
+ "aa",
505
+ ]),
506
+ indexes: number[] = [];
507
+ collection.every((item, index) => {
508
+ indexes.push(index);
509
+ return item.length === 1;
510
+ });
511
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
512
+ });
513
+ test("Should return the same value when called more than 1 times", () => {
514
+ const collection = new IterableCollection([
515
+ "a",
516
+ "b",
517
+ "c",
518
+ "c",
519
+ "a",
520
+ ]);
521
+ expect(collection.every((item) => item.length === 1)).toBe(true);
522
+ expect(collection.every((item) => item.length === 1)).toBe(true);
523
+ });
524
+ });
525
+ describe("method: take", () => {
526
+ test("Should take first item when input is 1", () => {
527
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
528
+ collection = new IterableCollection(arr),
529
+ newCollection = collection.take(1);
530
+ expect(newCollection.toArray()).toEqual(arr.slice(0, 1));
531
+ });
532
+ test("Should take 5 first items when input is 5", () => {
533
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
534
+ collection = new IterableCollection(arr),
535
+ newCollection = collection.take(5);
536
+ expect(newCollection.toArray()).toEqual(arr.slice(0, 5));
537
+ });
538
+ test("Should take 8 first items when input is -2", () => {
539
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
540
+ collection = new IterableCollection(arr),
541
+ newCollection = collection.take(-2);
542
+ expect(newCollection.toArray()).toEqual(arr.slice(0, -2));
543
+ });
544
+ });
545
+ describe("method: takeUntil", () => {
546
+ test("Should take all items until item is larger or equal to 3", () => {
547
+ const collection = new IterableCollection([1, 2, 3, 4]),
548
+ newCollection = collection.takeUntil((item) => item >= 3);
549
+ expect(newCollection.toArray()).toEqual([1, 2]);
550
+ });
551
+ test("Should input correct indexes to filter function", () => {
552
+ const collection = new IterableCollection([1, 2, 3, 4]),
553
+ indexes: number[] = [];
554
+ collection
555
+ .takeUntil((item, index) => {
556
+ indexes.push(index);
557
+ return item >= 3;
558
+ })
559
+ .toArray();
560
+ expect(indexes).toEqual([0, 1, 2]);
561
+ });
562
+ });
563
+ describe("method: takeWhile", () => {
564
+ test("Should take all items while item is less than 3", () => {
565
+ const collection = new IterableCollection([1, 2, 3, 4]),
566
+ newCollection = collection.takeWhile((item) => item < 3);
567
+ expect(newCollection.toArray()).toEqual([1, 2]);
568
+ });
569
+ test("Should input correct indexes to filter function", () => {
570
+ const collection = new IterableCollection([1, 2, 3, 4]),
571
+ indexes: number[] = [];
572
+ collection
573
+ .takeWhile((item, index) => {
574
+ indexes.push(index);
575
+ return item < 3;
576
+ })
577
+ .toArray();
578
+ expect(indexes).toEqual([0, 1, 2]);
579
+ });
580
+ });
581
+ describe("method: skip", () => {
582
+ test("Should skip first item when input is 1", () => {
583
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
584
+ collection = new IterableCollection(arr),
585
+ newCollection = collection.skip(1);
586
+ expect(newCollection.toArray()).toEqual(arr.slice(1));
587
+ });
588
+ test("Should skip 5 first items when input is 5", () => {
589
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
590
+ collection = new IterableCollection(arr),
591
+ newCollection = collection.skip(5);
592
+ expect(newCollection.toArray()).toEqual(arr.slice(5));
593
+ });
594
+ test("Should skip 8 first items when input is -2", () => {
595
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
596
+ collection = new IterableCollection(arr),
597
+ newCollection = collection.skip(-2);
598
+ expect(newCollection.toArray()).toEqual(arr.slice(-2));
599
+ });
600
+ });
601
+ describe("method: skipUntil", () => {
602
+ test("Should skip all items until item is larger or equal to 3", () => {
603
+ const collection = new IterableCollection([1, 2, 3, 4]),
604
+ newCollection = collection.skipUntil((item) => item >= 3);
605
+ expect(newCollection.toArray()).toEqual([3, 4]);
606
+ });
607
+ test("Should input correct indexes to filter function", () => {
608
+ const collection = new IterableCollection([1, 2, 3, 4]),
609
+ indexes: number[] = [];
610
+ collection
611
+ .skipUntil((item, index) => {
612
+ indexes.push(index);
613
+ return item >= 3;
614
+ })
615
+ .toArray();
616
+ expect(indexes).toEqual([0, 1, 2]);
617
+ });
618
+ });
619
+ describe("method: skipWhile", () => {
620
+ test("Should skipp all items while item is less than 3", () => {
621
+ const collection = new IterableCollection([1, 2, 3, 4]),
622
+ newCollection = collection.skipWhile((item) => item <= 3);
623
+ expect(newCollection.toArray()).toEqual([4]);
624
+ });
625
+ test("Should input correct indexes to filter function", () => {
626
+ const collection = new IterableCollection([1, 2, 3, 4]),
627
+ indexes: number[] = [];
628
+ collection
629
+ .skipWhile((item, index) => {
630
+ indexes.push(index);
631
+ return item <= 3;
632
+ })
633
+ .toArray();
634
+ expect(indexes).toEqual([0, 1, 2, 3]);
635
+ });
636
+ });
637
+ describe("method: when", () => {
638
+ test("Should append items when statement is true", () => {
639
+ const arr1 = ["a", "b", "c"],
640
+ collection = new IterableCollection(arr1),
641
+ arr2 = [1, 2, 3],
642
+ newCollection = collection.when(true, (collection) =>
643
+ collection.append(arr2),
644
+ );
645
+ expect(newCollection.toArray()).toEqual([...arr1, ...arr2]);
646
+ });
647
+ test("Should not append items when statement is false", () => {
648
+ const arr1 = ["a", "b", "c"],
649
+ collection = new IterableCollection(arr1),
650
+ arr2 = [1, 2, 3],
651
+ newCollection = collection.when(false, (collection) =>
652
+ collection.append(arr2),
653
+ );
654
+ expect(newCollection.toArray()).toEqual(arr1);
655
+ });
656
+ });
657
+ describe("method: whenEmpty", () => {
658
+ test("Should append items when empty", () => {
659
+ const collection = new IterableCollection<string>([]),
660
+ arr2 = [1, 2, 3],
661
+ newCollection = collection.whenEmpty((collection) =>
662
+ collection.append(arr2),
663
+ );
664
+ expect(newCollection.toArray()).toEqual(arr2);
665
+ });
666
+ test("Should not append items when not empty", () => {
667
+ const arr1 = ["a", "b", "c"],
668
+ collection = new IterableCollection(arr1),
669
+ arr2 = [1, 2, 3],
670
+ newCollection = collection.whenEmpty((collection) =>
671
+ collection.append(arr2),
672
+ );
673
+ expect(newCollection.toArray()).toEqual(arr1);
674
+ });
675
+ });
676
+ describe("method: whenNot", () => {
677
+ test("Should append items when statement is false", () => {
678
+ const arr1 = ["a", "b", "c"],
679
+ collection = new IterableCollection(arr1),
680
+ arr2 = [1, 2, 3],
681
+ newCollection = collection.whenNot(false, (collection) =>
682
+ collection.append(arr2),
683
+ );
684
+ expect(newCollection.toArray()).toEqual([...arr1, ...arr2]);
685
+ });
686
+ test("Should not append items when statement is true", () => {
687
+ const arr1 = ["a", "b", "c"],
688
+ collection = new IterableCollection(arr1),
689
+ arr2 = [1, 2, 3],
690
+ newCollection = collection.whenNot(true, (collection) =>
691
+ collection.append(arr2),
692
+ );
693
+ expect(newCollection.toArray()).toEqual(arr1);
694
+ });
695
+ });
696
+ describe("method: whenNotEmpty", () => {
697
+ test("Should append items when not empty", () => {
698
+ const arr1 = ["a", "b", "c"],
699
+ collection = new IterableCollection(arr1),
700
+ arr2 = [1, 2, 3],
701
+ newCollection = collection.whenNotEmpty((collection) =>
702
+ collection.append(arr2),
703
+ );
704
+ expect(newCollection.toArray()).toEqual([...arr1, ...arr2]);
705
+ });
706
+ test("Should not append items when empty", () => {
707
+ const collection = new IterableCollection([]),
708
+ arr2 = [1, 2, 3],
709
+ newCollection = collection.whenNotEmpty((collection) =>
710
+ collection.append(arr2),
711
+ );
712
+ expect(newCollection.toArray()).toEqual([]);
713
+ });
714
+ });
715
+ describe("method: pipe", () => {
716
+ test("Should pipe multiple functions", () => {
717
+ const collection = new IterableCollection([
718
+ "a",
719
+ "ab",
720
+ "abc",
721
+ "abcd",
722
+ ]),
723
+ result = collection
724
+ .pipe((collection) =>
725
+ collection.map((item) =>
726
+ new IterableCollection(item).map((char) =>
727
+ char.charCodeAt(0),
728
+ ),
729
+ ),
730
+ )
731
+ .pipe((collection) =>
732
+ collection.map((collection) => collection.sum()),
733
+ )
734
+ .pipe((collection) => collection.sum());
735
+ expect(result).toBeTypeOf("number");
736
+ });
737
+ });
738
+ describe("method: tap", () => {
739
+ test("Should change the original collection", () => {
740
+ const arr = ["a", "ab", "abc"],
741
+ collection = new IterableCollection(arr).tap((collection) =>
742
+ collection.map((item) => item.length),
743
+ );
744
+ expect(collection.toArray()).toEqual(arr);
745
+ });
746
+ });
747
+ describe("method: chunk", () => {
748
+ test("Should group items into groups of size 1", () => {
749
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8],
750
+ collection = new IterableCollection(arr),
751
+ newCollection = collection.chunk(1);
752
+ expect(
753
+ newCollection.map((item) => item.toArray()).toArray(),
754
+ ).toEqual(arr.map((item) => [item]));
755
+ });
756
+ test("Should group items into groups of size 4", () => {
757
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8],
758
+ collection = new IterableCollection(arr),
759
+ newCollection = collection.chunk(4);
760
+ expect(
761
+ newCollection.map((item) => item.toArray()).toArray(),
762
+ ).toEqual([arr.slice(0, 4), arr.slice(4)]);
763
+ });
764
+ });
765
+ describe("method: chunkWhile", () => {
766
+ test("Should group items by checking if next item is the same as the current item", () => {
767
+ const collection = new IterableCollection("AABBCCCD".split("")),
768
+ newCollection = collection.chunkWhile(
769
+ (value, _index, chunk) => value === chunk.last(),
770
+ );
771
+ expect(
772
+ newCollection.map((item) => item.toArray()).toArray(),
773
+ ).toEqual([["A", "A"], ["B", "B"], ["C", "C", "C"], ["D"]]);
774
+ });
775
+ });
776
+ describe("method: split", () => {
777
+ test("Should split items into 3 groups in equal size when size is 9", () => {
778
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9],
779
+ collection = new IterableCollection(arr),
780
+ newCollection = collection.split(3);
781
+ expect(
782
+ newCollection.map((item) => item.toArray()).toArray(),
783
+ ).toEqual([arr.slice(0, 3), arr.slice(3, 6), arr.slice(6, 9)]);
784
+ });
785
+ test("Should split items into 3 groups where the first group have on item more when size is 10", () => {
786
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
787
+ collection = new IterableCollection(arr),
788
+ newCollection = collection.split(3);
789
+ expect(
790
+ newCollection.map((item) => item.toArray()).toArray(),
791
+ ).toEqual([arr.slice(0, 4), arr.slice(4, 7), arr.slice(7, 10)]);
792
+ });
793
+ test("Should split items into 3 groups where the first and second group have on item more when size is 11", () => {
794
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
795
+ collection = new IterableCollection(arr),
796
+ newCollection = collection.split(3);
797
+ expect(
798
+ newCollection.map((item) => item.toArray()).toArray(),
799
+ ).toEqual([arr.slice(0, 4), arr.slice(4, 8), arr.slice(8, 11)]);
800
+ });
801
+ });
802
+ describe("method: partition", () => {
803
+ test("Should group items into strings and number", () => {
804
+ const arr = ["a", 1, "b", 2, "c", 3, "d", 4, "e", 5],
805
+ collection = new IterableCollection(arr),
806
+ newCollection = collection.partition(
807
+ (item) => typeof item === "string",
808
+ );
809
+ expect(
810
+ newCollection.map((item) => item.toArray()).toArray(),
811
+ ).toEqual([
812
+ arr.filter((item) => typeof item === "string"),
813
+ arr.filter((item) => typeof item === "number"),
814
+ ]);
815
+ });
816
+ test("Should input correct indexes to filter function", () => {
817
+ const arr = ["a", 1, "b", 2, "c", 3, "d", 4, "e", 5],
818
+ collection = new IterableCollection(arr),
819
+ indexes: number[] = [];
820
+ collection
821
+ .partition((item, index) => {
822
+ indexes.push(index);
823
+ return typeof item === "string";
824
+ })
825
+ .toArray();
826
+ expect(indexes).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
827
+ });
828
+ });
829
+ describe("method: sliding", () => {
830
+ test("Should group items into 7 groups when size is 2", () => {
831
+ const collection = new IterableCollection([
832
+ "a",
833
+ "b",
834
+ "c",
835
+ "d",
836
+ "e",
837
+ "f",
838
+ "g",
839
+ "h",
840
+ ]),
841
+ newCollection = collection.sliding({ chunkSize: 2 });
842
+ expect(
843
+ newCollection.map((item) => item.toArray()).toArray(),
844
+ ).toEqual([
845
+ ["a", "b"],
846
+ ["b", "c"],
847
+ ["c", "d"],
848
+ ["d", "e"],
849
+ ["e", "f"],
850
+ ["f", "g"],
851
+ ["g", "h"],
852
+ ]);
853
+ });
854
+ test("Should group items into 4 groups when size is 3", () => {
855
+ const collection = new IterableCollection([
856
+ "a",
857
+ "b",
858
+ "c",
859
+ "d",
860
+ "e",
861
+ "f",
862
+ "g",
863
+ "h",
864
+ ]),
865
+ newCollection = collection.sliding({ chunkSize: 3 });
866
+ expect(
867
+ newCollection.map((item) => item.toArray()).toArray(),
868
+ ).toEqual([
869
+ ["a", "b", "c"],
870
+ ["c", "d", "e"],
871
+ ["e", "f", "g"],
872
+ ["g", "h"],
873
+ ]);
874
+ });
875
+ test("Should group items into 6 groups when size is 3 and step is 1", () => {
876
+ const collection = new IterableCollection([
877
+ "a",
878
+ "b",
879
+ "c",
880
+ "d",
881
+ "e",
882
+ "f",
883
+ "g",
884
+ "h",
885
+ ]),
886
+ newCollection = collection.sliding({ chunkSize: 3, step: 1 });
887
+ expect(
888
+ newCollection.map((item) => item.toArray()).toArray(),
889
+ ).toEqual([
890
+ ["a", "b", "c"],
891
+ ["b", "c", "d"],
892
+ ["c", "d", "e"],
893
+ ["d", "e", "f"],
894
+ ["e", "f", "g"],
895
+ ["f", "g", "h"],
896
+ ]);
897
+ });
898
+ test("Should group items into 6 groups when size is 4 and step is 2", () => {
899
+ const collection = new IterableCollection([
900
+ "a",
901
+ "b",
902
+ "c",
903
+ "d",
904
+ "e",
905
+ "f",
906
+ "g",
907
+ "h",
908
+ ]),
909
+ newCollection = collection.sliding({ chunkSize: 4, step: 2 });
910
+ expect(
911
+ newCollection.map((item) => item.toArray()).toArray(),
912
+ ).toEqual([
913
+ ["a", "b", "c", "d"],
914
+ ["c", "d", "e", "f"],
915
+ ["e", "f", "g", "h"],
916
+ ]);
917
+ });
918
+ test("Should group items into 4 groups when size is 1 and step is 2", () => {
919
+ const collection = new IterableCollection([
920
+ "a",
921
+ "b",
922
+ "c",
923
+ "d",
924
+ "e",
925
+ "f",
926
+ "g",
927
+ "h",
928
+ ]),
929
+ newCollection = collection.sliding({ chunkSize: 1, step: 2 });
930
+ expect(
931
+ newCollection.map((item) => item.toArray()).toArray(),
932
+ ).toEqual([["a"], ["c"], ["e"], ["g"]]);
933
+ });
934
+ test("Should group items into 3 groups when size is 1 and step is 3", () => {
935
+ const collection = new IterableCollection([
936
+ "a",
937
+ "b",
938
+ "c",
939
+ "d",
940
+ "e",
941
+ "f",
942
+ "g",
943
+ "h",
944
+ ]),
945
+ newCollection = collection.sliding({ chunkSize: 1, step: 3 });
946
+ expect(
947
+ newCollection.map((item) => item.toArray()).toArray(),
948
+ ).toEqual([["a"], ["d"], ["g"]]);
949
+ });
950
+ test("Should group items into 2 groups when size is 1 and step is 4", () => {
951
+ const collection = new IterableCollection([
952
+ "a",
953
+ "b",
954
+ "c",
955
+ "d",
956
+ "e",
957
+ "f",
958
+ "g",
959
+ "h",
960
+ ]),
961
+ newCollection = collection.sliding({ chunkSize: 1, step: 3 });
962
+ expect(
963
+ newCollection.map((item) => item.toArray()).toArray(),
964
+ ).toEqual([["a"], ["d"], ["g"]]);
965
+ });
966
+ test("Should group items into 1 groups when size is 2 and step is 1 and array size is 2", () => {
967
+ const collection = new IterableCollection(["a", "b"]),
968
+ newCollection = collection.sliding({ chunkSize: 2, step: 1 });
969
+ expect(
970
+ newCollection.map((item) => item.toArray()).toArray(),
971
+ ).toEqual([["a", "b"]]);
972
+ });
973
+ test("Should group items into 1 groups when size is 2 and step is 2 and array size is 2", () => {
974
+ const collection = new IterableCollection(["a", "b"]),
975
+ newCollection = collection.sliding({ chunkSize: 2, step: 2 });
976
+ expect(
977
+ newCollection.map((item) => item.toArray()).toArray(),
978
+ ).toEqual([["a", "b"]]);
979
+ });
980
+ test("Should group items into 1 groups when size is 3 and step is 2 and array size is 2", () => {
981
+ const collection = new IterableCollection(["a", "b"]),
982
+ newCollection = collection.sliding({ chunkSize: 2, step: 3 });
983
+ expect(
984
+ newCollection.map((item) => item.toArray()).toArray(),
985
+ ).toEqual([["a", "b"]]);
986
+ });
987
+ test("Should group items into 1 groups when size is 2 and step is 3 and array size is 2", () => {
988
+ const collection = new IterableCollection(["a", "b"]),
989
+ newCollection = collection.sliding({ chunkSize: 3, step: 2 });
990
+ expect(
991
+ newCollection.map((item) => item.toArray()).toArray(),
992
+ ).toEqual([["a", "b"]]);
993
+ });
994
+ test("Should return empty collection when size is 1", () => {
995
+ const collection = new IterableCollection([
996
+ "a",
997
+ "b",
998
+ "c",
999
+ "d",
1000
+ "e",
1001
+ "f",
1002
+ "g",
1003
+ "h",
1004
+ ]),
1005
+ newCollection = collection.sliding({ chunkSize: 1 });
1006
+ expect(newCollection.toArray()).toEqual([]);
1007
+ });
1008
+ });
1009
+ describe("method: groupBy", () => {
1010
+ test("Should group by with default map function", () => {
1011
+ const arr = ["a", "b", "c", "a", "b", "c", "b", "d"],
1012
+ collection = new IterableCollection(arr),
1013
+ newCollection = collection.groupBy();
1014
+ expect(
1015
+ newCollection
1016
+ .map(
1017
+ ([key, item]): RecordItem<string, string[]> => [
1018
+ key,
1019
+ item.toArray(),
1020
+ ],
1021
+ )
1022
+ .toArray(),
1023
+ ).toEqual([
1024
+ ["a", arr.filter((item) => item === "a")],
1025
+ ["b", arr.filter((item) => item === "b")],
1026
+ ["c", arr.filter((item) => item === "c")],
1027
+ ["d", arr.filter((item) => item === "d")],
1028
+ ]);
1029
+ });
1030
+ test("Should group by with custom map function", () => {
1031
+ type Person = {
1032
+ name: string;
1033
+ age: number;
1034
+ };
1035
+ const arr: Person[] = [
1036
+ {
1037
+ name: "Abra",
1038
+ age: 20,
1039
+ },
1040
+ {
1041
+ name: "Asmail",
1042
+ age: 34,
1043
+ },
1044
+ {
1045
+ name: "Ibra",
1046
+ age: 50,
1047
+ },
1048
+ {
1049
+ name: "Asmail",
1050
+ age: 21,
1051
+ },
1052
+ {
1053
+ name: "Abra",
1054
+ age: 32,
1055
+ },
1056
+ {
1057
+ name: "Abra",
1058
+ age: 67,
1059
+ },
1060
+ ],
1061
+ collection = new IterableCollection<Person>(arr),
1062
+ newCollection = collection.groupBy({
1063
+ mapFn(item) {
1064
+ return item.name;
1065
+ },
1066
+ });
1067
+ expect(
1068
+ newCollection
1069
+ .map(
1070
+ ([key, item]): RecordItem<string, Person[]> => [
1071
+ key,
1072
+ item.toArray(),
1073
+ ],
1074
+ )
1075
+ .toArray(),
1076
+ ).toEqual([
1077
+ ["Abra", arr.filter((item) => item.name === "Abra")],
1078
+ ["Asmail", arr.filter((item) => item.name === "Asmail")],
1079
+ ["Ibra", arr.filter((item) => item.name === "Ibra")],
1080
+ ]);
1081
+ });
1082
+ test("Should input correct indexes to filter function", () => {
1083
+ const collection = new IterableCollection([
1084
+ "a",
1085
+ "b",
1086
+ "c",
1087
+ "a",
1088
+ "b",
1089
+ "c",
1090
+ "b",
1091
+ "d",
1092
+ ]),
1093
+ indexes: number[] = [];
1094
+ collection
1095
+ .groupBy({
1096
+ mapFn: (item, index) => {
1097
+ indexes.push(index);
1098
+ return item;
1099
+ },
1100
+ })
1101
+ .toArray();
1102
+ expect(indexes).toEqual([0, 1, 2, 3, 4, 5, 6, 7]);
1103
+ });
1104
+ });
1105
+ describe("method: countBy", () => {
1106
+ test("Should count by with default map function", () => {
1107
+ const arr = ["a", "b", "c", "a", "b", "c", "b", "d"],
1108
+ collection = new IterableCollection(arr),
1109
+ newCollection = collection.countBy();
1110
+ expect(newCollection.toArray()).toEqual([
1111
+ ["a", arr.filter((item) => item === "a").length],
1112
+ ["b", arr.filter((item) => item === "b").length],
1113
+ ["c", arr.filter((item) => item === "c").length],
1114
+ ["d", arr.filter((item) => item === "d").length],
1115
+ ]);
1116
+ });
1117
+ test("Should count by with custom map function", () => {
1118
+ type Person = {
1119
+ name: string;
1120
+ age: number;
1121
+ };
1122
+ const arr: Person[] = [
1123
+ {
1124
+ name: "Abra",
1125
+ age: 20,
1126
+ },
1127
+ {
1128
+ name: "Asmail",
1129
+ age: 34,
1130
+ },
1131
+ {
1132
+ name: "Ibra",
1133
+ age: 50,
1134
+ },
1135
+ {
1136
+ name: "Asmail",
1137
+ age: 21,
1138
+ },
1139
+ {
1140
+ name: "Abra",
1141
+ age: 32,
1142
+ },
1143
+ {
1144
+ name: "Abra",
1145
+ age: 67,
1146
+ },
1147
+ ],
1148
+ collection = new IterableCollection<Person>(arr),
1149
+ newCollection = collection.countBy({
1150
+ mapFn(item) {
1151
+ return item.name;
1152
+ },
1153
+ });
1154
+ expect(newCollection.toArray()).toEqual([
1155
+ ["Abra", arr.filter((item) => item.name === "Abra").length],
1156
+ ["Asmail", arr.filter((item) => item.name === "Asmail").length],
1157
+ ["Ibra", arr.filter((item) => item.name === "Ibra").length],
1158
+ ]);
1159
+ });
1160
+ test("Should input correct indexes to filter function", () => {
1161
+ const collection = new IterableCollection([
1162
+ "a",
1163
+ "b",
1164
+ "c",
1165
+ "a",
1166
+ "b",
1167
+ "c",
1168
+ "b",
1169
+ "d",
1170
+ ]),
1171
+ indexes: number[] = [];
1172
+ collection
1173
+ .countBy({
1174
+ mapFn: (item, index) => {
1175
+ indexes.push(index);
1176
+ return item;
1177
+ },
1178
+ })
1179
+ .toArray();
1180
+ expect(indexes).toEqual([0, 1, 2, 3, 4, 5, 6, 7]);
1181
+ });
1182
+ });
1183
+ describe("method: unique", () => {
1184
+ test("Should return unique items with default map function", () => {
1185
+ const collection = new IterableCollection([
1186
+ "a",
1187
+ "b",
1188
+ "c",
1189
+ "a",
1190
+ "b",
1191
+ "c",
1192
+ ]),
1193
+ newCollection = collection.unique();
1194
+ expect(newCollection.toArray()).toEqual(["a", "b", "c"]);
1195
+ });
1196
+ test("Should return unique items with custom map function", () => {
1197
+ const collection = new IterableCollection([
1198
+ "a",
1199
+ "bb",
1200
+ "cc",
1201
+ "acc",
1202
+ "b",
1203
+ "cccc",
1204
+ ]),
1205
+ newCollection = collection.unique({
1206
+ mapFn(item) {
1207
+ return item.length;
1208
+ },
1209
+ });
1210
+ expect(newCollection.toArray()).toEqual(["a", "bb", "acc", "cccc"]);
1211
+ });
1212
+ test("Should input correct indexes to filter function", () => {
1213
+ const collection = new IterableCollection([
1214
+ "a",
1215
+ "b",
1216
+ "c",
1217
+ "a",
1218
+ "b",
1219
+ "c",
1220
+ "b",
1221
+ "d",
1222
+ ]),
1223
+ indexes: number[] = [];
1224
+ collection
1225
+ .unique({
1226
+ mapFn: (item, index) => {
1227
+ indexes.push(index);
1228
+ return item;
1229
+ },
1230
+ })
1231
+ .toArray();
1232
+ expect(indexes).toEqual([0, 1, 2, 3, 4, 5, 6, 7]);
1233
+ });
1234
+ });
1235
+ describe("method: difference", () => {
1236
+ test("Should remove all elements matches the given iterable elements", () => {
1237
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1238
+ const difference = collection.difference([2, 4, 6, 8]);
1239
+ expect(difference.toArray()).toEqual([1, 3, 5]);
1240
+ });
1241
+ });
1242
+ describe("method: repeat", () => {
1243
+ test("Should repeath all elements 2 times when input is 3", () => {
1244
+ const arr = [1, 2, 3];
1245
+ const collection = new IterableCollection(arr);
1246
+ const newCollection = collection.repeat(4);
1247
+ expect(newCollection.toArray()).toEqual([...arr, ...arr, ...arr]);
1248
+ });
1249
+ });
1250
+ describe("method: padStart", () => {
1251
+ test(`Should retuern "foofoofabc" when maxLength is 10 and fillItems "foo"`, () => {
1252
+ const result = new IterableCollection("abc")
1253
+ .padStart(10, "foo")
1254
+ .join({
1255
+ seperator: "",
1256
+ });
1257
+ expect(result).toBe("foofoofabc");
1258
+ });
1259
+ test(`Should retuern "123abc" when maxLength is 6 and fillItems "abc"`, () => {
1260
+ const result = new IterableCollection("abc")
1261
+ .padStart(6, "123465")
1262
+ .join({ seperator: "" });
1263
+ expect(result).toBe("123abc");
1264
+ });
1265
+ test(`Should retuern "00000abc" when maxLength is 8 and fillItems "00000abc"`, () => {
1266
+ const result = new IterableCollection("abc")
1267
+ .padStart(8, "0")
1268
+ .join({ seperator: "" });
1269
+ expect(result).toBe("00000abc");
1270
+ });
1271
+ test(`Should retuern "abc" when maxLength is 1 and fillItems "_"`, () => {
1272
+ const result = new IterableCollection("abc")
1273
+ .padStart(1, "_")
1274
+ .join({ seperator: "" });
1275
+ expect(result).toBe("abc");
1276
+ });
1277
+ });
1278
+ describe("method: padEnd", () => {
1279
+ test(`Should retuern "abcfoofoof" when maxLength is 10 and fillItems "foo"`, () => {
1280
+ const result = new IterableCollection("abc")
1281
+ .padEnd(10, "foo")
1282
+ .join({
1283
+ seperator: "",
1284
+ });
1285
+ expect(result).toBe("abcfoofoof");
1286
+ });
1287
+ test(`Should retuern "abc123" when maxLength is 6 and fillItems "abc"`, () => {
1288
+ const result = new IterableCollection("abc")
1289
+ .padEnd(6, "123465")
1290
+ .join({ seperator: "" });
1291
+ expect(result).toBe("abc123");
1292
+ });
1293
+ test(`Should retuern "abc00000" when maxLength is 8 and fillItems "00000abc"`, () => {
1294
+ const result = new IterableCollection("abc")
1295
+ .padEnd(8, "0")
1296
+ .join({ seperator: "" });
1297
+ expect(result).toBe("abc00000");
1298
+ });
1299
+ test(`Should retuern "abc" when maxLength is 1 and fillItems "_"`, () => {
1300
+ const result = new IterableCollection("abc")
1301
+ .padEnd(1, "_")
1302
+ .join({ seperator: "" });
1303
+ expect(result).toBe("abc");
1304
+ });
1305
+ });
1306
+ describe("method: slice", () => {
1307
+ test("Should return [1] when start is 0, end is 1 and array is [1, 2, 3, 4, 5]", () => {
1308
+ const arr = [1, 2, 3, 4, 5];
1309
+ const collection = new IterableCollection(arr);
1310
+ const newCollection = collection.slice({ start: 0, end: 1 });
1311
+ expect(newCollection.toArray()).toEqual(arr.slice(0, 1));
1312
+ });
1313
+ test("Should return [4, 5] when start is -2 and array is [1, 2, 3, 4, 5]", () => {
1314
+ const arr = [1, 2, 3, 4, 5];
1315
+ const collection = new IterableCollection(arr);
1316
+ const newCollection = collection.slice({ start: -2 });
1317
+ expect(newCollection.toArray()).toEqual(arr.slice(-2));
1318
+ });
1319
+ test("Should return [1, 2, 3, 4] when start is 0, end is -1 and array is [1, 2, 3, 4, 5]", () => {
1320
+ const arr = [1, 2, 3, 4, 5];
1321
+ const collection = new IterableCollection(arr);
1322
+ const newCollection = collection.slice({ start: 0, end: -1 });
1323
+ expect(newCollection.toArray()).toEqual(arr.slice(0, -1));
1324
+ });
1325
+ test("Should return [3, 4] when start is 2, end is -1 and array is [1, 2, 3, 4, 5]", () => {
1326
+ const arr = [1, 2, 3, 4, 5];
1327
+ const collection = new IterableCollection(arr);
1328
+ const newCollection = collection.slice({ start: 2, end: -1 });
1329
+ expect(newCollection.toArray()).toEqual(arr.slice(2, -1));
1330
+ });
1331
+ test("Should return [2, 3, 4] when start is 1, end is 4 and array is [1, 2, 3, 4, 5]", () => {
1332
+ const arr = [1, 2, 3, 4, 5];
1333
+ const collection = new IterableCollection(arr);
1334
+ const newCollection = collection.slice({ start: 1, end: 4 });
1335
+ expect(newCollection.toArray()).toEqual(arr.slice(1, 4));
1336
+ });
1337
+ test("Should return [3, 4] when start is 2, end is 4 and array is [1, 2, 3, 4, 5]", () => {
1338
+ const arr = [1, 2, 3, 4, 5];
1339
+ const collection = new IterableCollection(arr);
1340
+ const newCollection = collection.slice({ start: 2, end: 4 });
1341
+ expect(newCollection.toArray()).toEqual(arr.slice(2, 4));
1342
+ });
1343
+ });
1344
+ describe("method: prepend", () => {
1345
+ test("Should prepend iterable", () => {
1346
+ const arr1 = ["a", "b", "c"],
1347
+ collection = new IterableCollection(arr1),
1348
+ arr2 = [1, 2, 3],
1349
+ prependedCollection = collection.prepend(arr2);
1350
+ expect(prependedCollection.toArray()).toEqual([...arr2, ...arr1]);
1351
+ });
1352
+ });
1353
+ describe("method: append", () => {
1354
+ test("Should append iterable", () => {
1355
+ const arr1 = ["a", "b", "c"],
1356
+ collection = new IterableCollection(arr1),
1357
+ arr2 = [1, 2, 3],
1358
+ appendedCollection = collection.append(arr2);
1359
+ expect(appendedCollection.toArray()).toEqual([...arr1, ...arr2]);
1360
+ });
1361
+ });
1362
+ describe("method: insertBefore", () => {
1363
+ test("Should insert iterable before first item", () => {
1364
+ const arr1 = ["a", "b", "c"],
1365
+ collection = new IterableCollection(arr1),
1366
+ arr2 = [1, 2, 3],
1367
+ newCollection = collection.insertBefore(
1368
+ (item) => item === "a",
1369
+ arr2,
1370
+ );
1371
+ expect(newCollection.toArray()).toEqual([...arr2, ...arr1]);
1372
+ });
1373
+ test("Should insert iterable before last item", () => {
1374
+ const arr1 = ["a", "b", "c"],
1375
+ collection = new IterableCollection(arr1),
1376
+ arr2 = [1, 2, 3],
1377
+ newCollection = collection.insertBefore(
1378
+ (item) => item === "c",
1379
+ arr2,
1380
+ );
1381
+ expect(newCollection.toArray()).toEqual([
1382
+ ...arr1.slice(0, -1),
1383
+ ...arr2,
1384
+ ...arr1.slice(-1),
1385
+ ]);
1386
+ });
1387
+ test("Should not insert iterable if filter item not found", () => {
1388
+ const arr1 = ["a", "b", "c"],
1389
+ collection = new IterableCollection(arr1),
1390
+ arr2 = [1, 2, 3],
1391
+ newCollection = collection.insertBefore(
1392
+ (item) => item === "d",
1393
+ arr2,
1394
+ );
1395
+ expect(newCollection.toArray()).toEqual(arr1);
1396
+ });
1397
+ });
1398
+ describe("method: insertAfter", () => {
1399
+ test("Should insert iterable after last item", () => {
1400
+ const arr1 = ["a", "b", "c"],
1401
+ collection = new IterableCollection(arr1),
1402
+ arr2 = [1, 2, 3],
1403
+ newCollection = collection.insertAfter(
1404
+ (item) => item === "c",
1405
+ arr2,
1406
+ );
1407
+ expect(newCollection.toArray()).toEqual([...arr1, ...arr2]);
1408
+ });
1409
+ test("Should insert iterable after first item", () => {
1410
+ const arr1 = ["a", "b", "c"],
1411
+ collection = new IterableCollection(arr1),
1412
+ arr2 = [1, 2, 3],
1413
+ newCollection = collection.insertAfter(
1414
+ (item) => item === "a",
1415
+ arr2,
1416
+ );
1417
+ expect(newCollection.toArray()).toEqual([
1418
+ ...arr1.slice(0, 1),
1419
+ ...arr2,
1420
+ ...arr1.slice(-2),
1421
+ ]);
1422
+ });
1423
+ test("Should not insert iterable if filter item not found", () => {
1424
+ const arr1 = ["a", "b", "c"],
1425
+ collection = new IterableCollection(arr1),
1426
+ arr2 = [1, 2, 3],
1427
+ newCollection = collection.insertAfter(
1428
+ (item) => item === "d",
1429
+ arr2,
1430
+ );
1431
+ expect(newCollection.toArray()).toEqual(arr1);
1432
+ });
1433
+ });
1434
+ describe("method: crossJoin", () => {
1435
+ test(`Should return 4 combinations when input iterable is [1, 2] and ["a", "b"]`, () => {
1436
+ const collection = new IterableCollection([1, 2]);
1437
+ const matrix = collection.crossJoin(["a", "b"]);
1438
+ expect(
1439
+ matrix.map((collection) => collection.toArray()).toArray(),
1440
+ ).toEqual([
1441
+ [1, "a"],
1442
+ [1, "b"],
1443
+ [2, "a"],
1444
+ [2, "b"],
1445
+ ]);
1446
+ });
1447
+ test(`Should return 8 combinations when input iterable is [1, 2], ["a", "b"] and ["I", "II"]`, () => {
1448
+ const collection = new IterableCollection([1, 2]);
1449
+ const matrix = collection.crossJoin(["a", "b"], ["I", "II"]);
1450
+ expect(
1451
+ matrix.map((collection) => collection.toArray()).toArray(),
1452
+ ).toEqual([
1453
+ [1, "a", "I"],
1454
+ [1, "a", "II"],
1455
+ [1, "b", "I"],
1456
+ [1, "b", "II"],
1457
+ [2, "a", "I"],
1458
+ [2, "a", "II"],
1459
+ [2, "b", "I"],
1460
+ [2, "b", "II"],
1461
+ ]);
1462
+ });
1463
+ });
1464
+ describe("method: zip", () => {
1465
+ test("Should zip iterable", () => {
1466
+ const arr1 = ["a", "b", "c"],
1467
+ collection = new IterableCollection(arr1),
1468
+ arr2 = [1, 2, 3],
1469
+ newCollection = collection.zip(arr2);
1470
+ expect(newCollection.toArray()).toEqual([
1471
+ [arr1[0], arr2[0]],
1472
+ [arr1[1], arr2[1]],
1473
+ [arr1[2], arr2[2]],
1474
+ ]);
1475
+ });
1476
+ test("Should have the length of collection", () => {
1477
+ const arr1 = ["a", "b", "c", "d"],
1478
+ collection = new IterableCollection(arr1),
1479
+ arr2 = [1, 2, 3],
1480
+ newCollection = collection.zip(arr2);
1481
+ expect(newCollection.toArray()).toEqual([
1482
+ [arr1[0], arr2[0]],
1483
+ [arr1[1], arr2[1]],
1484
+ [arr1[2], arr2[2]],
1485
+ ]);
1486
+ });
1487
+ test("Should have the length of input iterable", () => {
1488
+ const arr1 = ["a", "b", "c"],
1489
+ collection = new IterableCollection(arr1),
1490
+ arr2 = [1, 2, 3, 4],
1491
+ newCollection = collection.zip(arr2);
1492
+ expect(newCollection.toArray()).toEqual([
1493
+ [arr1[0], arr2[0]],
1494
+ [arr1[1], arr2[1]],
1495
+ [arr1[2], arr2[2]],
1496
+ ]);
1497
+ });
1498
+ });
1499
+ describe("method: sort", () => {
1500
+ test("Sort numbers from smallest to largest with custom comparator function", () => {
1501
+ const arr = [-1, 2, 1, -3, 4, 20, 15, -5, -3],
1502
+ collection = new IterableCollection(arr),
1503
+ newCollection = collection.sort((a, b) => a - b);
1504
+ expect(newCollection.toArray()).toEqual(
1505
+ [...arr].sort((a, b) => a - b),
1506
+ );
1507
+ });
1508
+ test("Sort numbers from smallest to largest with default compartor function", () => {
1509
+ const arr = [-1, 2, 1, -3, 4, 20, 15, -5, -3],
1510
+ collection = new IterableCollection(arr),
1511
+ newCollection = collection.sort();
1512
+ expect(newCollection.toArray()).toEqual([...arr].sort());
1513
+ });
1514
+ });
1515
+ describe("method: reverse", () => {
1516
+ test("Should reverse iterable", () => {
1517
+ const arr = ["a", "b", "c", "d", "e", "f"],
1518
+ collection = new IterableCollection(arr),
1519
+ newCollection = collection.reverse();
1520
+ expect(newCollection.toArray()).toEqual([...arr].reverse());
1521
+ });
1522
+ });
1523
+ describe("method: first", () => {
1524
+ test("Should return first item that matches the filter function", () => {
1525
+ type Person = {
1526
+ name: string;
1527
+ age: number;
1528
+ };
1529
+ const persons: Person[] = [
1530
+ {
1531
+ name: "Joe",
1532
+ age: 20,
1533
+ },
1534
+ {
1535
+ name: "Jhon",
1536
+ age: 23,
1537
+ },
1538
+ {
1539
+ name: "Joe",
1540
+ age: 30,
1541
+ },
1542
+ {
1543
+ name: "Jhon",
1544
+ age: 50,
1545
+ },
1546
+ ],
1547
+ collection = new IterableCollection(persons),
1548
+ item = collection.first({
1549
+ filterFn: (person) => person.name === "Joe",
1550
+ });
1551
+ expect(item).toEqual(persons[0]);
1552
+ });
1553
+ test("Should return first item when found", () => {
1554
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1555
+ item = collection.first();
1556
+ expect(item).toBe(1);
1557
+ });
1558
+ test("Should return null when item not found", () => {
1559
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1560
+ item = collection.first({
1561
+ filterFn: (item) => item === 6,
1562
+ });
1563
+ expect(item).toBe(null);
1564
+ });
1565
+ test("Should input correct indexes to filter function", () => {
1566
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1567
+ indexes: number[] = [];
1568
+ collection.first({
1569
+ filterFn: (item, index) => {
1570
+ indexes.push(index);
1571
+ return item === 6;
1572
+ },
1573
+ });
1574
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
1575
+ });
1576
+ test("Should return the same value when called more than 1 times", () => {
1577
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1578
+ expect(collection.first()).toBe(1);
1579
+ expect(collection.first()).toBe(1);
1580
+ });
1581
+ });
1582
+ describe("method: firstOr", () => {
1583
+ test("Should return first item that matches the filter function", () => {
1584
+ type Person = {
1585
+ name: string;
1586
+ age: number;
1587
+ };
1588
+ const persons: Person[] = [
1589
+ {
1590
+ name: "Joe",
1591
+ age: 20,
1592
+ },
1593
+ {
1594
+ name: "Jhon",
1595
+ age: 23,
1596
+ },
1597
+ {
1598
+ name: "Joe",
1599
+ age: 30,
1600
+ },
1601
+ {
1602
+ name: "Jhon",
1603
+ age: 50,
1604
+ },
1605
+ ],
1606
+ collection = new IterableCollection(persons),
1607
+ item = collection.firstOr({
1608
+ defaultValue: null,
1609
+ filterFn: (person) => person.name === "Joe",
1610
+ });
1611
+ expect(item).toEqual(persons[0]);
1612
+ });
1613
+ test("Should return first item when found", () => {
1614
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1615
+ item = collection.firstOr({
1616
+ defaultValue: "a",
1617
+ });
1618
+ expect(item).toBe(1);
1619
+ });
1620
+ test("Should return default value when item not found", () => {
1621
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1622
+ item = collection.firstOr({
1623
+ defaultValue: "a",
1624
+ filterFn: (item) => item === 6,
1625
+ });
1626
+ expect(item).toBe("a");
1627
+ });
1628
+ test("Should input correct indexes to filter function", () => {
1629
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1630
+ indexes: number[] = [];
1631
+ collection.firstOr({
1632
+ defaultValue: null,
1633
+ filterFn: (item, index) => {
1634
+ indexes.push(index);
1635
+ return item === 6;
1636
+ },
1637
+ });
1638
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
1639
+ });
1640
+ test("Should return the same value when called more than 1 times", () => {
1641
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1642
+ expect(
1643
+ collection.firstOr({
1644
+ defaultValue: "a",
1645
+ }),
1646
+ ).toBe(1);
1647
+ expect(
1648
+ collection.firstOr({
1649
+ defaultValue: "a",
1650
+ }),
1651
+ ).toBe(1);
1652
+ });
1653
+ });
1654
+ describe("method: firstOrFail", () => {
1655
+ test("Should return first item that matches the filter function", () => {
1656
+ type Person = {
1657
+ name: string;
1658
+ age: number;
1659
+ };
1660
+ const persons: Person[] = [
1661
+ {
1662
+ name: "Joe",
1663
+ age: 20,
1664
+ },
1665
+ {
1666
+ name: "Jhon",
1667
+ age: 23,
1668
+ },
1669
+ {
1670
+ name: "Joe",
1671
+ age: 30,
1672
+ },
1673
+ {
1674
+ name: "Jhon",
1675
+ age: 50,
1676
+ },
1677
+ ],
1678
+ collection = new IterableCollection(persons),
1679
+ item = collection.firstOrFail({
1680
+ filterFn: (person) => person.name === "Joe",
1681
+ });
1682
+ expect(item).toEqual(persons[0]);
1683
+ });
1684
+ test("Should return first item when found", () => {
1685
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1686
+ item = collection.firstOrFail();
1687
+ expect(item).toBe(1);
1688
+ });
1689
+ test("Should throw CollectionError when item not found", () => {
1690
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1691
+ expect(() => {
1692
+ collection.firstOrFail({
1693
+ filterFn: (item) => item === 6,
1694
+ });
1695
+ }).toThrowError(CollectionError);
1696
+ });
1697
+ test("Should throw ItemNotFoundError when item not found", () => {
1698
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1699
+ expect(() => {
1700
+ collection.firstOrFail({
1701
+ filterFn: (item) => item === 6,
1702
+ });
1703
+ }).toThrowError(ItemNotFoundError);
1704
+ });
1705
+ test("Should input correct indexes to filter function", () => {
1706
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1707
+ indexes: number[] = [];
1708
+ try {
1709
+ collection.firstOrFail({
1710
+ filterFn: (item, index) => {
1711
+ indexes.push(index);
1712
+ return item === 6;
1713
+ },
1714
+ });
1715
+ } catch {
1716
+ /* Empty */
1717
+ }
1718
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
1719
+ });
1720
+ test("Should return the same value when called more than 1 times", () => {
1721
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1722
+ expect(collection.firstOrFail()).toBe(1);
1723
+ expect(collection.firstOrFail()).toBe(1);
1724
+ });
1725
+ });
1726
+ describe("method: last", () => {
1727
+ test("Should return last item that matches the filter function", () => {
1728
+ type Person = {
1729
+ name: string;
1730
+ age: number;
1731
+ };
1732
+ const persons: Person[] = [
1733
+ {
1734
+ name: "Joe",
1735
+ age: 20,
1736
+ },
1737
+ {
1738
+ name: "Jhon",
1739
+ age: 23,
1740
+ },
1741
+ {
1742
+ name: "Joe",
1743
+ age: 30,
1744
+ },
1745
+ {
1746
+ name: "Jhon",
1747
+ age: 50,
1748
+ },
1749
+ ],
1750
+ collection = new IterableCollection(persons),
1751
+ item = collection.last({
1752
+ filterFn: (person) => person.name === "Joe",
1753
+ });
1754
+ expect(item).toEqual(persons[2]);
1755
+ });
1756
+ test("Should return last item when found", () => {
1757
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1758
+ item = collection.last();
1759
+ expect(item).toBe(5);
1760
+ });
1761
+ test("Should return null when item not found", () => {
1762
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1763
+ item = collection.last({
1764
+ filterFn: (item) => item === 6,
1765
+ });
1766
+ expect(item).toBe(null);
1767
+ });
1768
+ test("Should input correct indexes to filter function", () => {
1769
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1770
+ indexes: number[] = [];
1771
+ collection.last({
1772
+ filterFn: (item, index) => {
1773
+ indexes.push(index);
1774
+ return item === 6;
1775
+ },
1776
+ });
1777
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
1778
+ });
1779
+ test("Should return the same value when called more than 1 times", () => {
1780
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1781
+ expect(collection.last()).toBe(5);
1782
+ expect(collection.last()).toBe(5);
1783
+ });
1784
+ });
1785
+ describe("method: lastOr", () => {
1786
+ test("Should return last item that matches the filter function", () => {
1787
+ type Person = {
1788
+ name: string;
1789
+ age: number;
1790
+ };
1791
+ const persons: Person[] = [
1792
+ {
1793
+ name: "Joe",
1794
+ age: 20,
1795
+ },
1796
+ {
1797
+ name: "Jhon",
1798
+ age: 23,
1799
+ },
1800
+ {
1801
+ name: "Joe",
1802
+ age: 30,
1803
+ },
1804
+ {
1805
+ name: "Jhon",
1806
+ age: 50,
1807
+ },
1808
+ ],
1809
+ collection = new IterableCollection(persons),
1810
+ item = collection.lastOr({
1811
+ defaultValue: null,
1812
+ filterFn: (person) => person.name === "Joe",
1813
+ });
1814
+ expect(item).toEqual(persons[2]);
1815
+ });
1816
+ test("Should return last item when found", () => {
1817
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1818
+ item = collection.lastOr({
1819
+ defaultValue: "a",
1820
+ });
1821
+ expect(item).toBe(5);
1822
+ });
1823
+ test("Should return default value when item not found", () => {
1824
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1825
+ item = collection.lastOr({
1826
+ defaultValue: "a",
1827
+ filterFn: (item) => item === 6,
1828
+ });
1829
+ expect(item).toBe("a");
1830
+ });
1831
+ test("Should input correct indexes to filter function", () => {
1832
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1833
+ indexes: number[] = [];
1834
+ collection.lastOr({
1835
+ defaultValue: null,
1836
+ filterFn: (item, index) => {
1837
+ indexes.push(index);
1838
+ return item === 6;
1839
+ },
1840
+ });
1841
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
1842
+ });
1843
+ test("Should return the same value when called more than 1 times", () => {
1844
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1845
+ expect(
1846
+ collection.lastOr({
1847
+ defaultValue: "a",
1848
+ }),
1849
+ ).toBe(5);
1850
+ expect(
1851
+ collection.lastOr({
1852
+ defaultValue: "a",
1853
+ }),
1854
+ ).toBe(5);
1855
+ });
1856
+ });
1857
+ describe("method: lastOrFail", () => {
1858
+ test("Should return last item that matches the filter function", () => {
1859
+ type Person = {
1860
+ name: string;
1861
+ age: number;
1862
+ };
1863
+ const persons: Person[] = [
1864
+ {
1865
+ name: "Joe",
1866
+ age: 20,
1867
+ },
1868
+ {
1869
+ name: "Jhon",
1870
+ age: 23,
1871
+ },
1872
+ {
1873
+ name: "Joe",
1874
+ age: 30,
1875
+ },
1876
+ {
1877
+ name: "Jhon",
1878
+ age: 50,
1879
+ },
1880
+ ],
1881
+ collection = new IterableCollection(persons),
1882
+ item = collection.lastOrFail({
1883
+ filterFn: (person) => person.name === "Joe",
1884
+ });
1885
+ expect(item).toEqual(persons[2]);
1886
+ });
1887
+ test("Should return last item when found", () => {
1888
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1889
+ item = collection.lastOrFail();
1890
+ expect(item).toBe(5);
1891
+ });
1892
+ test("Should throw CollectionError when item not found", () => {
1893
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1894
+ expect(() => {
1895
+ collection.lastOrFail({
1896
+ filterFn: (item) => item === 6,
1897
+ });
1898
+ }).toThrowError(CollectionError);
1899
+ });
1900
+ test("Should throw ItemNotFoundError when item not found", () => {
1901
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1902
+ expect(() => {
1903
+ collection.lastOrFail({
1904
+ filterFn: (item) => item === 6,
1905
+ });
1906
+ }).toThrowError(ItemNotFoundError);
1907
+ });
1908
+ test("Should input correct indexes to filter function", () => {
1909
+ const collection = new IterableCollection([1, 2, 3, 4, 5]),
1910
+ indexes: number[] = [];
1911
+ try {
1912
+ collection.lastOrFail({
1913
+ filterFn: (item, index) => {
1914
+ indexes.push(index);
1915
+ return item === 6;
1916
+ },
1917
+ });
1918
+ } catch {
1919
+ /* Empty */
1920
+ }
1921
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
1922
+ });
1923
+ test("Should return the same value when called more than 1 times", () => {
1924
+ const collection = new IterableCollection([1, 2, 3, 4, 5]);
1925
+ expect(collection.lastOrFail()).toBe(5);
1926
+ expect(collection.lastOrFail()).toBe(5);
1927
+ });
1928
+ });
1929
+ describe("method: before", () => {
1930
+ test(`Should return "a" when searching for string "b" of ["a", "b", "c"]`, () => {
1931
+ const collection = new IterableCollection(["a", "b", "c"]),
1932
+ item = collection.before((item) => item === "b");
1933
+ expect(item).toBe("a");
1934
+ });
1935
+ test(`Should return "b" when searching for string "c" of ["a", "b", "c"]`, () => {
1936
+ const collection = new IterableCollection(["a", "b", "c"]),
1937
+ item = collection.before((item) => item === "c");
1938
+ expect(item).toBe("b");
1939
+ });
1940
+ test(`Should return null when searching for string "a" of ["a", "b", "c"]`, () => {
1941
+ const collection = new IterableCollection(["a", "b", "c"]),
1942
+ item = collection.before((item) => item === "a");
1943
+ expect(item).toBe(null);
1944
+ });
1945
+ test(`Should return null when searching for string "d" of ["a", "b", "c"]`, () => {
1946
+ const collection = new IterableCollection(["a", "b", "c"]),
1947
+ item = collection.before((item) => item === "d");
1948
+ expect(item).toBe(null);
1949
+ });
1950
+ test("Should input correct indexes to filter function", () => {
1951
+ const collection = new IterableCollection(["a", "b", "c"]),
1952
+ indexes: number[] = [];
1953
+ collection.before((item, index) => {
1954
+ indexes.push(index);
1955
+ return item === "c";
1956
+ });
1957
+ expect(indexes).toEqual([0, 1, 2]);
1958
+ });
1959
+ test("Should return the same value when called more than 1 times", () => {
1960
+ const collection = new IterableCollection(["a", "b", "c"]);
1961
+ expect(collection.before((item) => item === "c")).toBe("b");
1962
+ expect(collection.before((item) => item === "c")).toBe("b");
1963
+ });
1964
+ });
1965
+ describe("method: beforeOr", () => {
1966
+ test(`Should return "a" when searching for string "b" of ["a", "b", "c"]`, () => {
1967
+ const collection = new IterableCollection(["a", "b", "c"]),
1968
+ item = collection.beforeOr(-1, (item) => item === "b");
1969
+ expect(item).toBe("a");
1970
+ });
1971
+ test(`Should return "b" when searching for string "c" of ["a", "b", "c"]`, () => {
1972
+ const collection = new IterableCollection(["a", "b", "c"]),
1973
+ item = collection.beforeOr(-1, (item) => item === "c");
1974
+ expect(item).toBe("b");
1975
+ });
1976
+ test(`Should return default value when searching for string "a" of ["a", "b", "c"]`, () => {
1977
+ const collection = new IterableCollection(["a", "b", "c"]),
1978
+ item = collection.beforeOr(-1, (item) => item === "a");
1979
+ expect(item).toBe(-1);
1980
+ });
1981
+ test(`Should return default value when searching for string "d" of ["a", "b", "c"]`, () => {
1982
+ const collection = new IterableCollection(["a", "b", "c"]),
1983
+ item = collection.beforeOr(-1, (item) => item === "d");
1984
+ expect(item).toBe(-1);
1985
+ });
1986
+ test("Should input correct indexes to filter function", () => {
1987
+ const collection = new IterableCollection(["a", "b", "c"]),
1988
+ indexes: number[] = [];
1989
+ collection.beforeOr(null, (item, index) => {
1990
+ indexes.push(index);
1991
+ return item === "c";
1992
+ });
1993
+ expect(indexes).toEqual([0, 1, 2]);
1994
+ });
1995
+ test("Should return the same value when called more than 1 times", () => {
1996
+ const collection = new IterableCollection(["a", "b", "c"]);
1997
+ expect(collection.beforeOr(-1, (item) => item === "c")).toBe("b");
1998
+ expect(collection.beforeOr(-1, (item) => item === "c")).toBe("b");
1999
+ });
2000
+ });
2001
+ describe("method: beforeOrFail", () => {
2002
+ test(`Should return "a" when searching for string "b" of ["a", "b", "c"]`, () => {
2003
+ const collection = new IterableCollection(["a", "b", "c"]),
2004
+ item = collection.beforeOrFail((item) => item === "b");
2005
+ expect(item).toBe("a");
2006
+ });
2007
+ test(`Should return "b" when searching for string "c" of ["a", "b", "c"]`, () => {
2008
+ const collection = new IterableCollection(["a", "b", "c"]),
2009
+ item = collection.beforeOrFail((item) => item === "c");
2010
+ expect(item).toBe("b");
2011
+ });
2012
+ test(`Should throw CollectionError when searching for string "a" of ["a", "b", "c"]`, () => {
2013
+ const collection = new IterableCollection(["a", "b", "c"]);
2014
+ expect(() => {
2015
+ collection.beforeOrFail((item) => item === "a");
2016
+ }).toThrowError(CollectionError);
2017
+ });
2018
+ test(`Should throw ItemNotFoundError when searching for string "d" of ["a", "b", "c"]`, () => {
2019
+ const collection = new IterableCollection(["a", "b", "c"]);
2020
+ expect(() => {
2021
+ collection.beforeOrFail((item) => item === "d");
2022
+ }).toThrowError(ItemNotFoundError);
2023
+ });
2024
+ test("Should input correct indexes to filter function", () => {
2025
+ const collection = new IterableCollection(["a", "b", "c"]),
2026
+ indexes: number[] = [];
2027
+ try {
2028
+ collection.beforeOrFail((item, index) => {
2029
+ indexes.push(index);
2030
+ return item === "c";
2031
+ });
2032
+ } catch {
2033
+ /* Empty */
2034
+ }
2035
+ expect(indexes).toEqual([0, 1, 2]);
2036
+ });
2037
+ test("Should return the same value when called more than 1 times", () => {
2038
+ const collection = new IterableCollection(["a", "b", "c"]);
2039
+ expect(collection.beforeOrFail((item) => item === "c")).toBe("b");
2040
+ expect(collection.beforeOrFail((item) => item === "c")).toBe("b");
2041
+ });
2042
+ });
2043
+ describe("method: after", () => {
2044
+ test(`Should return "c" when searching for string "b" of ["a", "b", "c"]`, () => {
2045
+ const collection = new IterableCollection(["a", "b", "c"]),
2046
+ item = collection.after((item) => item === "b");
2047
+ expect(item).toBe("c");
2048
+ });
2049
+ test(`Should return "b" when searching for string "a" of ["a", "b", "c"]`, () => {
2050
+ const collection = new IterableCollection(["a", "b", "c"]),
2051
+ item = collection.after((item) => item === "a");
2052
+ expect(item).toBe("b");
2053
+ });
2054
+ test(`Should return null when searching for string "c" of ["a", "b", "c"]`, () => {
2055
+ const collection = new IterableCollection(["a", "b", "c"]),
2056
+ item = collection.after((item) => item === "c");
2057
+ expect(item).toBe(null);
2058
+ });
2059
+ test(`Should return null when searching for string "d" of ["a", "b", "c"]`, () => {
2060
+ const collection = new IterableCollection(["a", "b", "c"]),
2061
+ item = collection.after((item) => item === "d");
2062
+ expect(item).toBe(null);
2063
+ });
2064
+ test("Should input correct indexes to filter function", () => {
2065
+ const collection = new IterableCollection(["a", "b", "c"]),
2066
+ indexes: number[] = [];
2067
+ collection.after((item, index) => {
2068
+ indexes.push(index);
2069
+ return item === "c";
2070
+ });
2071
+ expect(indexes).toEqual([0, 1, 2]);
2072
+ });
2073
+ test("Should return the same value when called more than 1 times", () => {
2074
+ const collection = new IterableCollection(["a", "b", "c"]);
2075
+ expect(collection.after((item) => item === "a")).toBe("b");
2076
+ expect(collection.after((item) => item === "a")).toBe("b");
2077
+ });
2078
+ });
2079
+ describe("method: afterOr", () => {
2080
+ test(`Should return "c" when searching for string "b" of ["a", "b", "c"]`, () => {
2081
+ const collection = new IterableCollection(["a", "b", "c"]),
2082
+ item = collection.afterOr(-1, (item) => item === "b");
2083
+ expect(item).toBe("c");
2084
+ });
2085
+ test(`Should return "b" when searching for string "a" of ["a", "b", "c"]`, () => {
2086
+ const collection = new IterableCollection(["a", "b", "c"]),
2087
+ item = collection.afterOr(-1, (item) => item === "a");
2088
+ expect(item).toBe("b");
2089
+ });
2090
+ test(`Should return default value when searching for string "c" of ["a", "b", "c"]`, () => {
2091
+ const collection = new IterableCollection(["a", "b", "c"]),
2092
+ item = collection.afterOr(-1, (item) => item === "c");
2093
+ expect(item).toBe(-1);
2094
+ });
2095
+ test(`Should return default value when searching for string "d" of ["a", "b", "c"]`, () => {
2096
+ const collection = new IterableCollection(["a", "b", "c"]),
2097
+ item = collection.afterOr(-1, (item) => item === "d");
2098
+ expect(item).toBe(-1);
2099
+ });
2100
+ test("Should input correct indexes to filter function", () => {
2101
+ const collection = new IterableCollection(["a", "b", "c"]),
2102
+ indexes: number[] = [];
2103
+ collection.afterOr(null, (item, index) => {
2104
+ indexes.push(index);
2105
+ return item === "c";
2106
+ });
2107
+ expect(indexes).toEqual([0, 1, 2]);
2108
+ });
2109
+ test("Should return the same value when called more than 1 times", () => {
2110
+ const collection = new IterableCollection(["a", "b", "c"]);
2111
+ expect(collection.afterOr(-1, (item) => item === "a")).toBe("b");
2112
+ expect(collection.afterOr(-1, (item) => item === "a")).toBe("b");
2113
+ });
2114
+ });
2115
+ describe("method: afterOrFail", () => {
2116
+ test(`Should return "c" when searching for string "b" of ["a", "b", "c"]`, () => {
2117
+ const collection = new IterableCollection(["a", "b", "c"]),
2118
+ item = collection.afterOrFail((item) => item === "b");
2119
+ expect(item).toBe("c");
2120
+ });
2121
+ test(`Should return "b" when searching for string "a" of ["a", "b", "c"]`, () => {
2122
+ const collection = new IterableCollection(["a", "b", "c"]),
2123
+ item = collection.afterOrFail((item) => item === "a");
2124
+ expect(item).toBe("b");
2125
+ });
2126
+ test(`Should throw CollectionError when searching for string "c" of ["a", "b", "c"]`, () => {
2127
+ const collection = new IterableCollection(["a", "b", "c"]);
2128
+ expect(() => {
2129
+ collection.afterOrFail((item) => item === "c");
2130
+ }).toThrowError(CollectionError);
2131
+ });
2132
+ test(`Should throw ItemNotFoundError when searching for string "d" of ["a", "b", "c"]`, () => {
2133
+ const collection = new IterableCollection(["a", "b", "c"]);
2134
+ expect(() => {
2135
+ collection.afterOrFail((item) => item === "d");
2136
+ }).toThrowError(ItemNotFoundError);
2137
+ });
2138
+ test("Should input correct indexes to filter function", () => {
2139
+ const collection = new IterableCollection(["a", "b", "c"]),
2140
+ indexes: number[] = [];
2141
+ try {
2142
+ collection.afterOrFail((item, index) => {
2143
+ indexes.push(index);
2144
+ return item === "c";
2145
+ });
2146
+ } catch {
2147
+ /* Empty */
2148
+ }
2149
+ expect(indexes).toEqual([0, 1, 2]);
2150
+ });
2151
+ test("Should return the same value when called more than 1 times", () => {
2152
+ const collection = new IterableCollection(["a", "b", "c"]);
2153
+ expect(collection.afterOrFail((item) => item === "a")).toBe("b");
2154
+ expect(collection.afterOrFail((item) => item === "a")).toBe("b");
2155
+ });
2156
+ });
2157
+ describe("method: sole", () => {
2158
+ test("Should throw ItemNotFoundError when item does not exist", () => {
2159
+ const collection = new IterableCollection([
2160
+ "a",
2161
+ "a",
2162
+ "b",
2163
+ "c",
2164
+ "b",
2165
+ ]);
2166
+ expect(() => {
2167
+ collection.sole((item) => item === "f");
2168
+ }).toThrowError(ItemNotFoundError);
2169
+ });
2170
+ test("Should throw MultipleItemsFoundError when multiple item of same sort does exist", () => {
2171
+ const collection = new IterableCollection([
2172
+ "a",
2173
+ "a",
2174
+ "b",
2175
+ "c",
2176
+ "b",
2177
+ ]);
2178
+ expect(() => {
2179
+ collection.sole((item) => item === "a");
2180
+ }).toThrowError(MultipleItemsFoundError);
2181
+ });
2182
+ test("Should return item when only one item of the same sort exist", () => {
2183
+ const collection = new IterableCollection([
2184
+ "a",
2185
+ "a",
2186
+ "b",
2187
+ "c",
2188
+ "b",
2189
+ ]);
2190
+ expect(collection.sole((item) => item === "c")).toBe("c");
2191
+ });
2192
+ test("Should input correct indexes to filter function", () => {
2193
+ const collection = new IterableCollection([
2194
+ "a",
2195
+ "a",
2196
+ "b",
2197
+ "c",
2198
+ "b",
2199
+ ]),
2200
+ indexes: number[] = [];
2201
+ collection.sole((item, index) => {
2202
+ indexes.push(index);
2203
+ return item === "c";
2204
+ });
2205
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
2206
+ });
2207
+ test("Should return the same value when called more than 1 times", () => {
2208
+ const collection = new IterableCollection([
2209
+ "a",
2210
+ "a",
2211
+ "b",
2212
+ "c",
2213
+ "b",
2214
+ ]);
2215
+ expect(collection.sole((item) => item === "c")).toBe("c");
2216
+ expect(collection.sole((item) => item === "c")).toBe("c");
2217
+ });
2218
+ });
2219
+ describe("method: nth", () => {
2220
+ test("Should filter the 4:th items", () => {
2221
+ const collection = new IterableCollection([
2222
+ "a",
2223
+ "b",
2224
+ "c",
2225
+ "d",
2226
+ "e",
2227
+ "f",
2228
+ ]),
2229
+ newCollection = collection.nth(4);
2230
+ expect(newCollection.toArray()).toEqual(["a", "e"]);
2231
+ });
2232
+ });
2233
+ describe("method: count", () => {
2234
+ test(`Should return number 0 when filtering all string "a" of ["b", "b"]`, () => {
2235
+ const collection = new IterableCollection(["b", "b"]);
2236
+ expect(collection.count((item) => item === "a")).toBe(0);
2237
+ });
2238
+ test(`Should return number 3 when filtering all string "a" of ["a", "b", "a", "b", "a"]`, () => {
2239
+ const collection = new IterableCollection([
2240
+ "a",
2241
+ "b",
2242
+ "a",
2243
+ "b",
2244
+ "a",
2245
+ ]);
2246
+ expect(collection.count((item) => item === "a")).toBe(3);
2247
+ });
2248
+ test("Should input correct indexes to filter function", () => {
2249
+ const collection = new IterableCollection([
2250
+ "a",
2251
+ "a",
2252
+ "b",
2253
+ "c",
2254
+ "b",
2255
+ ]),
2256
+ indexes: number[] = [];
2257
+ collection.count((_item, index) => {
2258
+ indexes.push(index);
2259
+ return true;
2260
+ });
2261
+ expect(indexes).toEqual([0, 1, 2, 3, 4]);
2262
+ });
2263
+ test("Should return the same value when called more than 1 times", () => {
2264
+ const collection = new IterableCollection([
2265
+ "a",
2266
+ "b",
2267
+ "a",
2268
+ "b",
2269
+ "a",
2270
+ ]);
2271
+ expect(collection.count((item) => item === "a")).toBe(3);
2272
+ expect(collection.count((item) => item === "a")).toBe(3);
2273
+ });
2274
+ });
2275
+ describe("method: size", () => {
2276
+ test("Should return 0 when empty", () => {
2277
+ const collection = new IterableCollection([]);
2278
+ expect(collection.size()).toBe(0);
2279
+ });
2280
+ test("Should return number larger than 0 when empty", () => {
2281
+ const collection = new IterableCollection(["a", "b", "c"]);
2282
+ expect(collection.size()).toBeGreaterThan(0);
2283
+ });
2284
+ test("Should return 3 when contains 3 items", () => {
2285
+ const collection = new IterableCollection(["a", "b", "c"]);
2286
+ expect(collection.size()).toBe(3);
2287
+ });
2288
+ test("Should return the same value when called more than 1 times", () => {
2289
+ const collection = new IterableCollection(["a", "b", "c"]);
2290
+ expect(collection.size()).toBe(3);
2291
+ expect(collection.size()).toBe(3);
2292
+ });
2293
+ });
2294
+ describe("method: empty", () => {
2295
+ test("Should return true when empty", () => {
2296
+ const collection = new IterableCollection([]);
2297
+ expect(collection.empty()).toBe(true);
2298
+ });
2299
+ test("Should return false when not empty", () => {
2300
+ const collection = new IterableCollection([""]);
2301
+ expect(collection.empty()).toBe(false);
2302
+ });
2303
+ test("Should return the same value when called more than 1 times", () => {
2304
+ const collection = new IterableCollection([]);
2305
+ expect(collection.empty()).toBe(true);
2306
+ expect(collection.empty()).toBe(true);
2307
+ });
2308
+ });
2309
+ describe("method: notEmpty", () => {
2310
+ test("Should return true when not empty", () => {
2311
+ const collection = new IterableCollection([""]);
2312
+ expect(collection.notEmpty()).toBe(true);
2313
+ });
2314
+ test("Should return false when empty", () => {
2315
+ const collection = new IterableCollection([]);
2316
+ expect(collection.notEmpty()).toBe(false);
2317
+ });
2318
+ test("Should return the same value when called more than 1 times", () => {
2319
+ const collection = new IterableCollection([""]);
2320
+ expect(collection.notEmpty()).toBe(true);
2321
+ expect(collection.notEmpty()).toBe(true);
2322
+ });
2323
+ });
2324
+ describe("method: search", () => {
2325
+ test("Should return -1 when searching for value that does not exist in collection", () => {
2326
+ const collection = new IterableCollection(["a", "b", "c"]);
2327
+ expect(collection.search((item) => item === "d")).toBe(-1);
2328
+ });
2329
+ test(`Should return 1 when searching for string "b" of ["a", "b", "c"]`, () => {
2330
+ const collection = new IterableCollection(["a", "b", "c"]);
2331
+ expect(collection.search((item) => item === "b")).toBe(1);
2332
+ });
2333
+ test("Should return the same value when called more than 1 times", () => {
2334
+ const collection = new IterableCollection(["a", "b", "c"]);
2335
+ expect(collection.search((item) => item === "b")).toBe(1);
2336
+ expect(collection.search((item) => item === "b")).toBe(1);
2337
+ });
2338
+ });
2339
+ describe("method: forEach", () => {
2340
+ test("Should iterate all items", () => {
2341
+ const arr1 = [1, 2, 3],
2342
+ collection = new IterableCollection(arr1),
2343
+ arr2: number[] = [];
2344
+ collection.forEach((item) => arr2.push(item));
2345
+ expect(arr2).toEqual(arr1);
2346
+ });
2347
+ test("Should input correct indexes to filter function", () => {
2348
+ const collection = new IterableCollection([1, 2, 3]),
2349
+ indexes: number[] = [];
2350
+ collection.forEach((_item, index) => {
2351
+ indexes.push(index);
2352
+ });
2353
+ expect(indexes).toEqual([0, 1, 2]);
2354
+ });
2355
+ test("Should return the same value when called more than 1 times", () => {
2356
+ const arr1 = [1, 2, 3],
2357
+ collection = new IterableCollection(arr1),
2358
+ arr2: number[] = [];
2359
+ collection.forEach((item) => arr2.push(item));
2360
+ expect(arr2).toEqual(arr1);
2361
+ expect(arr2).toEqual(arr1);
2362
+ });
2363
+ });
2364
+ describe("method: toArray", () => {
2365
+ test("Should return array with 0 items when empty", () => {
2366
+ const collection = new IterableCollection([]);
2367
+ expect(collection.toArray()).toEqual([]);
2368
+ });
2369
+ test("Should return array with items when that match collection items", () => {
2370
+ const collection = new IterableCollection(["a", "b", "c"]);
2371
+ expect(collection.toArray()).toEqual(["a", "b", "c"]);
2372
+ });
2373
+ test("Should return the same value when called more than 1 times", () => {
2374
+ const collection = new IterableCollection(["a", "b", "c"]);
2375
+ expect(collection.toArray()).toEqual(["a", "b", "c"]);
2376
+ expect(collection.toArray()).toEqual(["a", "b", "c"]);
2377
+ });
2378
+ });
2379
+ });