@angular-wave/angular.ts 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 (231) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.cjs +29 -0
  3. package/.github/workflows/playwright.yml +27 -0
  4. package/CHANGELOG.md +17974 -0
  5. package/CODE_OF_CONDUCT.md +3 -0
  6. package/CONTRIBUTING.md +246 -0
  7. package/DEVELOPERS.md +488 -0
  8. package/LICENSE +22 -0
  9. package/Makefile +31 -0
  10. package/README.md +115 -0
  11. package/RELEASE.md +98 -0
  12. package/SECURITY.md +16 -0
  13. package/TRIAGING.md +135 -0
  14. package/css/angular.css +22 -0
  15. package/dist/angular-ts.cjs.js +36843 -0
  16. package/dist/angular-ts.esm.js +36841 -0
  17. package/dist/angular-ts.umd.js +36848 -0
  18. package/dist/build/angular-animate.js +4272 -0
  19. package/dist/build/angular-aria.js +426 -0
  20. package/dist/build/angular-message-format.js +1072 -0
  21. package/dist/build/angular-messages.js +829 -0
  22. package/dist/build/angular-mocks.js +3757 -0
  23. package/dist/build/angular-parse-ext.js +1275 -0
  24. package/dist/build/angular-resource.js +911 -0
  25. package/dist/build/angular-route.js +1266 -0
  26. package/dist/build/angular-sanitize.js +891 -0
  27. package/dist/build/angular-touch.js +368 -0
  28. package/dist/build/angular.js +36600 -0
  29. package/e2e/unit.spec.ts +15 -0
  30. package/images/android-chrome-192x192.png +0 -0
  31. package/images/android-chrome-512x512.png +0 -0
  32. package/images/apple-touch-icon.png +0 -0
  33. package/images/favicon-16x16.png +0 -0
  34. package/images/favicon-32x32.png +0 -0
  35. package/images/favicon.ico +0 -0
  36. package/images/site.webmanifest +1 -0
  37. package/index.html +104 -0
  38. package/package.json +47 -0
  39. package/playwright.config.ts +78 -0
  40. package/public/circle.html +1 -0
  41. package/public/my_child_directive.html +1 -0
  42. package/public/my_directive.html +1 -0
  43. package/public/my_other_directive.html +1 -0
  44. package/public/test.html +1 -0
  45. package/rollup.config.js +31 -0
  46. package/src/animations/animateCache.js +55 -0
  47. package/src/animations/animateChildrenDirective.js +105 -0
  48. package/src/animations/animateCss.js +1139 -0
  49. package/src/animations/animateCssDriver.js +291 -0
  50. package/src/animations/animateJs.js +367 -0
  51. package/src/animations/animateJsDriver.js +67 -0
  52. package/src/animations/animateQueue.js +851 -0
  53. package/src/animations/animation.js +506 -0
  54. package/src/animations/module.js +779 -0
  55. package/src/animations/ngAnimateSwap.js +119 -0
  56. package/src/animations/rafScheduler.js +50 -0
  57. package/src/animations/shared.js +378 -0
  58. package/src/constants.js +20 -0
  59. package/src/core/animate.js +845 -0
  60. package/src/core/animateCss.js +73 -0
  61. package/src/core/animateRunner.js +195 -0
  62. package/src/core/attributes.js +199 -0
  63. package/src/core/cache.js +45 -0
  64. package/src/core/compile.js +4727 -0
  65. package/src/core/controller.js +225 -0
  66. package/src/core/exceptionHandler.js +63 -0
  67. package/src/core/filter.js +146 -0
  68. package/src/core/interpolate.js +442 -0
  69. package/src/core/interval.js +188 -0
  70. package/src/core/intervalFactory.js +57 -0
  71. package/src/core/location.js +1086 -0
  72. package/src/core/parser/parse.js +2562 -0
  73. package/src/core/parser/parse.md +13 -0
  74. package/src/core/q.js +746 -0
  75. package/src/core/rootScope.js +1596 -0
  76. package/src/core/sanitizeUri.js +85 -0
  77. package/src/core/sce.js +1161 -0
  78. package/src/core/taskTrackerFactory.js +125 -0
  79. package/src/core/timeout.js +121 -0
  80. package/src/core/urlUtils.js +187 -0
  81. package/src/core/utils.js +1349 -0
  82. package/src/directive/a.js +37 -0
  83. package/src/directive/attrs.js +283 -0
  84. package/src/directive/bind.js +51 -0
  85. package/src/directive/bind.md +142 -0
  86. package/src/directive/change.js +12 -0
  87. package/src/directive/change.md +25 -0
  88. package/src/directive/cloak.js +12 -0
  89. package/src/directive/cloak.md +24 -0
  90. package/src/directive/events.js +75 -0
  91. package/src/directive/events.md +166 -0
  92. package/src/directive/form.js +725 -0
  93. package/src/directive/init.js +15 -0
  94. package/src/directive/init.md +41 -0
  95. package/src/directive/input.js +1783 -0
  96. package/src/directive/list.js +46 -0
  97. package/src/directive/list.md +22 -0
  98. package/src/directive/ngClass.js +249 -0
  99. package/src/directive/ngController.js +64 -0
  100. package/src/directive/ngCsp.js +82 -0
  101. package/src/directive/ngIf.js +134 -0
  102. package/src/directive/ngInclude.js +217 -0
  103. package/src/directive/ngModel.js +1356 -0
  104. package/src/directive/ngModelOptions.js +509 -0
  105. package/src/directive/ngOptions.js +670 -0
  106. package/src/directive/ngRef.js +90 -0
  107. package/src/directive/ngRepeat.js +650 -0
  108. package/src/directive/ngShowHide.js +255 -0
  109. package/src/directive/ngSwitch.js +178 -0
  110. package/src/directive/ngTransclude.js +98 -0
  111. package/src/directive/non-bindable.js +11 -0
  112. package/src/directive/non-bindable.md +17 -0
  113. package/src/directive/script.js +30 -0
  114. package/src/directive/select.js +624 -0
  115. package/src/directive/style.js +25 -0
  116. package/src/directive/style.md +23 -0
  117. package/src/directive/validators.js +329 -0
  118. package/src/exts/aria.js +544 -0
  119. package/src/exts/messages.js +852 -0
  120. package/src/filters/filter.js +207 -0
  121. package/src/filters/filter.md +69 -0
  122. package/src/filters/filters.js +239 -0
  123. package/src/filters/json.md +16 -0
  124. package/src/filters/limit-to.js +43 -0
  125. package/src/filters/limit-to.md +19 -0
  126. package/src/filters/order-by.js +183 -0
  127. package/src/filters/order-by.md +83 -0
  128. package/src/index.js +13 -0
  129. package/src/injector.js +1034 -0
  130. package/src/jqLite.js +1117 -0
  131. package/src/loader.js +1320 -0
  132. package/src/public.js +215 -0
  133. package/src/routeToRegExp.js +41 -0
  134. package/src/services/anchorScroll.js +135 -0
  135. package/src/services/browser.js +321 -0
  136. package/src/services/cacheFactory.js +398 -0
  137. package/src/services/cookieReader.js +72 -0
  138. package/src/services/document.js +64 -0
  139. package/src/services/http.js +1537 -0
  140. package/src/services/httpBackend.js +206 -0
  141. package/src/services/log.js +160 -0
  142. package/src/services/templateRequest.js +139 -0
  143. package/test/angular.spec.js +2153 -0
  144. package/test/aria/aria.spec.js +1245 -0
  145. package/test/binding.spec.js +504 -0
  146. package/test/build-test.html +14 -0
  147. package/test/injector.spec.js +2327 -0
  148. package/test/jasmine/jasmine-5.1.2/boot0.js +65 -0
  149. package/test/jasmine/jasmine-5.1.2/boot1.js +133 -0
  150. package/test/jasmine/jasmine-5.1.2/jasmine-html.js +963 -0
  151. package/test/jasmine/jasmine-5.1.2/jasmine.css +320 -0
  152. package/test/jasmine/jasmine-5.1.2/jasmine.js +10824 -0
  153. package/test/jasmine/jasmine-5.1.2/jasmine_favicon.png +0 -0
  154. package/test/jasmine/jasmine-browser.json +17 -0
  155. package/test/jasmine/jasmine.json +9 -0
  156. package/test/jqlite.spec.js +2133 -0
  157. package/test/loader.spec.js +219 -0
  158. package/test/messages/messages.spec.js +1146 -0
  159. package/test/min-err.spec.js +174 -0
  160. package/test/mock-test.html +13 -0
  161. package/test/module-test.html +15 -0
  162. package/test/ng/anomate.spec.js +606 -0
  163. package/test/ng/cache-factor.spec.js +334 -0
  164. package/test/ng/compile.spec.js +17956 -0
  165. package/test/ng/controller-provider.spec.js +227 -0
  166. package/test/ng/cookie-reader.spec.js +98 -0
  167. package/test/ng/directive/a.spec.js +192 -0
  168. package/test/ng/directive/bind.spec.js +334 -0
  169. package/test/ng/directive/boolean.spec.js +136 -0
  170. package/test/ng/directive/change.spec.js +71 -0
  171. package/test/ng/directive/class.spec.js +858 -0
  172. package/test/ng/directive/click.spec.js +38 -0
  173. package/test/ng/directive/cloak.spec.js +44 -0
  174. package/test/ng/directive/constoller.spec.js +194 -0
  175. package/test/ng/directive/element-style.spec.js +92 -0
  176. package/test/ng/directive/event.spec.js +282 -0
  177. package/test/ng/directive/form.spec.js +1518 -0
  178. package/test/ng/directive/href.spec.js +143 -0
  179. package/test/ng/directive/if.spec.js +402 -0
  180. package/test/ng/directive/include.spec.js +828 -0
  181. package/test/ng/directive/init.spec.js +68 -0
  182. package/test/ng/directive/input.spec.js +3810 -0
  183. package/test/ng/directive/list.spec.js +170 -0
  184. package/test/ng/directive/model-options.spec.js +1008 -0
  185. package/test/ng/directive/model.spec.js +1905 -0
  186. package/test/ng/directive/non-bindable.spec.js +55 -0
  187. package/test/ng/directive/options.spec.js +3583 -0
  188. package/test/ng/directive/ref.spec.js +575 -0
  189. package/test/ng/directive/repeat.spec.js +1675 -0
  190. package/test/ng/directive/script.spec.js +52 -0
  191. package/test/ng/directive/scrset.spec.js +67 -0
  192. package/test/ng/directive/select.spec.js +2541 -0
  193. package/test/ng/directive/show-hide.spec.js +253 -0
  194. package/test/ng/directive/src.spec.js +157 -0
  195. package/test/ng/directive/style.spec.js +178 -0
  196. package/test/ng/directive/switch.spec.js +647 -0
  197. package/test/ng/directive/validators.spec.js +717 -0
  198. package/test/ng/document.spec.js +52 -0
  199. package/test/ng/filter/filter.spec.js +714 -0
  200. package/test/ng/filter/filters.spec.js +35 -0
  201. package/test/ng/filter/limit-to.spec.js +251 -0
  202. package/test/ng/filter/order-by.spec.js +891 -0
  203. package/test/ng/filter.spec.js +149 -0
  204. package/test/ng/http-backend.spec.js +398 -0
  205. package/test/ng/http.spec.js +4071 -0
  206. package/test/ng/interpolate.spec.js +642 -0
  207. package/test/ng/interval.spec.js +343 -0
  208. package/test/ng/location.spec.js +3488 -0
  209. package/test/ng/on.spec.js +229 -0
  210. package/test/ng/parse.spec.js +4655 -0
  211. package/test/ng/prop.spec.js +805 -0
  212. package/test/ng/q.spec.js +2904 -0
  213. package/test/ng/root-element.spec.js +16 -0
  214. package/test/ng/sanitize-uri.spec.js +249 -0
  215. package/test/ng/sce.spec.js +660 -0
  216. package/test/ng/scope.spec.js +3442 -0
  217. package/test/ng/template-request.spec.js +236 -0
  218. package/test/ng/timeout.spec.js +351 -0
  219. package/test/ng/url-utils.spec.js +156 -0
  220. package/test/ng/utils.spec.js +144 -0
  221. package/test/original-test.html +21 -0
  222. package/test/public.spec.js +34 -0
  223. package/test/sanitize/bing-html.spec.js +36 -0
  224. package/test/server/express.js +158 -0
  225. package/test/test-utils.js +11 -0
  226. package/tsconfig.json +17 -0
  227. package/types/angular.d.ts +138 -0
  228. package/types/global.d.ts +9 -0
  229. package/types/index.d.ts +2357 -0
  230. package/types/jqlite.d.ts +558 -0
  231. package/vite.config.js +14 -0
@@ -0,0 +1,714 @@
1
+ import { publishExternalAPI } from "../../../src/public";
2
+ import { createInjector } from "../../../src/injector";
3
+ import { createMap, isString, includes } from "../../../src/core/utils";
4
+ import { jqLite } from "../../../src/jqLite";
5
+
6
+ describe("Filter: filter", () => {
7
+ let filter;
8
+
9
+ beforeEach(() => {
10
+ publishExternalAPI();
11
+ var injector = createInjector(["ng"]);
12
+ filter = injector.get("$filter")("filter");
13
+ });
14
+
15
+ it("should filter by string", () => {
16
+ const items = ["MIsKO", { name: "shyam" }, ["adam"], 1234];
17
+ expect(filter(items, "").length).toBe(4);
18
+ expect(filter(items, undefined).length).toBe(4);
19
+
20
+ expect(filter(items, "iSk").length).toBe(1);
21
+ expect(filter(items, "isk")[0]).toBe("MIsKO");
22
+
23
+ expect(filter(items, "yam").length).toBe(1);
24
+ expect(filter(items, "yam")[0]).toEqual(items[1]);
25
+
26
+ expect(filter(items, "da").length).toBe(1);
27
+ expect(filter(items, "da")[0]).toEqual(items[2]);
28
+
29
+ expect(filter(items, "34").length).toBe(1);
30
+ expect(filter(items, "34")[0]).toBe(1234);
31
+
32
+ expect(filter(items, "I don't exist").length).toBe(0);
33
+ });
34
+
35
+ it("should not read $ properties", () => {
36
+ expect("".charAt(0)).toBe(""); // assumption
37
+
38
+ const items = [{ $name: "misko" }];
39
+ expect(filter(items, "misko").length).toBe(0);
40
+ });
41
+
42
+ it("should filter on specific property", () => {
43
+ const items = [
44
+ { ignore: "a", name: "a" },
45
+ { ignore: "a", name: "abc" },
46
+ ];
47
+ expect(filter(items, {}).length).toBe(2);
48
+
49
+ expect(filter(items, { name: "a" }).length).toBe(2);
50
+
51
+ expect(filter(items, { name: "b" }).length).toBe(1);
52
+ expect(filter(items, { name: "b" })[0].name).toBe("abc");
53
+ });
54
+
55
+ it("should ignore undefined properties of the expression object", () => {
56
+ let items = [{ name: "a" }, { name: "abc" }];
57
+ expect(filter(items, { name: undefined })).toEqual([
58
+ { name: "a" },
59
+ { name: "abc" },
60
+ ]);
61
+
62
+ items = [
63
+ { first: "misko" },
64
+ { deep: { first: "misko" } },
65
+ { deep: { last: "hevery" } },
66
+ ];
67
+ expect(filter(items, { deep: { first: undefined } })).toEqual([
68
+ { deep: { first: "misko" } },
69
+ { deep: { last: "hevery" } },
70
+ ]);
71
+ });
72
+
73
+ it("should take function as predicate", () => {
74
+ const items = [{ name: "a" }, { name: "abc", done: true }];
75
+ expect(filter(items, (i) => i.done).length).toBe(1);
76
+ });
77
+
78
+ it("should pass the index to a function predicate", () => {
79
+ const items = [0, 1, 2, 3];
80
+
81
+ const result = filter(items, (value, index) => index % 2 === 0);
82
+
83
+ expect(result).toEqual([0, 2]);
84
+ });
85
+
86
+ it("should match primitive array values against top-level `$` property in object expression", () => {
87
+ let items;
88
+ let expr;
89
+
90
+ items = ["something", "something else", "another thing"];
91
+ expr = { $: "some" };
92
+ expect(filter(items, expr).length).toBe(2);
93
+ expect(filter(items, expr)).toEqual([items[0], items[1]]);
94
+
95
+ items = [
96
+ { val: "something" },
97
+ { val: "something else" },
98
+ { val: "another thing" },
99
+ ];
100
+ expr = { $: "some" };
101
+ expect(filter(items, expr).length).toBe(2);
102
+ expect(filter(items, expr)).toEqual([items[0], items[1]]);
103
+
104
+ items = [123, 456, 789];
105
+ expr = { $: 1 };
106
+ expect(filter(items, expr).length).toBe(1);
107
+ expect(filter(items, expr)).toEqual([items[0]]);
108
+
109
+ items = [true, false, "true"];
110
+ expr = { $: true, ignored: "false" };
111
+ expect(filter(items, expr).length).toBe(2);
112
+ expect(filter(items, expr)).toEqual([items[0], items[2]]);
113
+ });
114
+
115
+ it("should match items with array properties containing one or more matching items", () => {
116
+ let items;
117
+ let expr;
118
+
119
+ items = [
120
+ { tags: ["web", "html", "css", "js"] },
121
+ { tags: ["hybrid", "html", "css", "js", "ios", "android"] },
122
+ { tags: ["mobile", "ios", "android"] },
123
+ ];
124
+ expr = { tags: "html" };
125
+ expect(filter(items, expr).length).toBe(2);
126
+ expect(filter(items, expr)).toEqual([items[0], items[1]]);
127
+
128
+ items = [
129
+ { nums: [1, 345, 12] },
130
+ { nums: [0, 46, 78] },
131
+ { nums: [123, 4, 67] },
132
+ ];
133
+ expr = { nums: 12 };
134
+ expect(filter(items, expr).length).toBe(2);
135
+ expect(filter(items, expr)).toEqual([items[0], items[2]]);
136
+
137
+ items = [
138
+ { customers: [{ name: "John" }, { name: "Elena" }, { name: "Bill" }] },
139
+ { customers: [{ name: "Sam" }, { name: "Klara" }, { name: "Bill" }] },
140
+ { customers: [{ name: "Molli" }, { name: "Elena" }, { name: "Lora" }] },
141
+ ];
142
+ expr = { customers: { name: "Bill" } };
143
+ expect(filter(items, expr).length).toBe(2);
144
+ expect(filter(items, expr)).toEqual([items[0], items[1]]);
145
+ });
146
+
147
+ it("should take object as predicate", () => {
148
+ const items = [
149
+ { first: "misko", last: "hevery" },
150
+ { first: "adam", last: "abrons" },
151
+ ];
152
+
153
+ expect(filter(items, { first: "", last: "" }).length).toBe(2);
154
+ expect(filter(items, { first: "", last: "hevery" }).length).toBe(1);
155
+ expect(filter(items, { first: "adam", last: "hevery" }).length).toBe(0);
156
+ expect(filter(items, { first: "misko", last: "hevery" }).length).toBe(1);
157
+ expect(filter(items, { first: "misko", last: "hevery" })[0]).toEqual(
158
+ items[0],
159
+ );
160
+ });
161
+
162
+ it("should support predicate object with dots in the name", () => {
163
+ const items = [
164
+ { "first.name": "misko", "last.name": "hevery" },
165
+ { "first.name": "adam", "last.name": "abrons" },
166
+ ];
167
+
168
+ expect(filter(items, { "first.name": "", "last.name": "" }).length).toBe(2);
169
+ expect(filter(items, { "first.name": "misko", "last.name": "" })).toEqual([
170
+ items[0],
171
+ ]);
172
+ });
173
+
174
+ it("should support deep predicate objects", () => {
175
+ const items = [
176
+ { person: { name: "John" } },
177
+ { person: { name: "Rita" } },
178
+ { person: { name: "Billy" } },
179
+ { person: { name: "Joan" } },
180
+ ];
181
+ expect(filter(items, { person: { name: "Jo" } }).length).toBe(2);
182
+ expect(filter(items, { person: { name: "Jo" } })).toEqual([
183
+ { person: { name: "John" } },
184
+ { person: { name: "Joan" } },
185
+ ]);
186
+ });
187
+
188
+ it("should support deep expression objects with multiple properties", () => {
189
+ const items = [
190
+ { person: { name: "Annet", email: "annet@example.com" } },
191
+ { person: { name: "Billy", email: "me@billy.com" } },
192
+ { person: { name: "Joan", email: "joan@example.net" } },
193
+ { person: { name: "John", email: "john@example.com" } },
194
+ { person: { name: "Rita", email: "rita@example.com" } },
195
+ ];
196
+ const expr = { person: { name: "Jo", email: "!example.com" } };
197
+
198
+ expect(filter(items, expr).length).toBe(1);
199
+ expect(filter(items, expr)).toEqual([items[2]]);
200
+ });
201
+
202
+ it('should match any properties for given "$" property', () => {
203
+ const items = [
204
+ { first: "tom", last: "hevery" },
205
+ { first: "adam", last: "hevery", alias: "tom", done: false },
206
+ { first: "john", last: "clark", middle: "tommy" },
207
+ ];
208
+ expect(filter(items, { $: "tom" }).length).toBe(3);
209
+ expect(filter(items, { $: "a" }).length).toBe(2);
210
+ expect(filter(items, { $: false }).length).toBe(1);
211
+ expect(filter(items, { $: 10 }).length).toBe(0);
212
+ expect(filter(items, { $: "hevery" })[0]).toEqual(items[0]);
213
+ });
214
+
215
+ it('should allow specifying the special "match-all" property', () => {
216
+ const items = [{ foo: "baz" }, { bar: "baz" }, { "%": "no dollar" }];
217
+
218
+ expect(filter(items, { $: "baz" }).length).toBe(2);
219
+ expect(filter(items, { $: "baz" }, null, "%").length).toBe(0);
220
+
221
+ expect(filter(items, { "%": "dollar" }).length).toBe(1);
222
+ expect(filter(items, { $: "dollar" }).length).toBe(1);
223
+ expect(filter(items, { $: "dollar" }, null, "%").length).toBe(0);
224
+
225
+ expect(filter(items, { "%": "baz" }).length).toBe(0);
226
+ expect(filter(items, { "%": "baz" }, null, "%").length).toBe(2);
227
+ });
228
+
229
+ it('should match any properties in the nested object for given deep "$" property', () => {
230
+ const items = [
231
+ { person: { name: "Annet", email: "annet@example.com" } },
232
+ { person: { name: "Billy", email: "me@billy.com" } },
233
+ { person: { name: "Joan", email: "joan@example.net" } },
234
+ { person: { name: "John", email: "john@example.com" } },
235
+ { person: { name: "Rita", email: "rita@example.com" } },
236
+ ];
237
+ const expr = { person: { $: "net" } };
238
+
239
+ expect(filter(items, expr).length).toBe(2);
240
+ expect(filter(items, expr)).toEqual([items[0], items[2]]);
241
+ });
242
+
243
+ it("should match named properties only against named properties on the same level", () => {
244
+ const expr = { person: { name: "John" } };
245
+ const items = [
246
+ { person: "John" }, // No match (1 level higher)
247
+ { person: { name: "John" } }, // Match (same level)
248
+ { person: { name: { first: "John", last: "Doe" } } },
249
+ ]; // No match (1 level deeper)
250
+
251
+ expect(filter(items, expr).length).toBe(1);
252
+ expect(filter(items, expr)).toEqual([items[1]]);
253
+ });
254
+
255
+ it('should match any properties on same or deeper level for given "$" property', () => {
256
+ const items = [
257
+ { level1: "test", foo1: "bar1" },
258
+ { level1: { level2: "test", foo2: "bar2" }, foo1: "bar1" },
259
+ {
260
+ level1: { level2: { level3: "test", foo3: "bar3" }, foo2: "bar2" },
261
+ foo1: "bar1",
262
+ },
263
+ ];
264
+
265
+ expect(filter(items, { $: "ES" }).length).toBe(3);
266
+ expect(filter(items, { $: "ES" })).toEqual([items[0], items[1], items[2]]);
267
+
268
+ expect(filter(items, { level1: { $: "ES" } }).length).toBe(2);
269
+ expect(filter(items, { level1: { $: "ES" } })).toEqual([
270
+ items[1],
271
+ items[2],
272
+ ]);
273
+
274
+ expect(filter(items, { level1: { level2: { $: "ES" } } }).length).toBe(1);
275
+ expect(filter(items, { level1: { level2: { $: "ES" } } })).toEqual([
276
+ items[2],
277
+ ]);
278
+ });
279
+
280
+ it('should respect the nesting level of "$"', () => {
281
+ const items = [
282
+ {
283
+ supervisor: "me",
284
+ person: { name: "Annet", email: "annet@example.com" },
285
+ },
286
+ { supervisor: "me", person: { name: "Billy", email: "me@billy.com" } },
287
+ { supervisor: "me", person: { name: "Joan", email: "joan@example.net" } },
288
+ { supervisor: "me", person: { name: "John", email: "john@example.com" } },
289
+ { supervisor: "me", person: { name: "Rita", email: "rita@example.com" } },
290
+ ];
291
+ const expr = { $: { $: "me" } };
292
+
293
+ expect(filter(items, expr).length).toBe(1);
294
+ expect(filter(items, expr)).toEqual([items[1]]);
295
+ });
296
+
297
+ it("should support boolean properties", () => {
298
+ const items = [
299
+ { name: "tom", current: true },
300
+ { name: "demi", current: false },
301
+ { name: "sofia" },
302
+ ];
303
+
304
+ expect(filter(items, { current: true }).length).toBe(1);
305
+ expect(filter(items, { current: true })[0].name).toBe("tom");
306
+ expect(filter(items, { current: false }).length).toBe(1);
307
+ expect(filter(items, { current: false })[0].name).toBe("demi");
308
+ });
309
+
310
+ it("should support negation operator", () => {
311
+ const items = ["misko", "adam"];
312
+
313
+ expect(filter(items, "!isk").length).toBe(1);
314
+ expect(filter(items, "!isk")[0]).toEqual(items[1]);
315
+ });
316
+
317
+ it("should ignore function properties in items", () => {
318
+ // Own function properties
319
+ let items = [
320
+ { text: "hello", func: () => {} },
321
+ { text: "goodbye" },
322
+ { text: "kittens" },
323
+ { text: "puppies" },
324
+ ];
325
+ const expr = { text: "hello" };
326
+
327
+ expect(filter(items, expr).length).toBe(1);
328
+ expect(filter(items, expr)[0]).toBe(items[0]);
329
+ expect(filter(items, expr, true).length).toBe(1);
330
+ expect(filter(items, expr, true)[0]).toBe(items[0]);
331
+
332
+ // Inherited function properties
333
+ class Item {
334
+ constructor(text) {
335
+ this.text = text;
336
+ }
337
+ func() {}
338
+ }
339
+
340
+ items = [
341
+ new Item("hello"),
342
+ new Item("goodbye"),
343
+ new Item("kittens"),
344
+ new Item("puppies"),
345
+ ];
346
+
347
+ expect(filter(items, expr).length).toBe(1);
348
+ expect(filter(items, expr)[0]).toBe(items[0]);
349
+ expect(filter(items, expr, true).length).toBe(1);
350
+ expect(filter(items, expr, true)[0]).toBe(items[0]);
351
+ });
352
+
353
+ it("should ignore function properties in expression", () => {
354
+ // Own function properties
355
+ const items = [
356
+ { text: "hello" },
357
+ { text: "goodbye" },
358
+ { text: "kittens" },
359
+ { text: "puppies" },
360
+ ];
361
+ let expr = { text: "hello", func: () => {} };
362
+
363
+ expect(filter(items, expr).length).toBe(1);
364
+ expect(filter(items, expr)[0]).toBe(items[0]);
365
+ expect(filter(items, expr, true).length).toBe(1);
366
+ expect(filter(items, expr, true)[0]).toBe(items[0]);
367
+
368
+ // Inherited function properties
369
+ class Expr {
370
+ constructor(text) {
371
+ this.text = text;
372
+ }
373
+ func() {}
374
+ }
375
+
376
+ expr = new Expr("hello");
377
+
378
+ expect(filter(items, expr).length).toBe(1);
379
+ expect(filter(items, expr)[0]).toBe(items[0]);
380
+ expect(filter(items, expr, true).length).toBe(1);
381
+ expect(filter(items, expr, true)[0]).toBe(items[0]);
382
+ });
383
+
384
+ it("should consider inherited properties in items", () => {
385
+ class Item {
386
+ constructor(text) {
387
+ this.text = text;
388
+ }
389
+ }
390
+ Item.prototype.doubleL = "maybe";
391
+
392
+ const items = [
393
+ new Item("hello"),
394
+ new Item("goodbye"),
395
+ new Item("kittens"),
396
+ new Item("puppies"),
397
+ ];
398
+ let expr = { text: "hello", doubleL: "perhaps" };
399
+
400
+ expect(filter(items, expr).length).toBe(0);
401
+ expect(filter(items, expr, true).length).toBe(0);
402
+
403
+ expr = { text: "hello", doubleL: "maybe" };
404
+
405
+ expect(filter(items, expr).length).toBe(1);
406
+ expect(filter(items, expr)[0]).toBe(items[0]);
407
+ expect(filter(items, expr, true).length).toBe(1);
408
+ expect(filter(items, expr, true)[0]).toBe(items[0]);
409
+ });
410
+
411
+ it("should consider inherited properties in expression", () => {
412
+ class Expr {
413
+ constructor(text) {
414
+ this.text = text;
415
+ }
416
+ }
417
+ Expr.prototype.doubleL = true;
418
+
419
+ const items = [
420
+ { text: "hello", doubleL: true },
421
+ { text: "goodbye" },
422
+ { text: "kittens" },
423
+ { text: "puppies" },
424
+ ];
425
+ let expr = new Expr("e");
426
+
427
+ expect(filter(items, expr).length).toBe(1);
428
+ expect(filter(items, expr)[0]).toBe(items[0]);
429
+
430
+ expr = new Expr("hello");
431
+
432
+ expect(filter(items, expr, true).length).toBe(1);
433
+ expect(filter(items, expr)[0]).toBe(items[0]);
434
+ });
435
+
436
+ it("should not be affected by `Object.prototype` when using a string expression", () => {
437
+ // eslint-disable-next-line no-extend-native
438
+ Object.prototype.someProp = "oo";
439
+
440
+ const items = [createMap(), createMap(), createMap(), createMap()];
441
+ items[0].someProp = "hello";
442
+ items[1].someProp = "goodbye";
443
+ items[2].someProp = "kittens";
444
+ items[3].someProp = "puppies";
445
+
446
+ // Affected by `Object.prototype`
447
+ expect(filter(items, {}).length).toBe(1);
448
+ expect(filter(items, {})[0]).toBe(items[1]);
449
+
450
+ expect(filter(items, { $: "ll" }).length).toBe(0);
451
+
452
+ // Not affected by `Object.prototype`
453
+ expect(filter(items, "ll").length).toBe(1);
454
+ expect(filter(items, "ll")[0]).toBe(items[0]);
455
+
456
+ delete Object.prototype.someProp;
457
+ });
458
+
459
+ it("should throw an error when is not used with an array", () => {
460
+ let item = { not: "array" };
461
+ expect(() => {
462
+ filter(item, {});
463
+ }).toThrowError(/notarray/);
464
+
465
+ item = Object.create(null);
466
+ expect(() => {
467
+ filter(item, {});
468
+ }).toThrowError(/notarray/);
469
+
470
+ item = {
471
+ toString: null,
472
+ valueOf: null,
473
+ };
474
+ expect(() => {
475
+ filter(item, {});
476
+ }).toThrowError(/notarray/);
477
+ });
478
+
479
+ it("should not throw an error if used with an array like object", () => {
480
+ function getArguments() {
481
+ return arguments;
482
+ }
483
+ const argsObj = getArguments(
484
+ { name: "Misko" },
485
+ { name: "Igor" },
486
+ { name: "Brad" },
487
+ );
488
+
489
+ const nodeList = jqLite(
490
+ "<p><span>Misko</span><span>Igor</span><span>Brad</span></p>",
491
+ )[0].childNodes;
492
+ function nodeFilterPredicate(node) {
493
+ return node.innerHTML.indexOf("I") !== -1;
494
+ }
495
+
496
+ expect(filter(argsObj, "i").length).toBe(2);
497
+ expect(filter("abc", "b").length).toBe(1);
498
+ expect(filter(nodeList, nodeFilterPredicate).length).toBe(1);
499
+ });
500
+
501
+ it("should return undefined when the array is undefined", () => {
502
+ expect(filter(undefined, {})).toBeUndefined();
503
+ });
504
+
505
+ it("should return null when the value of the array is null", () => {
506
+ const item = null;
507
+ expect(filter(item, {})).toBe(null);
508
+ });
509
+
510
+ it("should not throw an error if property is null when comparing object", () => {
511
+ const items = [
512
+ { office: 1, people: { name: "john" } },
513
+ { office: 2, people: { name: "jane" } },
514
+ { office: 3, people: null },
515
+ ];
516
+ let f = {};
517
+ expect(filter(items, f).length).toBe(3);
518
+
519
+ f = { people: null };
520
+ expect(filter(items, f).length).toBe(1);
521
+
522
+ f = { people: {} };
523
+ expect(filter(items, f).length).toBe(2);
524
+
525
+ f = { people: { name: "" } };
526
+ expect(filter(items, f).length).toBe(2);
527
+
528
+ f = { people: { name: "john" } };
529
+ expect(filter(items, f).length).toBe(1);
530
+
531
+ f = { people: { name: "j" } };
532
+ expect(filter(items, f).length).toBe(2);
533
+ });
534
+
535
+ it("should match `null` against `null` only", () => {
536
+ const items = [
537
+ { value: null },
538
+ { value: undefined },
539
+ { value: true },
540
+ { value: false },
541
+ { value: NaN },
542
+ { value: 42 },
543
+ { value: "null" },
544
+ { value: "test" },
545
+ { value: {} },
546
+ { value: new Date() },
547
+ ];
548
+ let flt;
549
+
550
+ flt = null;
551
+ expect(filter(items, flt).length).toBe(1);
552
+ expect(filter(items, flt)[0]).toBe(items[0]);
553
+
554
+ flt = { value: null };
555
+ expect(filter(items, flt).length).toBe(1);
556
+ expect(filter(items, flt)[0]).toBe(items[0]);
557
+
558
+ flt = { value: undefined };
559
+ expect(filter(items, flt).length).toBe(items.length);
560
+
561
+ flt = { value: NaN };
562
+ expect(includes(filter(items, flt), items[0])).toBeFalsy();
563
+
564
+ flt = { value: false };
565
+ expect(includes(filter(items, flt), items[0])).toBeFalsy();
566
+
567
+ flt = "";
568
+ expect(includes(filter(items, flt), items[0])).toBeFalsy();
569
+
570
+ flt = { value: "null" };
571
+ expect(includes(filter(items, flt), items[0])).toBeFalsy();
572
+ });
573
+
574
+ describe("should support comparator", () => {
575
+ it("not convert `null` or `undefined` to string in non-strict comparison", () => {
576
+ const items = [{ value: null }, { value: undefined }];
577
+ const flt = { value: "u" };
578
+
579
+ expect(filter(items, flt).length).toBe(0);
580
+ });
581
+
582
+ it("not consider objects without a custom `toString` in non-strict comparison", () => {
583
+ const items = [{ test: {} }];
584
+ const expr = "[object";
585
+ expect(filter(items, expr).length).toBe(0);
586
+ });
587
+
588
+ it("should consider objects with custom `toString()` in non-strict comparison", () => {
589
+ let obj = new Date(1970, 1);
590
+ let items = [{ test: obj }];
591
+ expect(filter(items, "1970").length).toBe(1);
592
+ expect(filter(items, 1970).length).toBe(1);
593
+
594
+ obj = {
595
+ toString() {
596
+ return "custom";
597
+ },
598
+ };
599
+ items = [{ test: obj }];
600
+ expect(filter(items, "custom").length).toBe(1);
601
+ });
602
+
603
+ it("should cope with objects that have no `toString()` in non-strict comparison", () => {
604
+ const obj = Object.create(null);
605
+ const items = [{ test: obj }];
606
+ expect(() => {
607
+ filter(items, "foo");
608
+ }).not.toThrow();
609
+ expect(filter(items, "foo").length).toBe(0);
610
+ });
611
+
612
+ it("should cope with objects where `toString` is not a function in non-strict comparison", () => {
613
+ const obj = {
614
+ toString: "moo",
615
+ };
616
+ const items = [{ test: obj }];
617
+ expect(() => {
618
+ filter(items, "foo");
619
+ }).not.toThrow();
620
+ expect(filter(items, "foo").length).toBe(0);
621
+ });
622
+
623
+ it("as equality when true", () => {
624
+ let items = ["misko", "adam", "adamson"];
625
+ let expr = "adam";
626
+ expect(filter(items, expr, true)).toEqual([items[1]]);
627
+ expect(filter(items, expr, false)).toEqual([items[1], items[2]]);
628
+
629
+ items = [
630
+ { key: "value1", nonkey: 1 },
631
+ { key: "value2", nonkey: 2 },
632
+ { key: "value12", nonkey: 3 },
633
+ { key: "value1", nonkey: 4 },
634
+ { key: "Value1", nonkey: 5 },
635
+ ];
636
+ expr = { key: "value1" };
637
+ expect(filter(items, expr, true)).toEqual([items[0], items[3]]);
638
+
639
+ items = [
640
+ { key: 1, nonkey: 1 },
641
+ { key: 2, nonkey: 2 },
642
+ { key: 12, nonkey: 3 },
643
+ { key: 1, nonkey: 4 },
644
+ ];
645
+ expr = { key: 1 };
646
+ expect(filter(items, expr, true)).toEqual([items[0], items[3]]);
647
+
648
+ expr = 12;
649
+ expect(filter(items, expr, true)).toEqual([items[2]]);
650
+ });
651
+
652
+ it("and use the function given to compare values", () => {
653
+ const items = [
654
+ { key: 1, nonkey: 1 },
655
+ { key: 2, nonkey: 2 },
656
+ { key: 12, nonkey: 3 },
657
+ { key: 1, nonkey: 14 },
658
+ ];
659
+ let expr = { key: 10 };
660
+ const comparator = function (obj, value) {
661
+ return obj > value;
662
+ };
663
+ expect(filter(items, expr, comparator)).toEqual([items[2]]);
664
+
665
+ expr = 10;
666
+ expect(filter(items, expr, comparator)).toEqual([items[2], items[3]]);
667
+ });
668
+
669
+ it("and use it correctly with deep expression objects", () => {
670
+ const items = [
671
+ { id: 0, details: { email: "admin@example.com", role: "admin" } },
672
+ { id: 1, details: { email: "user1@example.com", role: "user" } },
673
+ { id: 2, details: { email: "user2@example.com", role: "user" } },
674
+ ];
675
+ let expr;
676
+ let comp;
677
+
678
+ expr = { details: { email: "user@example.com", role: "adm" } };
679
+ expect(filter(items, expr)).toEqual([]);
680
+
681
+ expr = { details: { email: "admin@example.com", role: "adm" } };
682
+ expect(filter(items, expr)).toEqual([items[0]]);
683
+
684
+ expr = { details: { email: "admin@example.com", role: "adm" } };
685
+ expect(filter(items, expr, true)).toEqual([]);
686
+
687
+ expr = { details: { email: "admin@example.com", role: "admin" } };
688
+ expect(filter(items, expr, true)).toEqual([items[0]]);
689
+
690
+ expr = { details: { email: "user", role: "us" } };
691
+ expect(filter(items, expr)).toEqual([items[1], items[2]]);
692
+
693
+ expr = { id: 0, details: { email: "user", role: "us" } };
694
+ expect(filter(items, expr)).toEqual([]);
695
+
696
+ expr = { id: 1, details: { email: "user", role: "us" } };
697
+ expect(filter(items, expr)).toEqual([items[1]]);
698
+
699
+ comp = function (actual, expected) {
700
+ return (
701
+ isString(actual) &&
702
+ isString(expected) &&
703
+ actual.indexOf(expected) === 0
704
+ );
705
+ };
706
+
707
+ expr = { details: { email: "admin@example.com", role: "min" } };
708
+ expect(filter(items, expr, comp)).toEqual([]);
709
+
710
+ expr = { details: { email: "admin@example.com", role: "adm" } };
711
+ expect(filter(items, expr, comp)).toEqual([items[0]]);
712
+ });
713
+ });
714
+ });