ivue 0.1.11 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintignore +7 -0
  3. package/.eslintrc copy.js +120 -0
  4. package/.eslintrc.js +120 -0
  5. package/.github/workflows/ci.yml +68 -0
  6. package/.prettierrc +5 -0
  7. package/LICENSE +2 -2
  8. package/README.md +20 -28
  9. package/demo/App.vue +113 -56
  10. package/demo/main.ts +5 -19
  11. package/demo/vite.config.ts +8 -1
  12. package/docs/.editorconfig +9 -0
  13. package/docs/.env +1 -0
  14. package/docs/.eslintignore +7 -0
  15. package/docs/.eslintrc.js +120 -0
  16. package/docs/.prettierrc +5 -0
  17. package/docs/docs/.vitepress/config.ts +56 -0
  18. package/docs/docs/api/propsWithDefaults.md +0 -0
  19. package/docs/docs/components/Button.vue +13 -0
  20. package/docs/docs/components/Component.vue +20 -0
  21. package/docs/docs/components/examples/Counter.vue +17 -0
  22. package/docs/docs/index.md +32 -0
  23. package/docs/docs/pages/getting-started.md +14 -0
  24. package/docs/docs/pages/how-it-works.md +0 -0
  25. package/docs/docs/pages/introduction.md +45 -0
  26. package/docs/docs/pages/usage.md +16 -0
  27. package/docs/package.json +35 -0
  28. package/docs/scripts/gh-pages-deploy.js +34 -0
  29. package/docs/vite-env.d.ts +7 -0
  30. package/docs/vite.config.ts +20 -0
  31. package/index.html +5 -4
  32. package/package.json +46 -61
  33. package/src/__tests__/ivue.vitest.spec.ts +426 -0
  34. package/src/index.ts +460 -80
  35. package/tsconfig.json +21 -11
  36. package/vite-env.d.ts +7 -0
  37. package/vite.config.ts +26 -26
  38. package/vitest.config.ts +13 -12
  39. package/.babelrc.json +0 -14
  40. package/.eslintrc.cjs +0 -24
  41. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  42. package/.idea/compiler.xml +0 -7
  43. package/.idea/inspectionProfiles/Project_Default.xml +0 -11
  44. package/.idea/ivue.iml +0 -10
  45. package/.idea/modules.xml +0 -8
  46. package/.idea/php.xml +0 -20
  47. package/.idea/vcs.xml +0 -6
  48. package/.vscode/extensions.json +0 -3
  49. package/PLAN.md +0 -39
  50. package/demo/components/IVueTest.vue +0 -301
  51. package/demo/components/PreComponent.vue +0 -13
  52. package/demo/components/SubComponent2.vue +0 -45
  53. package/demo/components/TraitsComponent.vue +0 -120
  54. package/demo/components/useIVueTest.vue +0 -136
  55. package/demo/router/index.ts +0 -14
  56. package/demo/tests/IVueTests.ts +0 -265
  57. package/demo/tests/Mouse.ts +0 -79
  58. package/demo/tests/ParentIVueTests.ts +0 -36
  59. package/demo/tests/TApp.ts +0 -15
  60. package/demo/tests/TAuth.ts +0 -23
  61. package/demo/tests/TField.ts +0 -84
  62. package/demo/tests/TMessage.ts +0 -52
  63. package/demo/tests/TRouter.ts +0 -18
  64. package/demo/tests/TUser.ts +0 -19
  65. package/demo/tests/Test.ts +0 -86
  66. package/demo/tests/useField.ts +0 -82
  67. package/demo/tests/useIVueTests.ts +0 -57
  68. package/dist/favicon.ico +0 -0
  69. package/dist/index.es.js +0 -516
  70. package/dist/index.umd.js +0 -1
  71. package/dist/src/behavior.d.ts +0 -72
  72. package/dist/src/config.d.ts +0 -6
  73. package/dist/src/index.d.ts +0 -21
  74. package/dist/src/ivue.d.ts +0 -36
  75. package/dist/src/kernel.d.ts +0 -182
  76. package/dist/src/traits/UseCapsule.d.ts +0 -9
  77. package/dist/src/traits/UseEmit.d.ts +0 -3
  78. package/dist/src/traits/UseInstance.d.ts +0 -6
  79. package/dist/src/traits/UseMounting.d.ts +0 -11
  80. package/dist/src/traits/UseRefs.d.ts +0 -8
  81. package/dist/src/traits/UseRoute.d.ts +0 -3
  82. package/dist/src/traits/UseRouter.d.ts +0 -3
  83. package/dist/src/traits/UseRouting.d.ts +0 -6
  84. package/dist/src/traits/UseTick.d.ts +0 -4
  85. package/dist/src/traits/UseVue.d.ts +0 -13
  86. package/dist/src/types/core.d.ts +0 -46
  87. package/dist/src/utils/dispose-garbage.d.ts +0 -12
  88. package/dist/src/utils/extend.d.ts +0 -12
  89. package/dist/src/utils/getters.d.ts +0 -21
  90. package/dist/src/utils/index.d.ts +0 -7
  91. package/dist/src/utils/is.d.ts +0 -14
  92. package/dist/src/utils/pre.d.ts +0 -9
  93. package/dist/src/utils/raw.d.ts +0 -12
  94. package/dist/src/utils/safe-class-name.d.ts +0 -7
  95. package/dist/src/utils/traits.d.ts +0 -41
  96. package/env.d.ts +0 -1
  97. package/package-lock.json +0 -14305
  98. package/public/favicon.ico +0 -0
  99. package/src/App/App.ts +0 -30
  100. package/src/App/Auth/Auth.ts +0 -105
  101. package/src/App/Auth/Auth.vue +0 -98
  102. package/src/App/Auth/Logout.vue +0 -14
  103. package/src/App/Auth/User.ts +0 -6
  104. package/src/App/BlackBox.ts +0 -82
  105. package/src/App/Config.ts +0 -6
  106. package/src/App/Generators/generators.ts +0 -47
  107. package/src/App/Home/Home.vue +0 -16
  108. package/src/App/Services/Http/FakeHttp.ts +0 -8
  109. package/src/App/Services/Http/Http.ts +0 -51
  110. package/src/App/Services/Message/Message.ts +0 -49
  111. package/src/App/Services/Message/Message.vue +0 -15
  112. package/src/App/Services/Navigation/Navigation.ts +0 -83
  113. package/src/App/Services/Navigation/Navigation.vue +0 -59
  114. package/src/App/Services/Routing/FakeRouter.ts +0 -7
  115. package/src/App/Services/Routing/NotFoundRoute.vue +0 -13
  116. package/src/App/Services/Routing/Router.ts +0 -263
  117. package/src/App/Services/Routing/Routes.ts +0 -49
  118. package/src/App/Stubs/SingleBookResultStub.ts +0 -13
  119. package/src/App/Traits/UseApp.ts +0 -6
  120. package/src/App/Traits/UseQuasar.ts +0 -8
  121. package/src/behavior.ts +0 -269
  122. package/src/config.ts +0 -15
  123. package/src/dev/dev-utils.ts +0 -78
  124. package/src/ivue.ts +0 -299
  125. package/src/kernel.ts +0 -815
  126. package/src/tests/auth.spec.ts +0 -87
  127. package/src/traits/UseCapsule.ts +0 -28
  128. package/src/traits/UseEmit.ts +0 -3
  129. package/src/traits/UseInstance.ts +0 -17
  130. package/src/traits/UseMounting.ts +0 -23
  131. package/src/traits/UseRefs.ts +0 -17
  132. package/src/traits/UseRoute.ts +0 -6
  133. package/src/traits/UseRouter.ts +0 -5
  134. package/src/traits/UseRouting.ts +0 -7
  135. package/src/traits/UseTick.ts +0 -5
  136. package/src/traits/UseVue.ts +0 -38
  137. package/src/types/core.ts +0 -66
  138. package/src/utils/dispose-garbage.ts +0 -34
  139. package/src/utils/extend.ts +0 -86
  140. package/src/utils/getters.ts +0 -59
  141. package/src/utils/index.ts +0 -16
  142. package/src/utils/is.ts +0 -22
  143. package/src/utils/pre.ts +0 -29
  144. package/src/utils/raw.ts +0 -19
  145. package/src/utils/safe-class-name.ts +0 -15
  146. package/src/utils/traits.ts +0 -121
  147. package/tsconfig.app.json +0 -47
  148. package/tsconfig.node.json +0 -14
  149. package/tsconfig.vitest.json +0 -9
  150. /package/{src/App/Traits/UseBlackline.ts → docs/docs/api/ivue.md} +0 -0
@@ -0,0 +1,426 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { isReactive, ref } from "vue";
3
+
4
+ import { ivue, getAllClassDescriptors, getAllClassProperties } from "../index";
5
+
6
+ class Basic {
7
+ id = ref("id") as unknown as string;
8
+ }
9
+
10
+ class Bit {
11
+ _testProperty = ref("test-value") as unknown as string;
12
+ /** Setter without a getter. */
13
+ set testProperty(value: string) {
14
+ this._testProperty = value;
15
+ }
16
+ }
17
+
18
+ class Item extends Bit {
19
+ _width = ref(5) as unknown as string | number;
20
+ unit = ref("px") as unknown as string;
21
+ get width(): string {
22
+ return String(this._width) + this.unit;
23
+ }
24
+ set width(value: string | number) {
25
+ this._width = value;
26
+ }
27
+ _height = ref(5) as unknown as string | number;
28
+ get height(): string {
29
+ return String(this._height) + this.unit;
30
+ }
31
+ set height(value: string | number) {
32
+ this._height = value;
33
+ }
34
+ }
35
+
36
+ class ProductItem extends Item {
37
+ _productType = ref("generic") as unknown as string;
38
+ get productType() {
39
+ return this._productType;
40
+ }
41
+ set productType(value) {
42
+ this._productType = value;
43
+ }
44
+ _productFit = ref("perfect-fit") as unknown as string;
45
+ get productFit() {
46
+ return this._productFit;
47
+ }
48
+ _productId = ref(0) as unknown as number;
49
+ set productId(value: number) {
50
+ this._productId = 0;
51
+ }
52
+ _productFeel = ref("sleek") as unknown as string;
53
+ public get productFeel() {
54
+ return this._productFeel;
55
+ }
56
+ }
57
+
58
+ class StoreItem extends ProductItem {
59
+ _productType = ref("store") as unknown as string;
60
+ get productType() {
61
+ const prefix = super.productFeel ?? "";
62
+ return (prefix ? prefix + ":" : "") + this._productType;
63
+ }
64
+ set productFeel(value: string) {
65
+ this._productFeel = value;
66
+ }
67
+ }
68
+
69
+ class RetailStoreItem extends StoreItem {
70
+ _productType = ref("retail") as unknown as string;
71
+ /** Do not overwrite productType getter here, on purpose. */
72
+ productHistory = ref([]);
73
+ get testProperty() {
74
+ return this._testProperty;
75
+ }
76
+ calculateSize() {
77
+ return (this._height as number) + (this._width as number);
78
+ }
79
+ }
80
+
81
+ let computedCalls = 0;
82
+ let notComputedCalls = 0;
83
+
84
+ class Entity {
85
+ _key = ref(0) as unknown as number;
86
+ height = ref(0) as unknown as number;
87
+ width = ref(0) as unknown as number;
88
+ constructor(height: number, width = 5) {
89
+ this.height = height;
90
+ this.width = width;
91
+ }
92
+ init() {
93
+ this._key = 5;
94
+ }
95
+ get key() {
96
+ return this._key;
97
+ }
98
+ static ivue = {
99
+ notComputed: false,
100
+ };
101
+
102
+ logNotComputedCalls() {
103
+ notComputedCalls++;
104
+ }
105
+ get notComputed() {
106
+ this.logNotComputedCalls();
107
+ return this.width + this.height;
108
+ }
109
+
110
+ logComputedCalls() {
111
+ computedCalls++;
112
+ }
113
+ get computed() {
114
+ this.logComputedCalls();
115
+ return this.width + this.height;
116
+ }
117
+ }
118
+
119
+ describe("ivue", () => {
120
+ describe("base architecture functions", () => {
121
+ it("getAllClassDescriptors correctly resolves all parent descriptors", () => {
122
+ const descriptors = getAllClassDescriptors(Item);
123
+
124
+ expect(descriptors.has("width")).toBe(true);
125
+ expect(typeof descriptors.get("width")?.get).toBe("function");
126
+ expect(typeof descriptors.get("width")?.set).toBe("function");
127
+
128
+ expect(descriptors.has("height")).toBe(true);
129
+ expect(typeof descriptors.get("height")?.get).toBe("function");
130
+ expect(typeof descriptors.get("height")?.set).toBe("function");
131
+
132
+ expect(descriptors.has("testProperty")).toBe(true);
133
+ expect(typeof descriptors.get("testProperty")?.get).toBe("undefined");
134
+ expect(typeof descriptors.get("testProperty")?.set).toBe("function");
135
+ });
136
+
137
+ it("getAllClassDescriptors correctly resolves all grand parent descriptors", () => {
138
+ const descriptors = getAllClassDescriptors(ProductItem);
139
+
140
+ expect(descriptors.has("width")).toBe(true);
141
+ expect(typeof descriptors.get("width")?.get).toBe("function");
142
+ expect(typeof descriptors.get("width")?.set).toBe("function");
143
+
144
+ expect(descriptors.has("height")).toBe(true);
145
+ expect(typeof descriptors.get("height")?.get).toBe("function");
146
+ expect(typeof descriptors.get("height")?.set).toBe("function");
147
+
148
+ expect(descriptors.has("testProperty")).toBe(true);
149
+ expect(typeof descriptors.get("testProperty")?.get).toBe("undefined");
150
+ expect(typeof descriptors.get("testProperty")?.set).toBe("function");
151
+
152
+ expect(descriptors.has("productType")).toBe(true);
153
+ expect(typeof descriptors.get("productType")?.get).toBe("function");
154
+ expect(typeof descriptors.get("productType")?.set).toBe("function");
155
+
156
+ expect(descriptors.has("productFeel")).toBe(true);
157
+ expect(typeof descriptors.get("productFeel")?.get).toBe("function");
158
+ expect(typeof descriptors.get("productFeel")?.set).toBe("undefined");
159
+
160
+ expect(descriptors.has("productId")).toBe(true);
161
+ expect(typeof descriptors.get("productId")?.get).toBe("undefined");
162
+ expect(typeof descriptors.get("productId")?.set).toBe("function");
163
+ });
164
+
165
+ it("getAllClassProperties correctly resolves all parent properties", () => {
166
+ const item = ivue(Item);
167
+ const props = getAllClassProperties(item);
168
+
169
+ expect(props.has("_width")).toBe(true);
170
+ expect(props.has("_height")).toBe(true);
171
+ expect(props.has("_testProperty")).toBe(true);
172
+ expect(props.has("width")).toBe(true);
173
+ expect(props.has("height")).toBe(true);
174
+ expect(props.has("testProperty")).toBe(true);
175
+ });
176
+
177
+ it("getAllClassProperties correctly resolves all grand parent properties", () => {
178
+ const item = ivue(ProductItem);
179
+ const props = getAllClassProperties(item);
180
+
181
+ expect(props.has("_width")).toBe(true);
182
+ expect(props.has("_height")).toBe(true);
183
+ expect(props.has("_testProperty")).toBe(true);
184
+ expect(props.has("_productType")).toBe(true);
185
+ expect(props.has("_productFit")).toBe(true);
186
+ expect(props.has("_productId")).toBe(true);
187
+ expect(props.has("width")).toBe(true);
188
+ expect(props.has("height")).toBe(true);
189
+ expect(props.has("testProperty")).toBe(true);
190
+ expect(props.has("productType")).toBe(true);
191
+ expect(props.has("productFit")).toBe(true);
192
+ expect(props.has("productId")).toBe(true);
193
+ });
194
+ });
195
+
196
+ describe("ivue full class reactivity inheritance", () => {
197
+ it("basic refs are working", () => {
198
+ const basic = ivue(Basic);
199
+
200
+ expect(basic.id).toBe("id");
201
+ basic.id = "test";
202
+ expect(basic.id).toBe("test");
203
+ });
204
+
205
+ it("basic refs are unwrapped inside reactive ivue object", () => {
206
+ const item = ivue(Item);
207
+
208
+ expect(item._height).toBe(5);
209
+ expect(item._width).toBe(5);
210
+ expect(isReactive(item)).toBe(true);
211
+ });
212
+
213
+ it("basic getter as computed is working", () => {
214
+ const item = ivue(Item);
215
+
216
+ expect(item._height).toBe(5);
217
+ expect(item.height).toBe("5px");
218
+ expect(item._width).toBe(5);
219
+ expect(item.width).toBe("5px");
220
+ });
221
+
222
+ it("basic setter is working", () => {
223
+ const item = ivue(Item);
224
+
225
+ expect(item._height).toBe(5);
226
+ /** SET VIA SETTER */
227
+ item.height = 10;
228
+ expect(item.height).toBe("10px");
229
+
230
+ expect(item._width).toBe(5);
231
+ /** SET VIA SETTER */
232
+ item.width = 10;
233
+ expect(item.width).toBe("10px");
234
+ });
235
+
236
+ it("parent getters from the prototype chain are working", () => {
237
+ const item = ivue(RetailStoreItem);
238
+
239
+ expect(item.productType).toBe("sleek:retail");
240
+ });
241
+
242
+ it("parent setters from the prototype chain are working", () => {
243
+ const item = ivue(RetailStoreItem);
244
+
245
+ expect(item.productType).toBe("sleek:retail");
246
+ /** SET VIA SETTER */
247
+ // @ts-expect-error ivue supports setting set and get separately in different levels of class prototype chain
248
+ item.productType = "new-retail";
249
+ expect(item.productType).toBe("sleek:new-retail");
250
+ });
251
+
252
+ it("parent setters that are set at different levels in the prototype chain work together in harmony", () => {
253
+ const item = ivue(RetailStoreItem);
254
+ /**
255
+ * Setter for product feel is set on @see {StoreItem} class,
256
+ * but getter is set on parent @see {ProductItem} class,
257
+ * but in ivue they still work together just as they should,
258
+ * completely emulating native JavaScript implementation.
259
+ */
260
+ item.productFeel = "new-feel";
261
+ expect(item.productType).toBe("new-feel:retail");
262
+ });
263
+
264
+ it("parent setters are working even without getters", () => {
265
+ const item = ivue(RetailStoreItem);
266
+
267
+ expect(item._testProperty).toBe("test-value");
268
+ /** SET VIA SETTER */
269
+ // @ts-expect-error ivue supports setting set and get separately in different levels of class prototype chain
270
+ item.testProperty = "new-test-value";
271
+ expect(item._testProperty).toBe("new-test-value");
272
+ });
273
+ });
274
+
275
+ describe("ivue toRefs conversion", () => {
276
+ it("toRefs all properties", () => {
277
+ const { _height, _width, height, width, calculateSize } =
278
+ ivue(RetailStoreItem).toRefs();
279
+
280
+ expect(_height.value).toBe(5);
281
+ expect(_width.value).toBe(5);
282
+ expect(height.value).toBe("5px");
283
+ expect(width.value).toBe("5px");
284
+ expect(calculateSize()).toBe(10);
285
+ });
286
+
287
+ it("toRefs all properties with pre-calculated computeds", () => {
288
+ const item = ivue(RetailStoreItem);
289
+
290
+ /** Access computeds to pre-calculate them before toRefs() */
291
+ item.height;
292
+ item.width;
293
+
294
+ const { height, width, calculateSize } = item.toRefs();
295
+
296
+ expect(height.value).toBe("5px");
297
+ expect(width.value).toBe("5px");
298
+ expect(calculateSize()).toBe(10);
299
+ });
300
+
301
+ it("toRefs(['prop', ...]) specific properties", () => {
302
+ const item = ivue(ProductItem);
303
+
304
+ const { _height, _width, height, width } = item.toRefs([
305
+ "_width",
306
+ "_height",
307
+ "height",
308
+ "width",
309
+ ]);
310
+
311
+ expect(_height.value).toBe(5);
312
+ expect(_width.value).toBe(5);
313
+ expect(height.value).toBe("5px");
314
+ expect(width.value).toBe("5px");
315
+ });
316
+
317
+ it("toRefs(['prop', ...]) specific properties with pre-calculated computeds", () => {
318
+ const item = ivue(ProductItem);
319
+
320
+ /** Access computeds to pre-calculate them before toRefs() */
321
+ item.height;
322
+ item.width;
323
+
324
+ const { _height, _width, height, width } = item.toRefs([
325
+ "_width",
326
+ "_height",
327
+ "height",
328
+ "width",
329
+ ]);
330
+
331
+ expect(_height.value).toBe(5);
332
+ expect(_width.value).toBe(5);
333
+ expect(height.value).toBe("5px");
334
+ expect(width.value).toBe("5px");
335
+ });
336
+
337
+ it("toRefs(['prop', ...]) specific functions", () => {
338
+ const { calculateSize } = ivue(RetailStoreItem).toRefs(["calculateSize"]);
339
+
340
+ expect(calculateSize()).toBe(10);
341
+ });
342
+
343
+ it("toRefs() all properties with using a computed as a setter without a getter", () => {
344
+ const item = ivue(ProductItem);
345
+
346
+ const { testProperty } = item.toRefs();
347
+
348
+ testProperty.value = "changed-test-value";
349
+ expect(item._testProperty).toBe("changed-test-value");
350
+ const call = () => testProperty.value;
351
+ expect(() => call()).toThrowError(TypeError);
352
+ });
353
+
354
+ it("toRefs(['prop', ...]) specific properties with using a computed as a setter without a getter", () => {
355
+ const item = ivue(ProductItem);
356
+
357
+ const { testProperty } = item.toRefs(["testProperty"]);
358
+
359
+ testProperty.value = "changed-test-value";
360
+ expect(item._testProperty).toBe("changed-test-value");
361
+ });
362
+
363
+ it("toRefs() all properties with a computed that has a setter without a getter, should throw error when accessed as a getter", () => {
364
+ const item = ivue(ProductItem);
365
+
366
+ const { testProperty } = item.toRefs();
367
+
368
+ const call = () => testProperty.value;
369
+ expect(() => call()).toThrowError(TypeError);
370
+ });
371
+
372
+ it("toRefs(['prop', ...]) with specific properties with a computed that has a setter without a getter, should throw error when accessed as a getter", () => {
373
+ const item = ivue(ProductItem);
374
+
375
+ const { testProperty } = item.toRefs(["testProperty"]);
376
+
377
+ const call = () => testProperty.value;
378
+ expect(() => call()).toThrowError(TypeError);
379
+ });
380
+ });
381
+
382
+ describe("ivue constructor", () => {
383
+ it("ivue constructor arguments get passed to the constructor work", () => {
384
+ const entity = ivue(Entity, 10, 20);
385
+ expect(entity.height).toBe(10);
386
+ expect(entity.width).toBe(20);
387
+ });
388
+ });
389
+
390
+ describe("ivue init method", () => {
391
+ it("init works", () => {
392
+ const entity = ivue(Entity, 10, 20);
393
+ expect(entity.key).toBe(5);
394
+ });
395
+ });
396
+
397
+ describe("ivue disabled getters", () => {
398
+ it("ivue active getter is a computed", () => {
399
+ computedCalls = 0;
400
+ notComputedCalls = 0;
401
+
402
+ const entity = ivue(Entity, 10, 20);
403
+ expect(entity.computed).toBe(30); // Access computed
404
+ expect(computedCalls).toBe(1); // Increment to 1, initial computed call
405
+ expect(entity.computed).toBe(30); // Access computed
406
+ expect(computedCalls).toBe(1); // Remains 1, because the dependencies didn't change
407
+ entity.height = 20; // Change dependency
408
+ expect(entity.computed).toBe(40); // Access computed
409
+ expect(computedCalls).toBe(2); // Computed call increments to 2, because dependency changed
410
+ });
411
+
412
+ it("ivue disabled getter is not a computed", () => {
413
+ computedCalls = 0;
414
+ notComputedCalls = 0;
415
+
416
+ const entity = ivue(Entity, 10, 20);
417
+ expect(entity.notComputed).toBe(30); // Access computed
418
+ expect(notComputedCalls).toBe(1); // Always incrementing
419
+ expect(entity.notComputed).toBe(30); // Access computed
420
+ expect(notComputedCalls).toBe(2); // Always incrementing
421
+ entity.height = 20; // Change reactive computed dependency
422
+ expect(entity.notComputed).toBe(40); // Access computed
423
+ expect(notComputedCalls).toBe(3); // Always incrementing
424
+ });
425
+ });
426
+ });