@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,2153 @@
1
+ import {
2
+ lowercase,
3
+ uppercase,
4
+ extend,
5
+ isDefined,
6
+ merge,
7
+ isDate,
8
+ isRegExp,
9
+ isElement,
10
+ shallowCopy,
11
+ equals,
12
+ isWindow,
13
+ hashKey,
14
+ toKeyValue,
15
+ parseKeyValue,
16
+ isError,
17
+ isArray,
18
+ isArrayLike,
19
+ encodeUriSegment,
20
+ encodeUriQuery,
21
+ forEach,
22
+ toJson,
23
+ fromJson,
24
+ nextUid,
25
+ nodeName_,
26
+ snakeCase,
27
+ } from "../src/core/utils";
28
+ import { dealoc, jqLite, startingTag } from "../src/jqLite";
29
+ import { Angular, angularInit } from "../src/loader";
30
+ import { publishExternalAPI } from "../src/public";
31
+ import { createInjector } from "../src/injector";
32
+
33
+ describe("angular", () => {
34
+ let element, document, module, injector, $rootScope, $compile;
35
+
36
+ beforeEach(() => {
37
+ window.angular = new Angular();
38
+ publishExternalAPI();
39
+ createInjector();
40
+ module = window.angular.module("defaultModule", ["ng"]);
41
+ injector = createInjector(["ng", "defaultModule"]);
42
+ $rootScope = injector.get("$rootScope");
43
+ $compile = injector.get("$compile");
44
+ });
45
+
46
+ beforeEach(() => {
47
+ document = window.document;
48
+ });
49
+
50
+ afterEach(() => {
51
+ dealoc(element);
52
+ });
53
+
54
+ describe("case", () => {
55
+ it("should change case", () => {
56
+ expect(lowercase("ABC90")).toEqual("abc90");
57
+ expect(uppercase("abc90")).toEqual("ABC90");
58
+ });
59
+
60
+ it("should change case of non-ASCII letters", () => {
61
+ expect(lowercase("Ω")).toEqual("ω");
62
+ expect(uppercase("ω")).toEqual("Ω");
63
+ });
64
+ });
65
+
66
+ // describe("copy", () => {
67
+ // it("should return same object", () => {
68
+ // const obj = {};
69
+ // const arr = [];
70
+ // expect(copy({}, obj)).toBe(obj);
71
+ // expect(copy([], arr)).toBe(arr);
72
+ // });
73
+
74
+ // it("should preserve prototype chaining", () => {
75
+ // const GrandParentProto = {};
76
+ // const ParentProto = Object.create(GrandParentProto);
77
+ // const obj = Object.create(ParentProto);
78
+ // expect(ParentProto.isPrototypeOf(copy(obj))).toBe(true);
79
+ // expect(GrandParentProto.isPrototypeOf(copy(obj))).toBe(true);
80
+ // const Foo = function () {};
81
+ // expect(copy(new Foo()) instanceof Foo).toBe(true);
82
+ // });
83
+
84
+ // it("should copy Date", () => {
85
+ // const date = new Date(123);
86
+ // expect(copy(date) instanceof Date).toBeTruthy();
87
+ // expect(copy(date).getTime()).toEqual(123);
88
+ // expect(copy(date) === date).toBeFalsy();
89
+ // });
90
+
91
+ // it("should copy RegExp", () => {
92
+ // const re = new RegExp(".*");
93
+ // expect(copy(re) instanceof RegExp).toBeTruthy();
94
+ // expect(copy(re).source).toBe(".*");
95
+ // expect(copy(re) === re).toBe(false);
96
+ // });
97
+
98
+ // it("should copy literal RegExp", () => {
99
+ // const re = /.*/;
100
+ // expect(copy(re) instanceof RegExp).toBeTruthy();
101
+ // expect(copy(re).source).toEqual(".*");
102
+ // expect(copy(re) === re).toBeFalsy();
103
+ // });
104
+
105
+ // it("should copy RegExp with flags", () => {
106
+ // const re = new RegExp(".*", "gim");
107
+ // expect(copy(re).global).toBe(true);
108
+ // expect(copy(re).ignoreCase).toBe(true);
109
+ // expect(copy(re).multiline).toBe(true);
110
+ // });
111
+
112
+ // it("should copy RegExp with lastIndex", () => {
113
+ // const re = /a+b+/g;
114
+ // const str = "ab aabb";
115
+ // expect(re.exec(str)[0]).toEqual("ab");
116
+ // expect(copy(re).exec(str)[0]).toEqual("aabb");
117
+ // });
118
+
119
+ // it("should deeply copy literal RegExp", () => {
120
+ // const objWithRegExp = {
121
+ // re: /.*/,
122
+ // };
123
+ // expect(copy(objWithRegExp).re instanceof RegExp).toBeTruthy();
124
+ // expect(copy(objWithRegExp).re.source).toEqual(".*");
125
+ // expect(copy(objWithRegExp.re) === objWithRegExp.re).toBeFalsy();
126
+ // });
127
+
128
+ // it("should copy a Uint8Array with no destination", () => {
129
+ // if (typeof Uint8Array !== "undefined") {
130
+ // const src = new Uint8Array(2);
131
+ // src[1] = 1;
132
+ // const dst = copy(src);
133
+ // expect(copy(src) instanceof Uint8Array).toBeTruthy();
134
+ // expect(dst).toEqual(src);
135
+ // expect(dst).not.toBe(src);
136
+ // expect(dst.buffer).not.toBe(src.buffer);
137
+ // }
138
+ // });
139
+
140
+ // it("should copy a Uint8ClampedArray with no destination", () => {
141
+ // if (typeof Uint8ClampedArray !== "undefined") {
142
+ // const src = new Uint8ClampedArray(2);
143
+ // src[1] = 1;
144
+ // const dst = copy(src);
145
+ // expect(copy(src) instanceof Uint8ClampedArray).toBeTruthy();
146
+ // expect(dst).toEqual(src);
147
+ // expect(dst).not.toBe(src);
148
+ // expect(dst.buffer).not.toBe(src.buffer);
149
+ // }
150
+ // });
151
+
152
+ // it("should copy a Uint16Array with no destination", () => {
153
+ // if (typeof Uint16Array !== "undefined") {
154
+ // const src = new Uint16Array(2);
155
+ // src[1] = 1;
156
+ // const dst = copy(src);
157
+ // expect(copy(src) instanceof Uint16Array).toBeTruthy();
158
+ // expect(dst).toEqual(src);
159
+ // expect(dst).not.toBe(src);
160
+ // expect(dst.buffer).not.toBe(src.buffer);
161
+ // }
162
+ // });
163
+
164
+ // it("should copy a Uint32Array with no destination", () => {
165
+ // if (typeof Uint32Array !== "undefined") {
166
+ // const src = new Uint32Array(2);
167
+ // src[1] = 1;
168
+ // const dst = copy(src);
169
+ // expect(copy(src) instanceof Uint32Array).toBeTruthy();
170
+ // expect(dst).toEqual(src);
171
+ // expect(dst).not.toBe(src);
172
+ // expect(dst.buffer).not.toBe(src.buffer);
173
+ // }
174
+ // });
175
+
176
+ // it("should copy a Int8Array with no destination", () => {
177
+ // if (typeof Int8Array !== "undefined") {
178
+ // const src = new Int8Array(2);
179
+ // src[1] = 1;
180
+ // const dst = copy(src);
181
+ // expect(copy(src) instanceof Int8Array).toBeTruthy();
182
+ // expect(dst).toEqual(src);
183
+ // expect(dst).not.toBe(src);
184
+ // expect(dst.buffer).not.toBe(src.buffer);
185
+ // }
186
+ // });
187
+
188
+ // it("should copy a Int16Array with no destination", () => {
189
+ // if (typeof Int16Array !== "undefined") {
190
+ // const src = new Int16Array(2);
191
+ // src[1] = 1;
192
+ // const dst = copy(src);
193
+ // expect(copy(src) instanceof Int16Array).toBeTruthy();
194
+ // expect(dst).toEqual(src);
195
+ // expect(dst).not.toBe(src);
196
+ // expect(dst.buffer).not.toBe(src.buffer);
197
+ // }
198
+ // });
199
+
200
+ // it("should copy a Int32Array with no destination", () => {
201
+ // if (typeof Int32Array !== "undefined") {
202
+ // const src = new Int32Array(2);
203
+ // src[1] = 1;
204
+ // const dst = copy(src);
205
+ // expect(copy(src) instanceof Int32Array).toBeTruthy();
206
+ // expect(dst).toEqual(src);
207
+ // expect(dst).not.toBe(src);
208
+ // expect(dst.buffer).not.toBe(src.buffer);
209
+ // }
210
+ // });
211
+
212
+ // it("should copy a Float32Array with no destination", () => {
213
+ // if (typeof Float32Array !== "undefined") {
214
+ // const src = new Float32Array(2);
215
+ // src[1] = 1;
216
+ // const dst = copy(src);
217
+ // expect(copy(src) instanceof Float32Array).toBeTruthy();
218
+ // expect(dst).toEqual(src);
219
+ // expect(dst).not.toBe(src);
220
+ // expect(dst.buffer).not.toBe(src.buffer);
221
+ // }
222
+ // });
223
+
224
+ // it("should copy a Float64Array with no destination", () => {
225
+ // if (typeof Float64Array !== "undefined") {
226
+ // const src = new Float64Array(2);
227
+ // src[1] = 1;
228
+ // const dst = copy(src);
229
+ // expect(copy(src) instanceof Float64Array).toBeTruthy();
230
+ // expect(dst).toEqual(src);
231
+ // expect(dst).not.toBe(src);
232
+ // expect(dst.buffer).not.toBe(src.buffer);
233
+ // }
234
+ // });
235
+
236
+ // it("should copy an ArrayBuffer with no destination", () => {
237
+ // if (typeof ArrayBuffer !== "undefined") {
238
+ // const src = new ArrayBuffer(8);
239
+ // new Int32Array(src).set([1, 2]);
240
+
241
+ // const dst = copy(src);
242
+ // expect(dst instanceof ArrayBuffer).toBeTruthy();
243
+ // expect(dst).toEqual(src);
244
+ // expect(dst).not.toBe(src);
245
+ // }
246
+ // });
247
+
248
+ // it("should handle ArrayBuffer objects with multiple references", () => {
249
+ // if (typeof ArrayBuffer !== "undefined") {
250
+ // const buffer = new ArrayBuffer(8);
251
+ // const src = [new Int32Array(buffer), new Float32Array(buffer)];
252
+ // src[0].set([1, 2]);
253
+
254
+ // const dst = copy(src);
255
+ // expect(dst).toEqual(src);
256
+ // expect(dst[0]).not.toBe(src[0]);
257
+ // expect(dst[1]).not.toBe(src[1]);
258
+ // expect(dst[0].buffer).toBe(dst[1].buffer);
259
+ // expect(dst[0].buffer).not.toBe(buffer);
260
+ // }
261
+ // });
262
+
263
+ // it("should handle Int32Array objects with multiple references", () => {
264
+ // if (typeof Int32Array !== "undefined") {
265
+ // const arr = new Int32Array(2);
266
+ // const src = [arr, arr];
267
+ // arr.set([1, 2]);
268
+
269
+ // const dst = copy(src);
270
+ // expect(dst).toEqual(src);
271
+ // expect(dst).not.toBe(src);
272
+ // expect(dst[0]).not.toBe(src[0]);
273
+ // expect(dst[0]).toBe(dst[1]);
274
+ // expect(dst[0].buffer).toBe(dst[1].buffer);
275
+ // }
276
+ // });
277
+
278
+ // it("should handle Blob objects", () => {
279
+ // if (typeof Blob !== "undefined") {
280
+ // const src = new Blob(["foo"], { type: "bar" });
281
+ // const dst = copy(src);
282
+
283
+ // expect(dst).not.toBe(src);
284
+ // expect(dst.size).toBe(3);
285
+ // expect(dst.type).toBe("bar");
286
+ // expect(isBlob(dst)).toBe(true);
287
+ // }
288
+ // });
289
+
290
+ // it("should handle Uint16Array subarray", () => {
291
+ // if (typeof Uint16Array !== "undefined") {
292
+ // const arr = new Uint16Array(4);
293
+ // arr[1] = 1;
294
+ // const src = arr.subarray(1, 2);
295
+ // const dst = copy(src);
296
+ // expect(dst instanceof Uint16Array).toBeTruthy();
297
+ // expect(dst.length).toEqual(1);
298
+ // expect(dst[0]).toEqual(1);
299
+ // expect(dst).not.toBe(src);
300
+ // expect(dst.buffer).not.toBe(src.buffer);
301
+ // }
302
+ // });
303
+
304
+ // it("should throw an exception if a Uint8Array is the destination", () => {
305
+ // if (typeof Uint8Array !== "undefined") {
306
+ // const src = new Uint8Array();
307
+ // const dst = new Uint8Array(5);
308
+ // expect(() => {
309
+ // copy(src, dst);
310
+ // }).toThrowError();
311
+ // }
312
+ // });
313
+
314
+ // it("should throw an exception if a Uint8ClampedArray is the destination", () => {
315
+ // if (typeof Uint8ClampedArray !== "undefined") {
316
+ // const src = new Uint8ClampedArray();
317
+ // const dst = new Uint8ClampedArray(5);
318
+ // expect(() => {
319
+ // copy(src, dst);
320
+ // }).toThrowError();
321
+ // }
322
+ // });
323
+
324
+ // it("should throw an exception if a Uint16Array is the destination", () => {
325
+ // if (typeof Uint16Array !== "undefined") {
326
+ // const src = new Uint16Array();
327
+ // const dst = new Uint16Array(5);
328
+ // expect(() => {
329
+ // copy(src, dst);
330
+ // }).toThrowError();
331
+ // }
332
+ // });
333
+
334
+ // it("should throw an exception if a Uint32Array is the destination", () => {
335
+ // if (typeof Uint32Array !== "undefined") {
336
+ // const src = new Uint32Array();
337
+ // const dst = new Uint32Array(5);
338
+ // expect(() => {
339
+ // copy(src, dst);
340
+ // }).toThrowError();
341
+ // }
342
+ // });
343
+
344
+ // it("should throw an exception if a Int8Array is the destination", () => {
345
+ // if (typeof Int8Array !== "undefined") {
346
+ // const src = new Int8Array();
347
+ // const dst = new Int8Array(5);
348
+ // expect(() => {
349
+ // copy(src, dst);
350
+ // }).toThrowError();
351
+ // }
352
+ // });
353
+
354
+ // it("should throw an exception if a Int16Array is the destination", () => {
355
+ // if (typeof Int16Array !== "undefined") {
356
+ // const src = new Int16Array();
357
+ // const dst = new Int16Array(5);
358
+ // expect(() => {
359
+ // copy(src, dst);
360
+ // }).toThrowError();
361
+ // }
362
+ // });
363
+
364
+ // it("should throw an exception if a Int32Array is the destination", () => {
365
+ // if (typeof Int32Array !== "undefined") {
366
+ // const src = new Int32Array();
367
+ // const dst = new Int32Array(5);
368
+ // expect(() => {
369
+ // copy(src, dst);
370
+ // }).toThrowError();
371
+ // }
372
+ // });
373
+
374
+ // it("should throw an exception if a Float32Array is the destination", () => {
375
+ // if (typeof Float32Array !== "undefined") {
376
+ // const src = new Float32Array();
377
+ // const dst = new Float32Array(5);
378
+ // expect(() => {
379
+ // copy(src, dst);
380
+ // }).toThrowError();
381
+ // }
382
+ // });
383
+
384
+ // it("should throw an exception if a Float64Array is the destination", () => {
385
+ // if (typeof Float64Array !== "undefined") {
386
+ // const src = new Float64Array();
387
+ // const dst = new Float64Array(5);
388
+ // expect(() => {
389
+ // copy(src, dst);
390
+ // }).toThrowError();
391
+ // }
392
+ // });
393
+
394
+ // it("should throw an exception if an ArrayBuffer is the destination", () => {
395
+ // if (typeof ArrayBuffer !== "undefined") {
396
+ // const src = new ArrayBuffer(5);
397
+ // const dst = new ArrayBuffer(5);
398
+ // expect(() => {
399
+ // copy(src, dst);
400
+ // }).toThrowError();
401
+ // }
402
+ // });
403
+
404
+ // it("should deeply copy an array into an existing array", () => {
405
+ // const src = [1, { name: "value" }];
406
+ // const dst = [{ key: "v" }];
407
+ // expect(copy(src, dst)).toBe(dst);
408
+ // expect(dst).toEqual([1, { name: "value" }]);
409
+ // expect(dst[1]).toEqual({ name: "value" });
410
+ // expect(dst[1]).not.toBe(src[1]);
411
+ // });
412
+
413
+ // it("should deeply copy an array into a new array", () => {
414
+ // const src = [1, { name: "value" }];
415
+ // const dst = copy(src);
416
+ // expect(src).toEqual([1, { name: "value" }]);
417
+ // expect(dst).toEqual(src);
418
+ // expect(dst).not.toBe(src);
419
+ // expect(dst[1]).not.toBe(src[1]);
420
+ // });
421
+
422
+ // it("should copy empty array", () => {
423
+ // const src = [];
424
+ // const dst = [{ key: "v" }];
425
+ // expect(copy(src, dst)).toEqual([]);
426
+ // expect(dst).toEqual([]);
427
+ // });
428
+
429
+ // it("should deeply copy an object into an existing object", () => {
430
+ // const src = { a: { name: "value" } };
431
+ // const dst = { b: { key: "v" } };
432
+ // expect(copy(src, dst)).toBe(dst);
433
+ // expect(dst).toEqual({ a: { name: "value" } });
434
+ // expect(dst.a).toEqual(src.a);
435
+ // expect(dst.a).not.toBe(src.a);
436
+ // });
437
+
438
+ // it("should deeply copy an object into a non-existing object", () => {
439
+ // const src = { a: { name: "value" } };
440
+ // const dst = copy(src, undefined);
441
+ // expect(src).toEqual({ a: { name: "value" } });
442
+ // expect(dst).toEqual(src);
443
+ // expect(dst).not.toBe(src);
444
+ // expect(dst.a).toEqual(src.a);
445
+ // expect(dst.a).not.toBe(src.a);
446
+ // });
447
+
448
+ // it("should copy primitives", () => {
449
+ // expect(copy(null)).toEqual(null);
450
+ // expect(copy("")).toBe("");
451
+ // expect(copy("lala")).toBe("lala");
452
+ // expect(copy(123)).toEqual(123);
453
+ // expect(copy([{ key: null }])).toEqual([{ key: null }]);
454
+ // });
455
+
456
+ // it("should throw an exception if a Scope is being copied", () => {
457
+ // expect(() => {
458
+ // copy($rootScope.$new());
459
+ // }).toThrowError(/cpws/);
460
+ // expect(() => {
461
+ // copy({ child: $rootScope.$new() }, {});
462
+ // }).toThrowError(/cpws/);
463
+ // expect(() => {
464
+ // copy([$rootScope.$new()]);
465
+ // }).toThrowError(/cpws/);
466
+ // });
467
+
468
+ // it("should throw an exception if a Window is being copied", () => {
469
+ // expect(() => {
470
+ // copy(window);
471
+ // }).toThrowError();
472
+ // expect(() => {
473
+ // copy({ child: window });
474
+ // }).toThrowError();
475
+ // expect(() => {
476
+ // copy([window], []);
477
+ // }).toThrowError();
478
+ // });
479
+
480
+ // it("should throw an exception when source and destination are equivalent", () => {
481
+ // let src;
482
+ // let dst;
483
+ // src = dst = { key: "value" };
484
+ // expect(() => {
485
+ // copy(src, dst);
486
+ // }).toThrowError();
487
+ // src = dst = [2, 4];
488
+ // expect(() => {
489
+ // copy(src, dst);
490
+ // }).toThrowError();
491
+ // });
492
+
493
+ // it("should not copy the private $$hashKey", () => {
494
+ // let src;
495
+ // let dst;
496
+ // src = {};
497
+ // hashKey(src);
498
+ // dst = copy(src);
499
+ // expect(hashKey(dst)).not.toEqual(hashKey(src));
500
+
501
+ // src = { foo: {} };
502
+ // hashKey(src.foo);
503
+ // dst = copy(src);
504
+ // expect(hashKey(src.foo)).not.toEqual(hashKey(dst.foo));
505
+ // });
506
+
507
+ // it("should retain the previous $$hashKey when copying object with hashKey", () => {
508
+ // let src;
509
+ // let dst;
510
+ // let h;
511
+ // src = {};
512
+ // dst = {};
513
+ // // force creation of a hashkey
514
+ // h = hashKey(dst);
515
+ // hashKey(src);
516
+ // dst = copy(src, dst);
517
+
518
+ // // make sure we don't copy the key
519
+ // expect(hashKey(dst)).not.toEqual(hashKey(src));
520
+ // // make sure we retain the old key
521
+ // expect(hashKey(dst)).toEqual(h);
522
+ // });
523
+
524
+ // it("should retain the previous $$hashKey when copying non-object", () => {
525
+ // const dst = {};
526
+ // const h = hashKey(dst);
527
+
528
+ // copy(null, dst);
529
+ // expect(hashKey(dst)).toEqual(h);
530
+
531
+ // copy(42, dst);
532
+ // expect(hashKey(dst)).toEqual(h);
533
+
534
+ // copy(new Date(), dst);
535
+ // expect(hashKey(dst)).toEqual(h);
536
+ // });
537
+
538
+ // it("should handle circular references", () => {
539
+ // const a = { b: { a: null }, self: null, selfs: [null, null, [null]] };
540
+ // a.b.a = a;
541
+ // a.self = a;
542
+ // a.selfs = [a, a.b, [a]];
543
+
544
+ // let aCopy = copy(a, null);
545
+ // expect(aCopy).toEqual(a);
546
+
547
+ // expect(aCopy).not.toBe(a);
548
+ // expect(aCopy).toBe(aCopy.self);
549
+ // expect(aCopy).toBe(aCopy.selfs[2][0]);
550
+ // expect(aCopy.selfs[2]).not.toBe(a.selfs[2]);
551
+
552
+ // const copyTo = [];
553
+ // aCopy = copy(a, copyTo);
554
+ // expect(aCopy).toBe(copyTo);
555
+ // expect(aCopy).not.toBe(a);
556
+ // expect(aCopy).toBe(aCopy.self);
557
+ // });
558
+
559
+ // it("should deeply copy XML nodes", () => {
560
+ // const anElement = document.createElement("foo");
561
+ // anElement.appendChild(document.createElement("bar"));
562
+ // const theCopy = anElement.cloneNode(true);
563
+ // expect(copy(anElement).outerHTML).toEqual(theCopy.outerHTML);
564
+ // expect(copy(anElement)).not.toBe(anElement);
565
+ // });
566
+
567
+ // it("should not try to call a non-function called `cloneNode`", () => {
568
+ // expect(copy.bind(null, { cloneNode: 100 })).not.toThrow();
569
+ // });
570
+
571
+ // it("should handle objects with multiple references", () => {
572
+ // const b = {};
573
+ // const a = [b, -1, b];
574
+
575
+ // let aCopy = copy(a);
576
+ // expect(aCopy[0]).not.toBe(a[0]);
577
+ // expect(aCopy[0]).toBe(aCopy[2]);
578
+
579
+ // const copyTo = [];
580
+ // aCopy = copy(a, copyTo);
581
+ // expect(aCopy).toBe(copyTo);
582
+ // expect(aCopy[0]).not.toBe(a[0]);
583
+ // expect(aCopy[0]).toBe(aCopy[2]);
584
+ // });
585
+
586
+ // it("should handle date/regex objects with multiple references", () => {
587
+ // const re = /foo/;
588
+ // const d = new Date();
589
+ // const o = { re, re2: re, d, d2: d };
590
+
591
+ // let oCopy = copy(o);
592
+ // expect(oCopy.re).toBe(oCopy.re2);
593
+ // expect(oCopy.d).toBe(oCopy.d2);
594
+
595
+ // oCopy = copy(o, {});
596
+ // expect(oCopy.re).toBe(oCopy.re2);
597
+ // expect(oCopy.d).toBe(oCopy.d2);
598
+ // });
599
+
600
+ // it("should clear destination arrays correctly when source is non-array", () => {
601
+ // expect(copy(null, [1, 2, 3])).toEqual([]);
602
+ // expect(copy(undefined, [1, 2, 3])).toEqual([]);
603
+ // expect(copy({ 0: 1, 1: 2 }, [1, 2, 3])).toEqual([1, 2]);
604
+ // expect(copy(new Date(), [1, 2, 3])).toEqual([]);
605
+ // expect(copy(/a/, [1, 2, 3])).toEqual([]);
606
+ // expect(copy(true, [1, 2, 3])).toEqual([]);
607
+ // });
608
+
609
+ // it("should clear destination objects correctly when source is non-array", () => {
610
+ // expect(copy(null, { 0: 1, 1: 2, 2: 3 })).toEqual({});
611
+ // expect(copy(undefined, { 0: 1, 1: 2, 2: 3 })).toEqual({});
612
+ // expect(copy(new Date(), { 0: 1, 1: 2, 2: 3 })).toEqual({});
613
+ // expect(copy(/a/, { 0: 1, 1: 2, 2: 3 })).toEqual({});
614
+ // expect(copy(true, { 0: 1, 1: 2, 2: 3 })).toEqual({});
615
+ // });
616
+
617
+ // it("should copy objects with no prototype parent", () => {
618
+ // const obj = extend(Object.create(null), {
619
+ // a: 1,
620
+ // b: 2,
621
+ // c: 3,
622
+ // });
623
+ // const dest = copy(obj);
624
+
625
+ // expect(Object.getPrototypeOf(dest)).toBe(null);
626
+ // expect(dest.a).toBe(1);
627
+ // expect(dest.b).toBe(2);
628
+ // expect(dest.c).toBe(3);
629
+ // expect(Object.keys(dest)).toEqual(["a", "b", "c"]);
630
+ // });
631
+
632
+ // it("should copy String() objects", () => {
633
+ // const obj = new String("foo");
634
+ // const dest = copy(obj);
635
+ // expect(dest).not.toBe(obj);
636
+ // expect(isObject(dest)).toBe(true);
637
+ // expect(dest.valueOf()).toBe(obj.valueOf());
638
+ // });
639
+
640
+ // it("should copy Boolean() objects", () => {
641
+ // const obj = new Boolean(true);
642
+ // const dest = copy(obj);
643
+ // expect(dest).not.toBe(obj);
644
+ // expect(isObject(dest)).toBe(true);
645
+ // expect(dest.valueOf()).toBe(obj.valueOf());
646
+ // });
647
+
648
+ // it("should copy Number() objects", () => {
649
+ // const obj = new Number(42);
650
+ // const dest = copy(obj);
651
+ // expect(dest).not.toBe(obj);
652
+ // expect(isObject(dest)).toBe(true);
653
+ // expect(dest.valueOf()).toBe(obj.valueOf());
654
+ // });
655
+
656
+ // it("should copy falsy String/Boolean/Number objects", () => {
657
+ // expect(copy(new String("")).valueOf()).toBe("");
658
+ // expect(copy(new Boolean(false)).valueOf()).toBe(false);
659
+ // expect(copy(new Number(0)).valueOf()).toBe(0);
660
+ // expect(copy(new Number(NaN)).valueOf()).toBeNaN();
661
+ // });
662
+
663
+ // it("should copy source until reaching a given max depth", () => {
664
+ // const source = {
665
+ // a1: 1,
666
+ // b1: { b2: { b3: 1 } },
667
+ // c1: [1, { c2: 1 }],
668
+ // d1: { d2: 1 },
669
+ // };
670
+ // let dest;
671
+
672
+ // dest = copy(source, {}, 1);
673
+ // expect(dest).toEqual({ a1: 1, b1: "...", c1: "...", d1: "..." });
674
+
675
+ // dest = copy(source, {}, 2);
676
+ // expect(dest).toEqual({
677
+ // a1: 1,
678
+ // b1: { b2: "..." },
679
+ // c1: [1, "..."],
680
+ // d1: { d2: 1 },
681
+ // });
682
+
683
+ // dest = copy(source, {}, 3);
684
+ // expect(dest).toEqual({
685
+ // a1: 1,
686
+ // b1: { b2: { b3: 1 } },
687
+ // c1: [1, { c2: 1 }],
688
+ // d1: { d2: 1 },
689
+ // });
690
+
691
+ // dest = copy(source, {}, 4);
692
+ // expect(dest).toEqual({
693
+ // a1: 1,
694
+ // b1: { b2: { b3: 1 } },
695
+ // c1: [1, { c2: 1 }],
696
+ // d1: { d2: 1 },
697
+ // });
698
+ // });
699
+
700
+ // it("should copy source and ignore max depth when maxDepth = $prop", () => {
701
+ // [NaN, null, undefined, true, false, -1, 0].forEach((maxDepth) => {
702
+ // const source = {
703
+ // a1: 1,
704
+ // b1: { b2: { b3: 1 } },
705
+ // c1: [1, { c2: 1 }],
706
+ // d1: { d2: 1 },
707
+ // };
708
+ // const dest = copy(source, {}, maxDepth);
709
+ // expect(dest).toEqual({
710
+ // a1: 1,
711
+ // b1: { b2: { b3: 1 } },
712
+ // c1: [1, { c2: 1 }],
713
+ // d1: { d2: 1 },
714
+ // });
715
+ // });
716
+ // });
717
+ // });
718
+
719
+ describe("extend", () => {
720
+ it("should not copy the private $$hashKey", () => {
721
+ let src;
722
+ let dst;
723
+ src = {};
724
+ dst = {};
725
+ hashKey(src);
726
+ dst = extend(dst, src);
727
+ expect(hashKey(dst)).not.toEqual(hashKey(src));
728
+ });
729
+
730
+ it("should copy the properties of the source object onto the destination object", () => {
731
+ let destination;
732
+ let source;
733
+ destination = {};
734
+ source = { foo: true };
735
+ destination = extend(destination, source);
736
+ expect(isDefined(destination.foo)).toBe(true);
737
+ });
738
+
739
+ it("ISSUE #4751 - should copy the length property of an object source to the destination object", () => {
740
+ let destination;
741
+ let source;
742
+ destination = {};
743
+ source = { radius: 30, length: 0 };
744
+ destination = extend(destination, source);
745
+ expect(isDefined(destination.length)).toBe(true);
746
+ expect(isDefined(destination.radius)).toBe(true);
747
+ });
748
+
749
+ it("should retain the previous $$hashKey", () => {
750
+ let src;
751
+ let dst;
752
+ let h;
753
+ src = {};
754
+ dst = {};
755
+ h = hashKey(dst);
756
+ hashKey(src);
757
+ dst = extend(dst, src);
758
+ // make sure we don't copy the key
759
+ expect(hashKey(dst)).not.toEqual(hashKey(src));
760
+ // make sure we retain the old key
761
+ expect(hashKey(dst)).toEqual(h);
762
+ });
763
+
764
+ it("should work when extending with itself", () => {
765
+ let src;
766
+ let dst;
767
+ let h;
768
+ dst = src = {};
769
+ h = hashKey(dst);
770
+ dst = extend(dst, src);
771
+ // make sure we retain the old key
772
+ expect(hashKey(dst)).toEqual(h);
773
+ });
774
+
775
+ it("should copy dates by reference", () => {
776
+ const src = { date: new Date() };
777
+ const dst = {};
778
+
779
+ extend(dst, src);
780
+
781
+ expect(dst.date).toBe(src.date);
782
+ });
783
+
784
+ it("should copy elements by reference", () => {
785
+ const src = {
786
+ element: document.createElement("div"),
787
+ jqObject: jqLite("<p><span>s1</span><span>s2</span></p>").find("span"),
788
+ };
789
+ const dst = {};
790
+
791
+ extend(dst, src);
792
+
793
+ expect(dst.element).toBe(src.element);
794
+ expect(dst.jqObject).toBe(src.jqObject);
795
+ });
796
+ });
797
+
798
+ describe("merge", () => {
799
+ it("should recursively copy objects into dst from left to right", () => {
800
+ const dst = { foo: { bar: "foobar" } };
801
+ const src1 = { foo: { bazz: "foobazz" } };
802
+ const src2 = { foo: { bozz: "foobozz" } };
803
+ merge(dst, src1, src2);
804
+ expect(dst).toEqual({
805
+ foo: {
806
+ bar: "foobar",
807
+ bazz: "foobazz",
808
+ bozz: "foobozz",
809
+ },
810
+ });
811
+ });
812
+
813
+ it("should replace primitives with objects", () => {
814
+ const dst = { foo: "bloop" };
815
+ const src = { foo: { bar: { baz: "bloop" } } };
816
+ merge(dst, src);
817
+ expect(dst).toEqual({
818
+ foo: {
819
+ bar: {
820
+ baz: "bloop",
821
+ },
822
+ },
823
+ });
824
+ });
825
+
826
+ it("should replace null values in destination with objects", () => {
827
+ const dst = { foo: null };
828
+ const src = { foo: { bar: { baz: "bloop" } } };
829
+ merge(dst, src);
830
+ expect(dst).toEqual({
831
+ foo: {
832
+ bar: {
833
+ baz: "bloop",
834
+ },
835
+ },
836
+ });
837
+ });
838
+
839
+ it("should copy references to functions by value rather than merging", () => {
840
+ function fn() {}
841
+ const dst = { foo: 1 };
842
+ const src = { foo: fn };
843
+ merge(dst, src);
844
+ expect(dst).toEqual({
845
+ foo: fn,
846
+ });
847
+ });
848
+
849
+ it("should create a new array if destination property is a non-object and source property is an array", () => {
850
+ const dst = { foo: NaN };
851
+ const src = { foo: [1, 2, 3] };
852
+ merge(dst, src);
853
+ expect(dst).toEqual({
854
+ foo: [1, 2, 3],
855
+ });
856
+ expect(dst.foo).not.toBe(src.foo);
857
+ });
858
+
859
+ it("should copy dates by value", () => {
860
+ const src = { date: new Date() };
861
+ const dst = {};
862
+
863
+ merge(dst, src);
864
+
865
+ expect(dst.date).not.toBe(src.date);
866
+ expect(isDate(dst.date)).toBeTruthy();
867
+ expect(dst.date.valueOf()).toEqual(src.date.valueOf());
868
+ });
869
+
870
+ it("should copy regexp by value", () => {
871
+ const src = { regexp: /blah/ };
872
+ const dst = {};
873
+
874
+ merge(dst, src);
875
+
876
+ expect(dst.regexp).not.toBe(src.regexp);
877
+ expect(isRegExp(dst.regexp)).toBe(true);
878
+ expect(dst.regexp.toString()).toBe(src.regexp.toString());
879
+ });
880
+
881
+ it("should not merge the __proto__ property", () => {
882
+ const src = JSON.parse('{ "__proto__": { "xxx": "polluted" } }');
883
+ const dst = {};
884
+
885
+ merge(dst, src);
886
+
887
+ if (typeof dst.__proto__ !== "undefined") {
888
+ // eslint-disable-line
889
+ // Should not overwrite the __proto__ property or pollute the Object prototype
890
+ expect(dst.__proto__).toBe(Object.prototype); // eslint-disable-line
891
+ }
892
+ expect({}.xxx).toBeUndefined();
893
+ });
894
+ });
895
+
896
+ describe("shallow copy", () => {
897
+ it("should make a copy", () => {
898
+ const original = { key: {} };
899
+ const copy = shallowCopy(original);
900
+ expect(copy).toEqual(original);
901
+ expect(copy.key).toBe(original.key);
902
+ });
903
+
904
+ it('should omit "$$"-prefixed properties', () => {
905
+ const original = { $$some: true, $$: true };
906
+ const clone = {};
907
+
908
+ expect(shallowCopy(original, clone)).toBe(clone);
909
+ expect(clone.$$some).toBeUndefined();
910
+ expect(clone.$$).toBeUndefined();
911
+ });
912
+
913
+ it('should copy "$"-prefixed properties from copy', () => {
914
+ const original = { $some: true };
915
+ const clone = {};
916
+
917
+ expect(shallowCopy(original, clone)).toBe(clone);
918
+ expect(clone.$some).toBe(original.$some);
919
+ });
920
+
921
+ it("should handle arrays", () => {
922
+ const original = [{}, 1];
923
+ const clone = [];
924
+
925
+ const aCopy = shallowCopy(original);
926
+ expect(aCopy).not.toBe(original);
927
+ expect(aCopy).toEqual(original);
928
+ expect(aCopy[0]).toBe(original[0]);
929
+
930
+ expect(shallowCopy(original, clone)).toBe(clone);
931
+ expect(clone).toEqual(original);
932
+ });
933
+
934
+ it("should handle primitives", () => {
935
+ expect(shallowCopy("test")).toBe("test");
936
+ expect(shallowCopy(3)).toBe(3);
937
+ expect(shallowCopy(true)).toBe(true);
938
+ });
939
+ });
940
+
941
+ describe("elementHTML", () => {
942
+ it("should dump element", () => {
943
+ expect(
944
+ startingTag('<div attr="123">something<span></span></div>'),
945
+ ).toEqual('<div attr="123">');
946
+ });
947
+ });
948
+
949
+ describe("equals", () => {
950
+ it("should return true if same object", () => {
951
+ const o = {};
952
+ expect(equals(o, o)).toEqual(true);
953
+ expect(equals(o, {})).toEqual(true);
954
+ expect(equals(1, "1")).toEqual(false);
955
+ expect(equals(1, "2")).toEqual(false);
956
+ });
957
+
958
+ it("should recurse into object", () => {
959
+ expect(equals({}, {})).toEqual(true);
960
+ expect(equals({ name: "misko" }, { name: "misko" })).toEqual(true);
961
+ expect(equals({ name: "misko", age: 1 }, { name: "misko" })).toEqual(
962
+ false,
963
+ );
964
+ expect(equals({ name: "misko" }, { name: "misko", age: 1 })).toEqual(
965
+ false,
966
+ );
967
+ expect(equals({ name: "misko" }, { name: "adam" })).toEqual(false);
968
+ expect(equals(["misko"], ["misko"])).toEqual(true);
969
+ expect(equals(["misko"], ["adam"])).toEqual(false);
970
+ expect(equals(["misko"], ["misko", "adam"])).toEqual(false);
971
+ });
972
+
973
+ it("should ignore undefined member variables during comparison", () => {
974
+ const obj1 = { name: "misko" };
975
+ const obj2 = { name: "misko", undefinedvar: undefined };
976
+
977
+ expect(equals(obj1, obj2)).toBe(true);
978
+ expect(equals(obj2, obj1)).toBe(true);
979
+ });
980
+
981
+ it("should ignore $ member variables", () => {
982
+ expect(
983
+ equals({ name: "misko", $id: 1 }, { name: "misko", $id: 2 }),
984
+ ).toEqual(true);
985
+ expect(equals({ name: "misko" }, { name: "misko", $id: 2 })).toEqual(
986
+ true,
987
+ );
988
+ expect(equals({ name: "misko", $id: 1 }, { name: "misko" })).toEqual(
989
+ true,
990
+ );
991
+ });
992
+
993
+ it("should ignore functions", () => {
994
+ expect(equals({ func() {} }, { bar() {} })).toEqual(true);
995
+ });
996
+
997
+ it("should work well with nulls", () => {
998
+ expect(equals(null, "123")).toBe(false);
999
+ expect(equals("123", null)).toBe(false);
1000
+
1001
+ const obj = { foo: "bar" };
1002
+ expect(equals(null, obj)).toBe(false);
1003
+ expect(equals(obj, null)).toBe(false);
1004
+
1005
+ expect(equals(null, null)).toBe(true);
1006
+ });
1007
+
1008
+ it("should work well with undefined", () => {
1009
+ expect(equals(undefined, "123")).toBe(false);
1010
+ expect(equals("123", undefined)).toBe(false);
1011
+
1012
+ const obj = { foo: "bar" };
1013
+ expect(equals(undefined, obj)).toBe(false);
1014
+ expect(equals(obj, undefined)).toBe(false);
1015
+
1016
+ expect(equals(undefined, undefined)).toBe(true);
1017
+ });
1018
+
1019
+ it("should treat two NaNs as equal", () => {
1020
+ expect(equals(NaN, NaN)).toBe(true);
1021
+ });
1022
+
1023
+ it("should compare Scope instances only by identity", () => {
1024
+ const scope1 = $rootScope.$new();
1025
+ const scope2 = $rootScope.$new();
1026
+
1027
+ expect(equals(scope1, scope1)).toBe(true);
1028
+ expect(equals(scope1, scope2)).toBe(false);
1029
+ expect(equals($rootScope, scope1)).toBe(false);
1030
+ expect(equals(undefined, scope1)).toBe(false);
1031
+ });
1032
+
1033
+ it("should compare Window instances only by identity", () => {
1034
+ expect(equals(window, window)).toBe(true);
1035
+ expect(equals(window, window.document)).toBe(false);
1036
+ expect(equals(window, undefined)).toBe(false);
1037
+ });
1038
+
1039
+ it("should compare dates", () => {
1040
+ expect(equals(new Date(0), new Date(0))).toBe(true);
1041
+ expect(equals(new Date(0), new Date(1))).toBe(false);
1042
+ expect(equals(new Date(0), 0)).toBe(false);
1043
+ expect(equals(0, new Date(0))).toBe(false);
1044
+
1045
+ expect(equals(new Date(undefined), new Date(undefined))).toBe(true);
1046
+ expect(equals(new Date(undefined), new Date(0))).toBe(false);
1047
+ expect(equals(new Date(undefined), new Date(null))).toBe(false);
1048
+ expect(equals(new Date(undefined), new Date("wrong"))).toBe(true);
1049
+ expect(equals(new Date(), /abc/)).toBe(false);
1050
+ });
1051
+
1052
+ it("should correctly test for keys that are present on Object.prototype", () => {
1053
+ expect(equals({}, { hasOwnProperty: 1 })).toBe(false);
1054
+ expect(equals({}, { toString: null })).toBe(false);
1055
+ });
1056
+
1057
+ it("should compare regular expressions", () => {
1058
+ expect(equals(/abc/, /abc/)).toBe(true);
1059
+ expect(equals(/abc/i, new RegExp("abc", "i"))).toBe(true);
1060
+ expect(equals(new RegExp("abc", "i"), new RegExp("abc", "i"))).toBe(true);
1061
+ expect(equals(new RegExp("abc", "i"), new RegExp("abc"))).toBe(false);
1062
+ expect(equals(/abc/i, /abc/)).toBe(false);
1063
+ expect(equals(/abc/, /def/)).toBe(false);
1064
+ expect(equals(/^abc/, /abc/)).toBe(false);
1065
+ expect(equals(/^abc/, "/^abc/")).toBe(false);
1066
+ expect(equals(/abc/, new Date())).toBe(false);
1067
+ });
1068
+
1069
+ it("should return false when comparing an object and an array", () => {
1070
+ expect(equals({}, [])).toBe(false);
1071
+ expect(equals([], {})).toBe(false);
1072
+ });
1073
+
1074
+ it("should return false when comparing an object and a RegExp", () => {
1075
+ expect(equals({}, /abc/)).toBe(false);
1076
+ expect(equals({}, new RegExp("abc", "i"))).toBe(false);
1077
+ });
1078
+
1079
+ it("should return false when comparing an object and a Date", () => {
1080
+ expect(equals({}, new Date())).toBe(false);
1081
+ });
1082
+
1083
+ it("should safely compare objects with no prototype parent", () => {
1084
+ const o1 = extend(Object.create(null), {
1085
+ a: 1,
1086
+ b: 2,
1087
+ c: 3,
1088
+ });
1089
+ const o2 = extend(Object.create(null), {
1090
+ a: 1,
1091
+ b: 2,
1092
+ c: 3,
1093
+ });
1094
+ expect(equals(o1, o2)).toBe(true);
1095
+ o2.c = 2;
1096
+ expect(equals(o1, o2)).toBe(false);
1097
+ });
1098
+
1099
+ it("should safely compare objects which shadow Object.prototype.hasOwnProperty", () => {
1100
+ const o1 = {
1101
+ hasOwnProperty: true,
1102
+ a: 1,
1103
+ b: 2,
1104
+ c: 3,
1105
+ };
1106
+ const o2 = {
1107
+ hasOwnProperty: true,
1108
+ a: 1,
1109
+ b: 2,
1110
+ c: 3,
1111
+ };
1112
+ expect(equals(o1, o2)).toBe(true);
1113
+ o1.hasOwnProperty = function () {};
1114
+ expect(equals(o1, o2)).toBe(false);
1115
+ });
1116
+ });
1117
+
1118
+ describe("parseKeyValue", () => {
1119
+ it("should parse a string into key-value pairs", () => {
1120
+ expect(parseKeyValue("")).toEqual({});
1121
+ expect(parseKeyValue("simple=pair")).toEqual({ simple: "pair" });
1122
+ expect(parseKeyValue("first=1&second=2")).toEqual({
1123
+ first: "1",
1124
+ second: "2",
1125
+ });
1126
+ expect(parseKeyValue("escaped%20key=escaped%20value")).toEqual({
1127
+ "escaped key": "escaped value",
1128
+ });
1129
+ expect(parseKeyValue("emptyKey=")).toEqual({ emptyKey: "" });
1130
+ expect(parseKeyValue("flag1&key=value&flag2")).toEqual({
1131
+ flag1: true,
1132
+ key: "value",
1133
+ flag2: true,
1134
+ });
1135
+ });
1136
+ it("should ignore key values that are not valid URI components", () => {
1137
+ expect(() => {
1138
+ parseKeyValue("%");
1139
+ }).not.toThrow();
1140
+ expect(parseKeyValue("%")).toEqual({});
1141
+ expect(parseKeyValue("invalid=%")).toEqual({ invalid: undefined });
1142
+ expect(parseKeyValue("invalid=%&valid=good")).toEqual({
1143
+ invalid: undefined,
1144
+ valid: "good",
1145
+ });
1146
+ });
1147
+ it("should parse a string into key-value pairs with duplicates grouped in an array", () => {
1148
+ expect(parseKeyValue("")).toEqual({});
1149
+ expect(parseKeyValue("duplicate=pair")).toEqual({ duplicate: "pair" });
1150
+ expect(parseKeyValue("first=1&first=2")).toEqual({ first: ["1", "2"] });
1151
+ expect(
1152
+ parseKeyValue(
1153
+ "escaped%20key=escaped%20value&&escaped%20key=escaped%20value2",
1154
+ ),
1155
+ ).toEqual({ "escaped key": ["escaped value", "escaped value2"] });
1156
+ expect(parseKeyValue("flag1&key=value&flag1")).toEqual({
1157
+ flag1: [true, true],
1158
+ key: "value",
1159
+ });
1160
+ expect(parseKeyValue("flag1&flag1=value&flag1=value2&flag1")).toEqual({
1161
+ flag1: [true, "value", "value2", true],
1162
+ });
1163
+ });
1164
+
1165
+ it("should ignore properties higher in the prototype chain", () => {
1166
+ expect(parseKeyValue("toString=123")).toEqual({
1167
+ toString: "123",
1168
+ });
1169
+ });
1170
+
1171
+ it("should ignore badly escaped = characters", () => {
1172
+ expect(parseKeyValue("test=a=b")).toEqual({
1173
+ test: "a=b",
1174
+ });
1175
+ });
1176
+ });
1177
+
1178
+ describe("toKeyValue", () => {
1179
+ it("should serialize key-value pairs into string", () => {
1180
+ expect(toKeyValue({})).toEqual("");
1181
+ expect(toKeyValue({ simple: "pair" })).toEqual("simple=pair");
1182
+ expect(toKeyValue({ first: "1", second: "2" })).toEqual(
1183
+ "first=1&second=2",
1184
+ );
1185
+ expect(toKeyValue({ "escaped key": "escaped value" })).toEqual(
1186
+ "escaped%20key=escaped%20value",
1187
+ );
1188
+ expect(toKeyValue({ emptyKey: "" })).toEqual("emptyKey=");
1189
+ });
1190
+
1191
+ it("should serialize true values into flags", () => {
1192
+ expect(toKeyValue({ flag1: true, key: "value", flag2: true })).toEqual(
1193
+ "flag1&key=value&flag2",
1194
+ );
1195
+ });
1196
+
1197
+ it("should serialize duplicates into duplicate param strings", () => {
1198
+ expect(toKeyValue({ key: [323, "value", true] })).toEqual(
1199
+ "key=323&key=value&key",
1200
+ );
1201
+ expect(toKeyValue({ key: [323, "value", true, 1234] })).toEqual(
1202
+ "key=323&key=value&key&key=1234",
1203
+ );
1204
+ });
1205
+ });
1206
+
1207
+ describe("isArray", () => {
1208
+ it("should return true if passed an `Array`", () => {
1209
+ expect(isArray([])).toBe(true);
1210
+ });
1211
+
1212
+ it("should return true if passed an `Array` from a different window context", () => {
1213
+ const iframe = document.createElement("iframe");
1214
+ document.body.appendChild(iframe); // No `contentWindow` if not attached to the DOM.
1215
+ const arr = new iframe.contentWindow.Array();
1216
+ document.body.removeChild(iframe); // Clean up.
1217
+
1218
+ expect(arr instanceof Array).toBe(false);
1219
+ expect(isArray(arr)).toBe(true);
1220
+ });
1221
+
1222
+ it("should return true if passed an object prototypically inherited from `Array`", () => {
1223
+ function FooArray() {}
1224
+ FooArray.prototype = [];
1225
+
1226
+ expect(isArray(new FooArray())).toBe(true);
1227
+ });
1228
+
1229
+ it("should return false if passed non-array objects", () => {
1230
+ expect(isArray(document.body.childNodes)).toBe(false);
1231
+ expect(isArray({ length: 0 })).toBe(false);
1232
+ expect(isArray({ length: 2, 0: "one", 1: "two" })).toBe(false);
1233
+ });
1234
+ });
1235
+
1236
+ describe("isArrayLike", () => {
1237
+ it("should return false if passed a number", () => {
1238
+ expect(isArrayLike(10)).toBe(false);
1239
+ });
1240
+
1241
+ it("should return true if passed an array", () => {
1242
+ expect(isArrayLike([1, 2, 3, 4])).toBe(true);
1243
+ });
1244
+
1245
+ it("should return true if passed an object", () => {
1246
+ expect(isArrayLike({ 0: "test", 1: "bob", 2: "tree", length: 3 })).toBe(
1247
+ true,
1248
+ );
1249
+ });
1250
+
1251
+ it("should return true if passed arguments object", () => {
1252
+ function test(a, b, c) {
1253
+ expect(isArrayLike(arguments)).toBe(true);
1254
+ }
1255
+ test(1, 2, 3);
1256
+ });
1257
+
1258
+ it("should return true if passed a nodelist", () => {
1259
+ const nodes1 = document.body.childNodes;
1260
+ expect(isArrayLike(nodes1)).toBe(true);
1261
+
1262
+ const nodes2 = document.getElementsByTagName("nonExistingTagName");
1263
+ expect(isArrayLike(nodes2)).toBe(true);
1264
+ });
1265
+
1266
+ it("should return false for objects with `length` but no matching indexable items", () => {
1267
+ const obj1 = {
1268
+ a: "a",
1269
+ b: "b",
1270
+ length: 10,
1271
+ };
1272
+ expect(isArrayLike(obj1)).toBe(false);
1273
+
1274
+ const obj2 = {
1275
+ length: 0,
1276
+ };
1277
+ expect(isArrayLike(obj2)).toBe(false);
1278
+ });
1279
+
1280
+ it("should return true for empty instances of an Array subclass", () => {
1281
+ function ArrayLike() {}
1282
+ ArrayLike.prototype = Array.prototype;
1283
+
1284
+ const arrLike = new ArrayLike();
1285
+ expect(arrLike.length).toBe(0);
1286
+ expect(isArrayLike(arrLike)).toBe(true);
1287
+
1288
+ arrLike.push(1, 2, 3);
1289
+ expect(arrLike.length).toBe(3);
1290
+ expect(isArrayLike(arrLike)).toBe(true);
1291
+ });
1292
+ });
1293
+
1294
+ describe("forEach", () => {
1295
+ it("should iterate over *own* object properties", () => {
1296
+ function MyObj() {
1297
+ this.bar = "barVal";
1298
+ this.baz = "bazVal";
1299
+ }
1300
+ MyObj.prototype.foo = "fooVal";
1301
+
1302
+ const obj = new MyObj();
1303
+ const log = [];
1304
+
1305
+ forEach(obj, (value, key) => {
1306
+ log.push(`${key}:${value}`);
1307
+ });
1308
+
1309
+ expect(log).toEqual(["bar:barVal", "baz:bazVal"]);
1310
+ });
1311
+
1312
+ it("should not break if obj is an array we override hasOwnProperty", () => {
1313
+ const obj = [];
1314
+ obj[0] = 1;
1315
+ obj[1] = 2;
1316
+ obj.hasOwnProperty = null;
1317
+ const log = [];
1318
+ forEach(obj, (value, key) => {
1319
+ log.push(`${key}:${value}`);
1320
+ });
1321
+ expect(log).toEqual(["0:1", "1:2"]);
1322
+ });
1323
+
1324
+ it("should handle JQLite and jQuery objects like arrays", () => {
1325
+ let jqObject = jqLite("<p><span>s1</span><span>s2</span></p>").find(
1326
+ "span",
1327
+ );
1328
+ let log = [];
1329
+
1330
+ forEach(jqObject, (value, key) => {
1331
+ log.push(`${key}:${value.innerHTML}`);
1332
+ });
1333
+ expect(log).toEqual(["0:s1", "1:s2"]);
1334
+
1335
+ log = [];
1336
+ jqObject = jqLite("<pane></pane>");
1337
+ forEach(jqObject.children(), (value, key) => {
1338
+ log.push(`${key}:${value.innerHTML}`);
1339
+ });
1340
+ expect(log).toEqual([]);
1341
+ });
1342
+
1343
+ it("should handle NodeList objects like arrays", () => {
1344
+ const nodeList = jqLite(
1345
+ "<p><span>a</span><span>b</span><span>c</span></p>",
1346
+ )[0].childNodes;
1347
+ const log = [];
1348
+
1349
+ forEach(nodeList, (value, key) => {
1350
+ log.push(`${key}:${value.innerHTML}`);
1351
+ });
1352
+ expect(log).toEqual(["0:a", "1:b", "2:c"]);
1353
+ });
1354
+
1355
+ it("should handle HTMLCollection objects like arrays", () => {
1356
+ document.getElementById("dummy").innerHTML =
1357
+ "<p>" +
1358
+ "<a name='x'>a</a>" +
1359
+ "<a name='y'>b</a>" +
1360
+ "<a name='x'>c</a>" +
1361
+ "</p>";
1362
+
1363
+ const htmlCollection = document.getElementsByName("x");
1364
+ const log = [];
1365
+
1366
+ forEach(htmlCollection, (value, key) => {
1367
+ log.push(`${key}:${value.innerHTML}`);
1368
+ });
1369
+ expect(log).toEqual(["0:a", "1:c"]);
1370
+ });
1371
+
1372
+ it("should handle arguments objects like arrays", () => {
1373
+ let args;
1374
+ const log = [];
1375
+
1376
+ (function () {
1377
+ args = arguments;
1378
+ })("a", "b", "c");
1379
+
1380
+ forEach(args, (value, key) => {
1381
+ log.push(`${key}:${value}`);
1382
+ });
1383
+ expect(log).toEqual(["0:a", "1:b", "2:c"]);
1384
+ });
1385
+
1386
+ it("should handle string values like arrays", () => {
1387
+ const log = [];
1388
+
1389
+ forEach("bar", (value, key) => {
1390
+ log.push(`${key}:${value}`);
1391
+ });
1392
+ expect(log).toEqual(["0:b", "1:a", "2:r"]);
1393
+ });
1394
+
1395
+ it("should handle objects with length property as objects", () => {
1396
+ const obj = {
1397
+ foo: "bar",
1398
+ length: 2,
1399
+ };
1400
+ const log = [];
1401
+
1402
+ forEach(obj, (value, key) => {
1403
+ log.push(`${key}:${value}`);
1404
+ });
1405
+ expect(log).toEqual(["foo:bar", "length:2"]);
1406
+ });
1407
+
1408
+ it("should handle objects of custom types with length property as objects", () => {
1409
+ function CustomType() {
1410
+ this.length = 2;
1411
+ this.foo = "bar";
1412
+ }
1413
+
1414
+ const obj = new CustomType();
1415
+ const log = [];
1416
+
1417
+ forEach(obj, (value, key) => {
1418
+ log.push(`${key}:${value}`);
1419
+ });
1420
+ expect(log).toEqual(["length:2", "foo:bar"]);
1421
+ });
1422
+
1423
+ it("should not invoke the iterator for indexed properties which are not present in the collection", () => {
1424
+ const log = [];
1425
+ const collection = [];
1426
+ collection[5] = "SPARSE";
1427
+ forEach(collection, (item, index) => {
1428
+ log.push(item + index);
1429
+ });
1430
+ expect(log.length).toBe(1);
1431
+ expect(log[0]).toBe("SPARSE5");
1432
+ });
1433
+
1434
+ it("should safely iterate through objects with no prototype parent", () => {
1435
+ const obj = extend(Object.create(null), {
1436
+ a: 1,
1437
+ b: 2,
1438
+ c: 3,
1439
+ });
1440
+ const log = [];
1441
+ const self = {};
1442
+ forEach(
1443
+ obj,
1444
+ function (val, key, collection) {
1445
+ expect(this).toBe(self);
1446
+ expect(collection).toBe(obj);
1447
+ log.push(`${key}=${val}`);
1448
+ },
1449
+ self,
1450
+ );
1451
+ expect(log.length).toBe(3);
1452
+ expect(log).toEqual(["a=1", "b=2", "c=3"]);
1453
+ });
1454
+
1455
+ it("should safely iterate through objects which shadow Object.prototype.hasOwnProperty", () => {
1456
+ const obj = {
1457
+ hasOwnProperty: true,
1458
+ a: 1,
1459
+ b: 2,
1460
+ c: 3,
1461
+ };
1462
+ const log = [];
1463
+ const self = {};
1464
+ forEach(
1465
+ obj,
1466
+ function (val, key, collection) {
1467
+ expect(this).toBe(self);
1468
+ expect(collection).toBe(obj);
1469
+ log.push(`${key}=${val}`);
1470
+ },
1471
+ self,
1472
+ );
1473
+ expect(log.length).toBe(4);
1474
+ expect(log).toEqual(["hasOwnProperty=true", "a=1", "b=2", "c=3"]);
1475
+ });
1476
+
1477
+ describe("ES spec api compliance", () => {
1478
+ function testForEachSpec(expectedSize, collection) {
1479
+ const that = {};
1480
+
1481
+ forEach(
1482
+ collection,
1483
+ function (value, key, collectionArg) {
1484
+ expect(collectionArg).toBe(collection);
1485
+ expect(collectionArg[key]).toBe(value);
1486
+
1487
+ expect(this).toBe(that);
1488
+
1489
+ expectedSize--;
1490
+ },
1491
+ that,
1492
+ );
1493
+
1494
+ expect(expectedSize).toBe(0);
1495
+ }
1496
+
1497
+ it("should follow the ES spec when called with array", () => {
1498
+ testForEachSpec(2, [1, 2]);
1499
+ });
1500
+
1501
+ it("should follow the ES spec when called with arguments", () => {
1502
+ testForEachSpec(
1503
+ 2,
1504
+ (function () {
1505
+ return arguments;
1506
+ })(1, 2),
1507
+ );
1508
+ });
1509
+
1510
+ it("should follow the ES spec when called with string", () => {
1511
+ testForEachSpec(2, "12");
1512
+ });
1513
+
1514
+ it("should follow the ES spec when called with jQuery/jqLite", () => {
1515
+ testForEachSpec(2, jqLite("<span>a</span><span>b</span>"));
1516
+ });
1517
+
1518
+ it("should follow the ES spec when called with childNodes NodeList", () => {
1519
+ testForEachSpec(
1520
+ 2,
1521
+ jqLite("<p><span>a</span><span>b</span></p>")[0].childNodes,
1522
+ );
1523
+ });
1524
+
1525
+ it("should follow the ES spec when called with getElementsByTagName HTMLCollection", () => {
1526
+ testForEachSpec(
1527
+ 2,
1528
+ jqLite("<p><span>a</span><span>b</span></p>")[0].getElementsByTagName(
1529
+ "*",
1530
+ ),
1531
+ );
1532
+ });
1533
+
1534
+ it("should follow the ES spec when called with querySelectorAll HTMLCollection", () => {
1535
+ testForEachSpec(
1536
+ 2,
1537
+ jqLite("<p><span>a</span><span>b</span></p>")[0].querySelectorAll(
1538
+ "*",
1539
+ ),
1540
+ );
1541
+ });
1542
+
1543
+ it("should follow the ES spec when called with JSON", () => {
1544
+ testForEachSpec(2, { a: 1, b: 2 });
1545
+ });
1546
+
1547
+ it("should follow the ES spec when called with function", () => {
1548
+ function f() {}
1549
+ f.a = 1;
1550
+ f.b = 2;
1551
+ testForEachSpec(2, f);
1552
+ });
1553
+ });
1554
+ });
1555
+
1556
+ describe("encodeUriSegment", () => {
1557
+ it("should correctly encode uri segment and not encode chars defined as pchar set in rfc3986", () => {
1558
+ // don't encode alphanum
1559
+ expect(encodeUriSegment("asdf1234asdf")).toEqual("asdf1234asdf");
1560
+
1561
+ // don't encode unreserved'
1562
+ expect(encodeUriSegment("-_.!~*'(); -_.!~*'();")).toEqual(
1563
+ "-_.!~*'();%20-_.!~*'();",
1564
+ );
1565
+
1566
+ // don't encode the rest of pchar'
1567
+ expect(encodeUriSegment(":@&=+$, :@&=+$,")).toEqual(":@&=+$,%20:@&=+$,");
1568
+
1569
+ // encode '/' and ' ''
1570
+ expect(encodeUriSegment("/; /;")).toEqual("%2F;%20%2F;");
1571
+ });
1572
+ });
1573
+
1574
+ describe("encodeUriQuery", () => {
1575
+ it("should correctly encode uri query and not encode chars defined as pchar set in rfc3986", () => {
1576
+ // don't encode alphanum
1577
+ expect(encodeUriQuery("asdf1234asdf")).toEqual("asdf1234asdf");
1578
+
1579
+ // don't encode unreserved
1580
+ expect(encodeUriQuery("-_.!~*'() -_.!~*'()")).toEqual(
1581
+ "-_.!~*'()+-_.!~*'()",
1582
+ );
1583
+
1584
+ // don't encode the rest of pchar
1585
+ expect(encodeUriQuery(":@$, :@$,")).toEqual(":@$,+:@$,");
1586
+
1587
+ // encode '&', ';', '=', '+', and '#'
1588
+ expect(encodeUriQuery("&;=+# &;=+#")).toEqual(
1589
+ "%26;%3D%2B%23+%26;%3D%2B%23",
1590
+ );
1591
+
1592
+ // encode ' ' as '+'
1593
+ expect(encodeUriQuery(" ")).toEqual("++");
1594
+
1595
+ // encode ' ' as '%20' when a flag is used
1596
+ expect(encodeUriQuery(" ", true)).toEqual("%20%20");
1597
+
1598
+ // do not encode `null` as '+' when flag is used
1599
+ expect(encodeUriQuery("null", true)).toEqual("null");
1600
+
1601
+ // do not encode `null` with no flag
1602
+ expect(encodeUriQuery("null")).toEqual("null");
1603
+ });
1604
+ });
1605
+
1606
+ describe("angularInit", () => {
1607
+ let bootstrapSpy;
1608
+ let element;
1609
+
1610
+ beforeEach(() => {
1611
+ element = {
1612
+ hasAttribute(name) {
1613
+ return !!element[name];
1614
+ },
1615
+
1616
+ querySelector(arg) {
1617
+ return element.querySelector[arg] || null;
1618
+ },
1619
+
1620
+ getAttribute(name) {
1621
+ return element[name];
1622
+ },
1623
+ };
1624
+ bootstrapSpy = spyOn(window.angular, "bootstrap").and.callThrough();
1625
+ });
1626
+
1627
+ it("should do nothing when not found", () => {
1628
+ angularInit(element);
1629
+ expect(bootstrapSpy).not.toHaveBeenCalled();
1630
+ });
1631
+
1632
+ it("should look for ngApp directive as attr", () => {
1633
+ window.angular.module("ABC", []);
1634
+ const appElement = jqLite('<div ng-app="ABC"></div>')[0];
1635
+
1636
+ angularInit(appElement);
1637
+ expect(bootstrapSpy).toHaveBeenCalled();
1638
+ });
1639
+
1640
+ it("should look for ngApp directive using querySelectorAll", () => {
1641
+ window.angular.module("ABC", []);
1642
+ const appElement = jqLite('<div x-ng-app="ABC"></div>')[0];
1643
+ element.querySelector["[x-ng-app]"] = appElement;
1644
+ angularInit(element);
1645
+ expect(bootstrapSpy).toHaveBeenCalled();
1646
+ });
1647
+
1648
+ it("should bootstrap anonymously", () => {
1649
+ const appElement = jqLite("<div x-ng-app></div>")[0];
1650
+ element.querySelector["[x-ng-app]"] = appElement;
1651
+ angularInit(element);
1652
+ expect(bootstrapSpy).toHaveBeenCalled();
1653
+ });
1654
+
1655
+ it("should bootstrap if the annotation is on the root element", () => {
1656
+ const appElement = jqLite('<div ng-app=""></div>')[0];
1657
+ angularInit(appElement);
1658
+ expect(bootstrapSpy).toHaveBeenCalled();
1659
+ });
1660
+
1661
+ it("should complain if app module cannot be found", () => {
1662
+ const appElement = jqLite('<div ng-app="doesntexist"></div>')[0];
1663
+ expect(() => {
1664
+ angularInit(appElement);
1665
+ }).toThrowError(/modulerr/);
1666
+ });
1667
+
1668
+ it("should complain if an element has already been bootstrapped", () => {
1669
+ const element = jqLite("<div>bootstrap me!</div>");
1670
+ angular.bootstrap(element);
1671
+
1672
+ expect(() => {
1673
+ angular.bootstrap(element);
1674
+ }).toThrowError(/btstrpd/);
1675
+
1676
+ dealoc(element);
1677
+ });
1678
+
1679
+ it("should complain if manually bootstrapping a document whose <html> element has already been bootstrapped", () => {
1680
+ angular.bootstrap(document.getElementsByTagName("html")[0]);
1681
+ expect(() => {
1682
+ angular.bootstrap(document);
1683
+ }).toThrowError(/btstrpd/);
1684
+
1685
+ dealoc(document);
1686
+ });
1687
+
1688
+ it("should bootstrap in strict mode when ng-strict-di attribute is specified", () => {
1689
+ const appElement = jqLite('<div ng-app="" ng-strict-di></div>');
1690
+ angularInit(jqLite("<div></div>").append(appElement[0])[0]);
1691
+ expect(bootstrapSpy).toHaveBeenCalled();
1692
+ expect(bootstrapSpy.calls.mostRecent().args[2].strictDi).toBe(true);
1693
+
1694
+ const injector = appElement.injector();
1695
+ function testFactory($rootScope) {}
1696
+ expect(() => {
1697
+ injector.instantiate(testFactory);
1698
+ }).toThrowError(/strictdi/);
1699
+
1700
+ dealoc(appElement);
1701
+ });
1702
+ });
1703
+
1704
+ describe("AngularJS service", () => {
1705
+ it("should override services", () => {
1706
+ injector = createInjector([
1707
+ function ($provide) {
1708
+ $provide.value("fake", "old");
1709
+ $provide.value("fake", "new");
1710
+ },
1711
+ ]);
1712
+ expect(injector.get("fake")).toEqual("new");
1713
+ });
1714
+
1715
+ it("should inject dependencies specified by $inject and ignore function argument name", () => {
1716
+ expect(
1717
+ angular
1718
+ .injector([
1719
+ function ($provide) {
1720
+ $provide.factory("svc1", () => "svc1");
1721
+ $provide.factory("svc2", [
1722
+ "svc1",
1723
+ function (s) {
1724
+ return `svc2-${s}`;
1725
+ },
1726
+ ]);
1727
+ },
1728
+ ])
1729
+ .get("svc2"),
1730
+ ).toEqual("svc2-svc1");
1731
+ });
1732
+ });
1733
+
1734
+ describe("isDate", () => {
1735
+ it("should return true for Date object", () => {
1736
+ expect(isDate(new Date())).toBe(true);
1737
+ });
1738
+
1739
+ it("should return false for non Date objects", () => {
1740
+ expect(isDate([])).toBe(false);
1741
+ expect(isDate("")).toBe(false);
1742
+ expect(isDate(23)).toBe(false);
1743
+ expect(isDate({})).toBe(false);
1744
+ });
1745
+ });
1746
+
1747
+ describe("isError", () => {
1748
+ function testErrorFromDifferentContext(createError) {
1749
+ const iframe = document.createElement("iframe");
1750
+ document.getElementById("dummy").appendChild(iframe);
1751
+ try {
1752
+ const error = createError(iframe.contentWindow);
1753
+ expect(isError(error)).toBe(true);
1754
+ } finally {
1755
+ iframe.parentElement.removeChild(iframe);
1756
+ }
1757
+ }
1758
+
1759
+ it("should not assume objects are errors", () => {
1760
+ const fakeError = { message: "A fake error", stack: "no stack here" };
1761
+ expect(isError(fakeError)).toBe(false);
1762
+ });
1763
+
1764
+ it("should detect simple error instances", () => {
1765
+ expect(isError(new Error())).toBe(true);
1766
+ });
1767
+
1768
+ it("should detect errors from another context", () => {
1769
+ testErrorFromDifferentContext((win) => new win.Error());
1770
+ });
1771
+
1772
+ it("should detect DOMException errors from another context", () => {
1773
+ testErrorFromDifferentContext((win) => {
1774
+ try {
1775
+ win.document.querySelectorAll("");
1776
+ } catch (e) {
1777
+ return e;
1778
+ }
1779
+ });
1780
+ });
1781
+ });
1782
+
1783
+ describe("isRegExp", () => {
1784
+ it("should return true for RegExp object", () => {
1785
+ expect(isRegExp(/^foobar$/)).toBe(true);
1786
+ expect(isRegExp(new RegExp("^foobar$/"))).toBe(true);
1787
+ });
1788
+
1789
+ it("should return false for non RegExp objects", () => {
1790
+ expect(isRegExp([])).toBe(false);
1791
+ expect(isRegExp("")).toBe(false);
1792
+ expect(isRegExp(23)).toBe(false);
1793
+ expect(isRegExp({})).toBe(false);
1794
+ expect(isRegExp(new Date())).toBe(false);
1795
+ });
1796
+ });
1797
+
1798
+ describe("isWindow", () => {
1799
+ it("should return true for the Window object", () => {
1800
+ expect(isWindow(window)).toBe(true);
1801
+ });
1802
+
1803
+ it("should return false for any object that is not a Window", () => {
1804
+ expect(isWindow([])).toBe(false);
1805
+ expect(isWindow("")).toBeFalsy();
1806
+ expect(isWindow(23)).toBe(false);
1807
+ expect(isWindow({})).toBe(false);
1808
+ expect(isWindow(new Date())).toBe(false);
1809
+ expect(isWindow(document)).toBe(false);
1810
+ });
1811
+ });
1812
+
1813
+ describe("compile", () => {
1814
+ it("should link to existing node and create scope", () => {
1815
+ const template = angular.element(
1816
+ '<div>{{greeting = "hello world"}}</div>',
1817
+ );
1818
+ element = $compile(template)($rootScope);
1819
+ $rootScope.$digest();
1820
+ expect(template.text()).toEqual("hello world");
1821
+ expect($rootScope.greeting).toEqual("hello world");
1822
+ });
1823
+
1824
+ it("should link to existing node and given scope", () => {
1825
+ const template = angular.element(
1826
+ '<div>{{greeting = "hello world"}}</div>',
1827
+ );
1828
+ element = $compile(template)($rootScope);
1829
+ $rootScope.$digest();
1830
+ expect(template.text()).toEqual("hello world");
1831
+ });
1832
+
1833
+ it("should link to new node and given scope", () => {
1834
+ const template = jqLite('<div>{{greeting = "hello world"}}</div>');
1835
+
1836
+ const compile = $compile(template);
1837
+ let templateClone = template[0].cloneNode(true);
1838
+
1839
+ element = compile($rootScope, (clone) => {
1840
+ templateClone = clone;
1841
+ });
1842
+ $rootScope.$digest();
1843
+
1844
+ expect(template.text()).toEqual('{{greeting = "hello world"}}');
1845
+ expect(element.text()).toEqual("hello world");
1846
+ expect(element).toEqual(templateClone);
1847
+ expect($rootScope.greeting).toEqual("hello world");
1848
+ });
1849
+
1850
+ it("should link to cloned node and create scope", () => {
1851
+ const template = jqLite('<div>{{greeting = "hello world"}}</div>');
1852
+ element = $compile(template)($rootScope, () => {});
1853
+ $rootScope.$digest();
1854
+ expect(template.text()).toEqual('{{greeting = "hello world"}}');
1855
+ expect(element.text()).toEqual("hello world");
1856
+ expect($rootScope.greeting).toEqual("hello world");
1857
+ });
1858
+ });
1859
+
1860
+ describe("nodeName_", () => {
1861
+ it('should correctly detect node name with "namespace" when xmlns is defined', () => {
1862
+ const div = jqLite(
1863
+ '<div xmlns:ngtest="http://angularjs.org/">' +
1864
+ '<ngtest:foo ngtest:attr="bar"></ngtest:foo>' +
1865
+ "</div>",
1866
+ )[0];
1867
+ expect(nodeName_(div.childNodes[0])).toBe("ngtest:foo");
1868
+ expect(div.childNodes[0].getAttribute("ngtest:attr")).toBe("bar");
1869
+ });
1870
+
1871
+ it('should correctly detect node name with "namespace" when xmlns is NOT defined', () => {
1872
+ const div = jqLite(
1873
+ '<div xmlns:ngtest="http://angularjs.org/">' +
1874
+ '<ngtest:foo ngtest:attr="bar"></ng-test>' +
1875
+ "</div>",
1876
+ )[0];
1877
+ expect(nodeName_(div.childNodes[0])).toBe("ngtest:foo");
1878
+ expect(div.childNodes[0].getAttribute("ngtest:attr")).toBe("bar");
1879
+ });
1880
+
1881
+ it("should return undefined for elements without the .nodeName property", () => {
1882
+ // some elements, like SVGElementInstance don't have .nodeName property
1883
+ expect(nodeName_({})).toBeUndefined();
1884
+ });
1885
+ });
1886
+
1887
+ describe("nextUid()", () => {
1888
+ it("should return new id per call", () => {
1889
+ const seen = {};
1890
+ let count = 100;
1891
+
1892
+ while (count--) {
1893
+ const current = nextUid();
1894
+ expect(typeof current).toBe("number");
1895
+ expect(seen[current]).toBeFalsy();
1896
+ seen[current] = true;
1897
+ }
1898
+ });
1899
+ });
1900
+
1901
+ describe("bootstrap", () => {
1902
+ let module, injector, $rootScope, $compile;
1903
+
1904
+ beforeEach(() => {
1905
+ window.angular = new Angular();
1906
+ publishExternalAPI();
1907
+ createInjector();
1908
+ module = window.angular.module("defaultModule", ["ng"]);
1909
+ injector = createInjector(["ng", "defaultModule"]);
1910
+ $rootScope = injector.get("$rootScope");
1911
+ $compile = injector.get("$compile");
1912
+ });
1913
+
1914
+ it("should bootstrap app", () => {
1915
+ const element = jqLite("<div>{{1+2}}</div>");
1916
+ const injector = angular.bootstrap(element);
1917
+ expect(injector).toBeDefined();
1918
+ expect(element.injector()).toBe(injector);
1919
+ dealoc(element);
1920
+ });
1921
+
1922
+ it("should complain if app module can't be found", () => {
1923
+ const element = jqLite("<div>{{1+2}}</div>");
1924
+
1925
+ expect(() => {
1926
+ angular.bootstrap(element, ["doesntexist"]);
1927
+ }).toThrowError(/modulerr/);
1928
+
1929
+ expect(element.html()).toBe("{{1+2}}");
1930
+ dealoc(element);
1931
+ });
1932
+
1933
+ describe("deferred bootstrap", () => {
1934
+ const originalName = window.name;
1935
+ let element;
1936
+
1937
+ beforeEach(() => {
1938
+ window.name = "";
1939
+ element = jqLite("<div>{{1+2}}</div>");
1940
+ });
1941
+
1942
+ afterEach(() => {
1943
+ dealoc(element);
1944
+ window.name = originalName;
1945
+ });
1946
+
1947
+ it("should provide injector for deferred bootstrap", () => {
1948
+ window.name = "NG_DEFER_BOOTSTRAP!";
1949
+
1950
+ injector = angular.bootstrap(element);
1951
+ expect(injector).toBeUndefined();
1952
+
1953
+ injector = angular.resumeBootstrap();
1954
+ expect(injector).toBeDefined();
1955
+ });
1956
+
1957
+ it("should resume deferred bootstrap, if defined", () => {
1958
+ window.name = "NG_DEFER_BOOTSTRAP!";
1959
+
1960
+ angular.resumeDeferredBootstrap = () => {};
1961
+ const spy = spyOn(angular, "resumeDeferredBootstrap");
1962
+ injector = angular.bootstrap(element);
1963
+ expect(spy).toHaveBeenCalled();
1964
+ });
1965
+
1966
+ it("should wait for extra modules", () => {
1967
+ window.name = "NG_DEFER_BOOTSTRAP!";
1968
+ angular.bootstrap(element);
1969
+
1970
+ expect(element.html()).toBe("{{1+2}}");
1971
+
1972
+ angular.resumeBootstrap();
1973
+
1974
+ expect(element.html()).toBe("3");
1975
+ expect(window.name).toEqual("");
1976
+ });
1977
+
1978
+ it("should load extra modules", () => {
1979
+ element = jqLite("<div>{{1+2}}</div>");
1980
+ window.name = "NG_DEFER_BOOTSTRAP!";
1981
+
1982
+ const bootstrapping = jasmine.createSpy("bootstrapping");
1983
+ angular.bootstrap(element, [bootstrapping]);
1984
+
1985
+ expect(bootstrapping).not.toHaveBeenCalled();
1986
+ expect(element.injector()).toBeUndefined();
1987
+
1988
+ angular.module("addedModule", []).value("foo", "bar");
1989
+ angular.resumeBootstrap(["addedModule"]);
1990
+
1991
+ expect(bootstrapping).toHaveBeenCalled();
1992
+ expect(element.injector().get("foo")).toEqual("bar");
1993
+ });
1994
+
1995
+ it("should not defer bootstrap without window.name cue", () => {
1996
+ angular.bootstrap(element, []);
1997
+ angular.module("addedModule", []).value("foo", "bar");
1998
+
1999
+ expect(() => {
2000
+ element.injector().get("foo");
2001
+ }).toThrowError(/unpr/);
2002
+
2003
+ expect(element.injector().get("$http")).toBeDefined();
2004
+ });
2005
+
2006
+ it("should restore the original window.name after bootstrap", () => {
2007
+ window.name = "NG_DEFER_BOOTSTRAP!my custom name";
2008
+ angular.bootstrap(element);
2009
+
2010
+ expect(element.html()).toBe("{{1+2}}");
2011
+
2012
+ angular.resumeBootstrap();
2013
+
2014
+ expect(element.html()).toBe("3");
2015
+ expect(window.name).toEqual("my custom name");
2016
+ });
2017
+ });
2018
+ });
2019
+
2020
+ describe("startingElementHtml", () => {
2021
+ it("should show starting element tag only", () => {
2022
+ expect(startingTag('<ng-abc x="2A"><div>text</div></ng-abc>')).toBe(
2023
+ '<ng-abc x="2A">',
2024
+ );
2025
+ });
2026
+ });
2027
+
2028
+ describe("startingTag", () => {
2029
+ it("should allow passing in Nodes instead of Elements", () => {
2030
+ const txtNode = document.createTextNode("some text");
2031
+ expect(startingTag(txtNode)).toBe("some text");
2032
+ });
2033
+ });
2034
+
2035
+ describe("snakeCase", () => {
2036
+ it("should convert to snakeCase", () => {
2037
+ expect(snakeCase("ABC")).toEqual("a_b_c");
2038
+ expect(snakeCase("alanBobCharles")).toEqual("alan_bob_charles");
2039
+ });
2040
+
2041
+ it("should allow separator to be overridden", () => {
2042
+ expect(snakeCase("ABC", "&")).toEqual("a&b&c");
2043
+ expect(snakeCase("alanBobCharles", "&")).toEqual("alan&bob&charles");
2044
+ });
2045
+ });
2046
+
2047
+ describe("fromJson", () => {
2048
+ it("should delegate to JSON.parse", () => {
2049
+ const spy = spyOn(JSON, "parse").and.callThrough();
2050
+
2051
+ expect(fromJson("{}")).toEqual({});
2052
+ expect(spy).toHaveBeenCalled();
2053
+ });
2054
+ });
2055
+
2056
+ describe("toJson", () => {
2057
+ it("should delegate to JSON.stringify", () => {
2058
+ const spy = spyOn(JSON, "stringify").and.callThrough();
2059
+
2060
+ expect(toJson({})).toEqual("{}");
2061
+ expect(spy).toHaveBeenCalled();
2062
+ });
2063
+
2064
+ it("should format objects pretty", () => {
2065
+ expect(toJson({ a: 1, b: 2 }, true)).toBe('{\n "a": 1,\n "b": 2\n}');
2066
+ expect(toJson({ a: { b: 2 } }, true)).toBe(
2067
+ '{\n "a": {\n "b": 2\n }\n}',
2068
+ );
2069
+ expect(toJson({ a: 1, b: 2 }, false)).toBe('{"a":1,"b":2}');
2070
+ expect(toJson({ a: 1, b: 2 }, 0)).toBe('{"a":1,"b":2}');
2071
+ expect(toJson({ a: 1, b: 2 }, 1)).toBe('{\n "a": 1,\n "b": 2\n}');
2072
+ expect(toJson({ a: 1, b: 2 }, {})).toBe('{\n "a": 1,\n "b": 2\n}');
2073
+ });
2074
+
2075
+ it("should not serialize properties starting with $$", () => {
2076
+ expect(toJson({ $$some: "value" }, false)).toEqual("{}");
2077
+ });
2078
+
2079
+ it("should serialize properties starting with $", () => {
2080
+ expect(toJson({ $few: "v" }, false)).toEqual('{"$few":"v"}');
2081
+ });
2082
+
2083
+ it("should not serialize $window object", () => {
2084
+ expect(toJson(window)).toEqual('"$WINDOW"');
2085
+ });
2086
+
2087
+ it("should not serialize $document object", () => {
2088
+ expect(toJson(document)).toEqual('"$DOCUMENT"');
2089
+ });
2090
+
2091
+ it("should not serialize scope instances", () => {
2092
+ expect(toJson({ key: $rootScope })).toEqual('{"key":"$SCOPE"}');
2093
+ });
2094
+
2095
+ it("should serialize undefined as undefined", () => {
2096
+ expect(toJson(undefined)).toEqual(undefined);
2097
+ });
2098
+ });
2099
+
2100
+ describe("isElement", () => {
2101
+ it("should return a boolean value", () => {
2102
+ const element = $compile("<p>Hello, world!</p>")($rootScope);
2103
+ const body = window.document.body;
2104
+ const expected = [
2105
+ false,
2106
+ false,
2107
+ false,
2108
+ false,
2109
+ false,
2110
+ false,
2111
+ false,
2112
+ true,
2113
+ true,
2114
+ ];
2115
+ const tests = [
2116
+ null,
2117
+ undefined,
2118
+ "string",
2119
+ 1001,
2120
+ {},
2121
+ 0,
2122
+ false,
2123
+ body,
2124
+ element,
2125
+ ];
2126
+ angular.forEach(tests, (value, idx) => {
2127
+ const result = angular.isElement(value);
2128
+ expect(typeof result).toEqual("boolean");
2129
+ expect(result).toEqual(expected[idx]);
2130
+ });
2131
+ });
2132
+
2133
+ // Issue #4805
2134
+ it("should return false for objects resembling a Backbone Collection", () => {
2135
+ // Backbone stuff is sort of hard to mock, if you have a better way of doing this,
2136
+ // please fix this.
2137
+ const fakeBackboneCollection = {
2138
+ children: [{}, {}, {}],
2139
+ find() {},
2140
+ on() {},
2141
+ off() {},
2142
+ bind() {},
2143
+ };
2144
+ expect(isElement(fakeBackboneCollection)).toBe(false);
2145
+ });
2146
+
2147
+ it("should return false for arrays with node-like properties", () => {
2148
+ const array = [1, 2, 3];
2149
+ array.on = true;
2150
+ expect(isElement(array)).toBe(false);
2151
+ });
2152
+ });
2153
+ });