@gogocat/data-bind 1.12.0 → 2.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 (271) hide show
  1. package/.editorconfig +14 -14
  2. package/.vscode/launch.json +12 -12
  3. package/CONFIGURATION.md +294 -0
  4. package/REACTIVE_MODE.md +553 -0
  5. package/README.md +266 -829
  6. package/babel.config.json +30 -0
  7. package/dist/js/_escape.d.ts +14 -0
  8. package/dist/js/_escape.d.ts.map +1 -0
  9. package/dist/js/applyBinding.d.ts +11 -0
  10. package/dist/js/applyBinding.d.ts.map +1 -0
  11. package/dist/js/attrBinding.d.ts +12 -0
  12. package/dist/js/attrBinding.d.ts.map +1 -0
  13. package/dist/js/binder.d.ts +67 -0
  14. package/dist/js/binder.d.ts.map +1 -0
  15. package/dist/js/changeBinding.d.ts +19 -0
  16. package/dist/js/changeBinding.d.ts.map +1 -0
  17. package/dist/js/commentWrapper.d.ts +39 -0
  18. package/dist/js/commentWrapper.d.ts.map +1 -0
  19. package/dist/js/config.d.ts +55 -0
  20. package/dist/js/config.d.ts.map +1 -0
  21. package/dist/js/createBindingOption.d.ts +32 -0
  22. package/dist/js/createBindingOption.d.ts.map +1 -0
  23. package/dist/js/createEventBinding.d.ts +10 -0
  24. package/dist/js/createEventBinding.d.ts.map +1 -0
  25. package/dist/js/cssBinding.d.ts +15 -0
  26. package/dist/js/cssBinding.d.ts.map +1 -0
  27. package/dist/js/dataBind.js +2756 -2530
  28. package/dist/js/dataBind.min.js +8 -1
  29. package/dist/js/dataBind.min.js.map +1 -1
  30. package/dist/js/domWalker.d.ts +9 -0
  31. package/dist/js/domWalker.d.ts.map +1 -0
  32. package/dist/js/forOfBinding.d.ts +12 -0
  33. package/dist/js/forOfBinding.d.ts.map +1 -0
  34. package/dist/js/hoverBinding.d.ts +13 -0
  35. package/dist/js/hoverBinding.d.ts.map +1 -0
  36. package/dist/js/ifBinding.d.ts +12 -0
  37. package/dist/js/ifBinding.d.ts.map +1 -0
  38. package/dist/js/index.d.ts +10 -0
  39. package/dist/js/index.d.ts.map +1 -0
  40. package/dist/js/modelBinding.d.ts +12 -0
  41. package/dist/js/modelBinding.d.ts.map +1 -0
  42. package/dist/js/postProcess.d.ts +3 -0
  43. package/dist/js/postProcess.d.ts.map +1 -0
  44. package/dist/js/pubSub.d.ts +11 -0
  45. package/dist/js/pubSub.d.ts.map +1 -0
  46. package/dist/js/reactiveProxy.d.ts +28 -0
  47. package/dist/js/reactiveProxy.d.ts.map +1 -0
  48. package/dist/js/renderForOfBinding.d.ts +8 -0
  49. package/dist/js/renderForOfBinding.d.ts.map +1 -0
  50. package/dist/js/renderIfBinding.d.ts +22 -0
  51. package/dist/js/renderIfBinding.d.ts.map +1 -0
  52. package/dist/js/renderIteration.d.ts +16 -0
  53. package/dist/js/renderIteration.d.ts.map +1 -0
  54. package/dist/js/renderTemplate.d.ts +14 -0
  55. package/dist/js/renderTemplate.d.ts.map +1 -0
  56. package/dist/js/renderTemplatesBinding.d.ts +19 -0
  57. package/dist/js/renderTemplatesBinding.d.ts.map +1 -0
  58. package/dist/js/showBinding.d.ts +13 -0
  59. package/dist/js/showBinding.d.ts.map +1 -0
  60. package/dist/js/switchBinding.d.ts +13 -0
  61. package/dist/js/switchBinding.d.ts.map +1 -0
  62. package/dist/js/textBinding.d.ts +13 -0
  63. package/dist/js/textBinding.d.ts.map +1 -0
  64. package/dist/js/types/_escape.d.ts +14 -0
  65. package/dist/js/types/_escape.d.ts.map +1 -0
  66. package/dist/js/types/applyBinding.d.ts +11 -0
  67. package/dist/js/types/applyBinding.d.ts.map +1 -0
  68. package/dist/js/types/attrBinding.d.ts +12 -0
  69. package/dist/js/types/attrBinding.d.ts.map +1 -0
  70. package/dist/js/types/binder.d.ts +67 -0
  71. package/dist/js/types/binder.d.ts.map +1 -0
  72. package/dist/js/types/changeBinding.d.ts +19 -0
  73. package/dist/js/types/changeBinding.d.ts.map +1 -0
  74. package/dist/js/types/commentWrapper.d.ts +39 -0
  75. package/dist/js/types/commentWrapper.d.ts.map +1 -0
  76. package/dist/js/types/config.d.ts +55 -0
  77. package/dist/js/types/config.d.ts.map +1 -0
  78. package/dist/js/types/createBindingOption.d.ts +32 -0
  79. package/dist/js/types/createBindingOption.d.ts.map +1 -0
  80. package/dist/js/types/createEventBinding.d.ts +10 -0
  81. package/dist/js/types/createEventBinding.d.ts.map +1 -0
  82. package/dist/js/types/cssBinding.d.ts +15 -0
  83. package/dist/js/types/cssBinding.d.ts.map +1 -0
  84. package/dist/js/types/domWalker.d.ts +9 -0
  85. package/dist/js/types/domWalker.d.ts.map +1 -0
  86. package/dist/js/types/forOfBinding.d.ts +12 -0
  87. package/dist/js/types/forOfBinding.d.ts.map +1 -0
  88. package/dist/js/types/hoverBinding.d.ts +13 -0
  89. package/dist/js/types/hoverBinding.d.ts.map +1 -0
  90. package/dist/js/types/ifBinding.d.ts +12 -0
  91. package/dist/js/types/ifBinding.d.ts.map +1 -0
  92. package/dist/js/types/index.d.ts +10 -0
  93. package/dist/js/types/index.d.ts.map +1 -0
  94. package/dist/js/types/modelBinding.d.ts +12 -0
  95. package/dist/js/types/modelBinding.d.ts.map +1 -0
  96. package/dist/js/types/postProcess.d.ts +3 -0
  97. package/dist/js/types/postProcess.d.ts.map +1 -0
  98. package/dist/js/types/pubSub.d.ts +11 -0
  99. package/dist/js/types/pubSub.d.ts.map +1 -0
  100. package/dist/js/types/reactiveProxy.d.ts +28 -0
  101. package/dist/js/types/reactiveProxy.d.ts.map +1 -0
  102. package/dist/js/types/renderForOfBinding.d.ts +8 -0
  103. package/dist/js/types/renderForOfBinding.d.ts.map +1 -0
  104. package/dist/js/types/renderIfBinding.d.ts +22 -0
  105. package/dist/js/types/renderIfBinding.d.ts.map +1 -0
  106. package/dist/js/types/renderIteration.d.ts +16 -0
  107. package/dist/js/types/renderIteration.d.ts.map +1 -0
  108. package/dist/js/types/renderTemplate.d.ts +14 -0
  109. package/dist/js/types/renderTemplate.d.ts.map +1 -0
  110. package/dist/js/types/renderTemplatesBinding.d.ts +19 -0
  111. package/dist/js/types/renderTemplatesBinding.d.ts.map +1 -0
  112. package/dist/js/types/showBinding.d.ts +13 -0
  113. package/dist/js/types/showBinding.d.ts.map +1 -0
  114. package/dist/js/types/switchBinding.d.ts +13 -0
  115. package/dist/js/types/switchBinding.d.ts.map +1 -0
  116. package/dist/js/types/textBinding.d.ts +13 -0
  117. package/dist/js/types/textBinding.d.ts.map +1 -0
  118. package/dist/js/types/types.d.ts +111 -0
  119. package/dist/js/types/types.d.ts.map +1 -0
  120. package/dist/js/types/util.d.ts +119 -0
  121. package/dist/js/types/util.d.ts.map +1 -0
  122. package/dist/js/types.d.ts +111 -0
  123. package/dist/js/types.d.ts.map +1 -0
  124. package/dist/js/util.d.ts +119 -0
  125. package/dist/js/util.d.ts.map +1 -0
  126. package/eslint.config.js +124 -0
  127. package/examples/DBMONSTER_COMPARISON.md +123 -0
  128. package/examples/afterRenderDemo.html +119 -0
  129. package/examples/bootstrap/css/animate.css +1579 -1579
  130. package/examples/bootstrap/css/bootstrap.min.css +6 -6
  131. package/examples/bootstrap/css/homeservices.css +378 -390
  132. package/examples/bootstrap/css/open-iconic.css +511 -511
  133. package/examples/bootstrap/fonts/open-iconic.svg +543 -543
  134. package/examples/bootstrap/js/compMessageDialog.js +20 -19
  135. package/examples/bootstrap/js/compSearchBar.js +12 -19
  136. package/examples/bootstrap/js/compSearchResults.js +50 -46
  137. package/examples/bootstrap/js/featureAdsResult.json +65 -65
  138. package/examples/bootstrap/js/searchResult.json +57 -57
  139. package/examples/bootstrap.html +343 -332
  140. package/examples/css/baseTodo.css +141 -141
  141. package/examples/css/dbMonsterStyles.css +27 -27
  142. package/examples/css/indexTodo.css +374 -374
  143. package/examples/dbmonsterForOfReactive.html +40 -0
  144. package/examples/dbmonsterReact.html +19 -0
  145. package/examples/forOfBindingSimpleDebug.html +45 -0
  146. package/examples/globalConfig.html +131 -0
  147. package/examples/js/afterRenderDemo.js +190 -0
  148. package/examples/js/appTodo.js +46 -46
  149. package/examples/js/attrBindingDemo.js +2 -2
  150. package/examples/js/dbMonApp.js +24 -26
  151. package/examples/js/dbMonAppReact.jsx +79 -0
  152. package/examples/js/dbMonAppReactive.js +28 -0
  153. package/examples/js/fiberDemo.js +4 -4
  154. package/examples/js/filtersDemo.js +8 -8
  155. package/examples/js/forOfDemo.js +7 -9
  156. package/examples/js/forOfDemoComplex.js +44 -17
  157. package/examples/js/form.js +14 -14
  158. package/examples/js/globalConfig.js +117 -0
  159. package/examples/js/ifBindingDemo.js +16 -16
  160. package/examples/js/reactiveDemo.js +119 -0
  161. package/examples/js/switchBindingDemo.js +8 -8
  162. package/examples/react-dbmonster/dist/bundle.js +43 -0
  163. package/examples/react-dbmonster/package-lock.json +537 -0
  164. package/examples/react-dbmonster/package.json +16 -0
  165. package/examples/react-dbmonster/src/index.jsx +80 -0
  166. package/examples/reactiveDemo.html +127 -0
  167. package/examples/refreshRateTest.html +75 -75
  168. package/index.html +841 -0
  169. package/package.json +31 -34
  170. package/rollup.config.js +79 -36
  171. package/src/{_escape.js → _escape.ts} +19 -17
  172. package/src/{applyBinding.js → applyBinding.ts} +27 -18
  173. package/src/{attrBinding.js → attrBinding.ts} +14 -13
  174. package/src/{binder.js → binder.ts} +289 -181
  175. package/src/changeBinding.ts +93 -0
  176. package/src/{commentWrapper.js → commentWrapper.ts} +33 -30
  177. package/src/config.ts +107 -0
  178. package/src/{createBindingOption.js → createBindingOption.ts} +39 -15
  179. package/src/createEventBinding.ts +88 -0
  180. package/src/{cssBinding.js → cssBinding.ts} +13 -11
  181. package/src/{domWalker.js → domWalker.ts} +44 -30
  182. package/src/{forOfBinding.js → forOfBinding.ts} +4 -3
  183. package/src/hoverBinding.ts +84 -0
  184. package/src/{ifBinding.js → ifBinding.ts} +14 -12
  185. package/src/index.ts +53 -0
  186. package/src/{modelBinding.js → modelBinding.ts} +11 -9
  187. package/src/{postProcess.js → postProcess.ts} +6 -4
  188. package/src/{pubSub.js → pubSub.ts} +24 -21
  189. package/src/reactiveProxy.ts +285 -0
  190. package/src/{renderForOfBinding.js → renderForOfBinding.ts} +54 -32
  191. package/src/{renderIfBinding.js → renderIfBinding.ts} +41 -19
  192. package/src/{renderIteration.js → renderIteration.ts} +24 -8
  193. package/src/renderTemplate.ts +165 -0
  194. package/src/renderTemplatesBinding.ts +73 -0
  195. package/src/{showBinding.js → showBinding.ts} +4 -3
  196. package/src/{switchBinding.js → switchBinding.ts} +18 -15
  197. package/src/{textBinding.js → textBinding.ts} +5 -4
  198. package/src/types.ts +124 -0
  199. package/src/util.ts +810 -0
  200. package/test/css/reporter.css +9 -9
  201. package/test/globals.d.ts +19 -0
  202. package/test/helpers/testHelper.js +46 -11
  203. package/test/mocks/featureAdsResult.json +65 -65
  204. package/test/mocks/searchResult.json +57 -57
  205. package/test/specs/{attrBinding.spec.js → attrBinding.spec.ts} +103 -106
  206. package/test/specs/{binder.spec.js → binder.spec.ts} +29 -27
  207. package/test/specs/blurBinding.spec.ts +60 -0
  208. package/test/specs/chainableUse.spec.ts +125 -0
  209. package/test/specs/clickBinding.spec.ts +194 -0
  210. package/test/specs/{cssBinding.spec.js → cssBinding.spec.ts} +72 -79
  211. package/test/specs/{dataBindBootstrap.spec.js → dataBindBootstrap.spec.ts} +332 -313
  212. package/test/specs/{filter.spec.js → filter.spec.ts} +75 -76
  213. package/test/specs/{forOfBinding.spec.js → forOfBinding.spec.ts} +208 -219
  214. package/test/specs/formBinding.spec.ts +272 -0
  215. package/test/specs/ifBinding.spec.ts +165 -0
  216. package/test/specs/{nestedComponent.spec.js → nestedComponent.spec.ts} +88 -88
  217. package/test/specs/reactiveProxy.spec.ts +465 -0
  218. package/test/specs/{showBinding.spec.js → showBinding.spec.ts} +148 -149
  219. package/test/specs/{switchBinding.spec.js → switchBinding.spec.ts} +172 -173
  220. package/test/specs/templateBinding.spec.ts +273 -0
  221. package/test/specs/{textBinding.spec.js → textBinding.spec.ts} +47 -48
  222. package/test/tsconfig.json +31 -0
  223. package/test-output.txt +200 -0
  224. package/test-reactive.html +224 -0
  225. package/tsconfig.json +28 -0
  226. package/vendors/lodash.custom.js +4577 -4577
  227. package/vendors/lodash.custom.min.js +45 -45
  228. package/vitest.config.js +27 -0
  229. package/.eslintrc.js +0 -1
  230. package/.grunt/grunt-contrib-jasmine/boot.js +0 -161
  231. package/.grunt/grunt-contrib-jasmine/dist/js/dataBind.js +0 -9
  232. package/.grunt/grunt-contrib-jasmine/grunt-template-jasmine-istanbul/reporter.js +0 -23
  233. package/.grunt/grunt-contrib-jasmine/jasmine-html.js +0 -853
  234. package/.grunt/grunt-contrib-jasmine/jasmine.css +0 -271
  235. package/.grunt/grunt-contrib-jasmine/jasmine.js +0 -9761
  236. package/.grunt/grunt-contrib-jasmine/jasmine_favicon.png +0 -0
  237. package/.grunt/grunt-contrib-jasmine/json2.js +0 -489
  238. package/.grunt/grunt-contrib-jasmine/reporter.js +0 -107
  239. package/coverage/coverage.json +0 -1
  240. package/coverage/lcov/lcov-report/base.css +0 -213
  241. package/coverage/lcov/lcov-report/index.html +0 -93
  242. package/coverage/lcov/lcov-report/js/dataBind.js.html +0 -6596
  243. package/coverage/lcov/lcov-report/js/index.html +0 -93
  244. package/coverage/lcov/lcov-report/prettify.css +0 -1
  245. package/coverage/lcov/lcov-report/prettify.js +0 -1
  246. package/coverage/lcov/lcov-report/sort-arrow-sprite.png +0 -0
  247. package/coverage/lcov/lcov-report/sorter.js +0 -158
  248. package/coverage/lcov/lcov.info +0 -1991
  249. package/eslintrc.json +0 -40
  250. package/examples/bootstrap/js/bootstrap.min.js +0 -6
  251. package/examples/bootstrap/js/popper.min.js +0 -5
  252. package/examples/bootstrap/js/searchSuggestion.js +0 -58
  253. package/examples/bootstrap/js/typeahead.jquery.js +0 -1538
  254. package/gruntfile.js +0 -92
  255. package/gulpfile.js +0 -32
  256. package/src/applyBindingExport.js +0 -5
  257. package/src/changeBinding.js +0 -63
  258. package/src/config.js +0 -66
  259. package/src/createEventBinding.js +0 -46
  260. package/src/eventSystem.js +0 -46
  261. package/src/hoverBinding.js +0 -57
  262. package/src/index.js +0 -26
  263. package/src/renderTemplate.js +0 -128
  264. package/src/renderTemplatesBinding.js +0 -44
  265. package/src/util.js +0 -648
  266. package/test/specs/blurBinding.spec.js +0 -57
  267. package/test/specs/formBinding.spec.js +0 -316
  268. package/test/specs/ifBinding.spec.js +0 -169
  269. package/test/specs/templateBinding.spec.js +0 -117
  270. package/vendors/jasmine-jquery.js +0 -841
  271. package/vendors/jquery-3.2.1.min.js +0 -4
@@ -1,48 +1,47 @@
1
- describe('Given [data-bind-comp="text-component"] inited', () => {
2
- const namespace = {};
3
- const testContent2 = 'text-binding content';
4
-
5
- jasmine.getFixtures().fixturesPath = 'test';
6
-
7
- beforeEach(() => {
8
- loadFixtures('./fixtures/textBinding.html');
9
-
10
- namespace.viewModel = {
11
- heading: 'my text-binding Component',
12
- description: 'test description',
13
- getTextContent: function() {
14
- return testContent2;
15
- },
16
- updateView: function(opt) {
17
- this.APP.render(opt);
18
- },
19
- };
20
-
21
- namespace.myTextComponent = dataBind.init(document.querySelector('[data-bind-comp="text-component"]'), namespace.viewModel);
22
-
23
- namespace.myTextComponent.render();
24
- });
25
-
26
- afterEach(() => {
27
- // clean up all app/components
28
- for (const prop in namespace) {
29
- if (namespace.hasOwnProperty(prop)) {
30
- delete namespace[prop];
31
- }
32
- }
33
- });
34
-
35
- it('Then [data-bind-comp="myTextComponent"] should have render', (done) => {
36
- setTimeout(() => {
37
- const $heading = document.getElementById('text-binding-heading');
38
- const $textBindingContent = document.getElementById('text-binding-content');
39
- const $textBindingContent2 = document.getElementById('text-binding-content2');
40
-
41
- expect($heading.textContent).toBe(namespace.viewModel.heading);
42
- expect($textBindingContent.textContent).toBe(namespace.viewModel.description);
43
- expect($textBindingContent2.textContent).toBe(testContent2);
44
-
45
- done();
46
- }, 200);
47
- });
48
- });
1
+ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
2
+ import {waitFor} from '@testing-library/dom';
3
+
4
+ describe('Given [data-bind-comp="text-component"] inited', () => {
5
+ const namespace: any = {};
6
+ const testContent2 = 'text-binding content';
7
+
8
+ beforeEach(() => {
9
+ loadFixture('test/fixtures/textBinding.html');
10
+
11
+ namespace.viewModel = {
12
+ heading: 'my text-binding Component',
13
+ description: 'test description',
14
+ getTextContent() {
15
+ return testContent2;
16
+ },
17
+ updateView(opt?: any) {
18
+ this.APP.render(opt);
19
+ },
20
+ };
21
+
22
+ namespace.myTextComponent = dataBind.init(document.querySelector('[data-bind-comp="text-component"]'), namespace.viewModel);
23
+
24
+ namespace.myTextComponent.render();
25
+ });
26
+
27
+ afterEach(() => {
28
+ // clean up all app/components
29
+ for (const prop in namespace) {
30
+ if (Object.prototype.hasOwnProperty.call(namespace, prop)) {
31
+ delete namespace[prop];
32
+ }
33
+ }
34
+ });
35
+
36
+ it('Then [data-bind-comp="myTextComponent"] should have render', async () => {
37
+ await waitFor(() => {
38
+ const $heading = document.getElementById('text-binding-heading')!;
39
+ const $textBindingContent = document.getElementById('text-binding-content')!;
40
+ const $textBindingContent2 = document.getElementById('text-binding-content2')!;
41
+
42
+ expect($heading.textContent).toBe(namespace.viewModel.heading);
43
+ expect($textBindingContent.textContent).toBe(namespace.viewModel.description);
44
+ expect($textBindingContent2.textContent).toBe(testContent2);
45
+ }, {timeout: 500});
46
+ });
47
+ });
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2015",
4
+ "module": "ESNext",
5
+ "lib": ["ES2015", "DOM"],
6
+ "strict": false,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "moduleResolution": "node",
11
+ "resolveJsonModule": true,
12
+ "allowSyntheticDefaultImports": true,
13
+ "noUnusedLocals": false,
14
+ "noUnusedParameters": false,
15
+ "noImplicitAny": false,
16
+ "strictNullChecks": false,
17
+ "strictFunctionTypes": false,
18
+ "strictPropertyInitialization": false,
19
+ "noImplicitThis": false,
20
+ "allowJs": true,
21
+ "noEmit": true,
22
+ "types": ["vitest/globals"]
23
+ },
24
+ "include": [
25
+ "./**/*.ts",
26
+ "./globals.d.ts"
27
+ ],
28
+ "exclude": [
29
+ "../node_modules"
30
+ ]
31
+ }
@@ -0,0 +1,200 @@
1
+
2
+ > @gogocat/data-bind@1.12.0 test
3
+ > vitest run
4
+
5
+
6
+ RUN v2.1.9 /Users/adamchow/My-workspace/dataBind
7
+
8
+ ❯ test/specs/switchBinding.spec.js (0 test)
9
+ ❯ test/specs/ifBinding.spec.js (0 test)
10
+ ❯ test/specs/nestedComponent.spec.js (0 test)
11
+ ❯ test/specs/templateBinding.spec.js (0 test)
12
+ ❯ test/specs/showBinding.spec.js (0 test)
13
+ stderr | test/specs/forOfBinding.spec.js > When search-results-component with forOf binding inited > Then [data-bind-comp="search-results-component"] should have render
14
+ error in rendering: TypeError: __vite_ssr_import_1__.default is not a function
15
+ at /Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:33:25
16
+ at Array.forEach (<anonymous>)
17
+ at Module.renderTemplatesBinding [as default] (/Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:32:40)
18
+ at Binder.render (/Users/adamchow/My-workspace/dataBind/src/binder.js:141:31)
19
+ at Timeout._onTimeout (/Users/adamchow/My-workspace/dataBind/src/util.js:365:24)
20
+ at listOnTimeout (node:internal/timers:594:17)
21
+ at processTimers (node:internal/timers:529:7)
22
+
23
+ ✓ test/specs/attrBinding.spec.js (5 tests) 107ms
24
+ ❯ test/specs/dataBindBootstrap.spec.js (5 tests | 5 failed) 75ms
25
+ × Given dataBindBootstrp initised > Then [data-bind-comp="search-bar"] should has bond with namespace.searchBarComponentVM 44ms
26
+ → spyOn is not defined
27
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
28
+ × Given dataBindBootstrp initised > When [data-bind-comp="search-bar"] was server rendered then show binding should not update element 8ms
29
+ → spyOn is not defined
30
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
31
+ × Given dataBindBootstrp initised > When change #searchWord input value to "Handyman" viewModel onSearchWordChange should have been called 6ms
32
+ → spyOn is not defined
33
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
34
+ × Given dataBindBootstrp initised > When change #location input value to "Melbourne" viewModel onSearchLocationChange should have been called 10ms
35
+ → spyOn is not defined
36
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
37
+ × Given dataBindBootstrp initised > When [data-bind-comp="search-bar"] was server rendered "data-server-rendered" attribute should have removed 6ms
38
+ → spyOn is not defined
39
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
40
+ stderr | test/specs/dataBindBootstrap.spec.js
41
+ error in rendering: TypeError: __vite_ssr_import_1__.default is not a function
42
+ at /Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:33:25
43
+ at Array.forEach (<anonymous>)
44
+ at Module.renderTemplatesBinding [as default] (/Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:32:40)
45
+ at Binder.render (/Users/adamchow/My-workspace/dataBind/src/binder.js:141:31)
46
+ at Timeout._onTimeout (/Users/adamchow/My-workspace/dataBind/src/util.js:365:24)
47
+ at listOnTimeout (node:internal/timers:594:17)
48
+ at processTimers (node:internal/timers:529:7)
49
+ error in rendering: TypeError: __vite_ssr_import_1__.default is not a function
50
+ at /Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:33:25
51
+ at Array.forEach (<anonymous>)
52
+ at Module.renderTemplatesBinding [as default] (/Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:32:40)
53
+ at Binder.render (/Users/adamchow/My-workspace/dataBind/src/binder.js:141:31)
54
+ at Timeout._onTimeout (/Users/adamchow/My-workspace/dataBind/src/util.js:365:24)
55
+ at listOnTimeout (node:internal/timers:594:17)
56
+ at processTimers (node:internal/timers:529:7)
57
+ error in rendering: TypeError: __vite_ssr_import_1__.default is not a function
58
+ at /Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:33:25
59
+ at Array.forEach (<anonymous>)
60
+ at Module.renderTemplatesBinding [as default] (/Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:32:40)
61
+ at Binder.render (/Users/adamchow/My-workspace/dataBind/src/binder.js:141:31)
62
+ at Timeout._onTimeout (/Users/adamchow/My-workspace/dataBind/src/util.js:365:24)
63
+ at listOnTimeout (node:internal/timers:594:17)
64
+ at processTimers (node:internal/timers:529:7)
65
+
66
+ stderr | Timeout._onTimeout (/Users/adamchow/My-workspace/dataBind/src/util.js:370:29)
67
+ error in rendering: TypeError: __vite_ssr_import_1__.default is not a function
68
+ at /Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:33:25
69
+ at Array.forEach (<anonymous>)
70
+ at Module.renderTemplatesBinding [as default] (/Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:32:40)
71
+ at Binder.render (/Users/adamchow/My-workspace/dataBind/src/binder.js:141:31)
72
+ at Timeout._onTimeout (/Users/adamchow/My-workspace/dataBind/src/util.js:365:24)
73
+ at listOnTimeout (node:internal/timers:594:17)
74
+ at processTimers (node:internal/timers:529:7)
75
+ error in rendering: TypeError: __vite_ssr_import_1__.default is not a function
76
+ at /Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:33:25
77
+ at Array.forEach (<anonymous>)
78
+ at Module.renderTemplatesBinding [as default] (/Users/adamchow/My-workspace/dataBind/src/renderTemplatesBinding.js:32:40)
79
+ at Binder.render (/Users/adamchow/My-workspace/dataBind/src/binder.js:141:31)
80
+ at Timeout._onTimeout (/Users/adamchow/My-workspace/dataBind/src/util.js:365:24)
81
+ at listOnTimeout (node:internal/timers:594:17)
82
+ at processTimers (node:internal/timers:529:7)
83
+
84
+ ✓ test/specs/binder.spec.js (5 tests) 4ms
85
+ ❯ test/specs/filter.spec.js (3 tests | 3 failed) 18ms
86
+ × Given [data-bind-comp="filter-component"] inited > Then [data-bind-comp="filter-component"] should render story with once filter and not intro 15ms
87
+ → expected <div id="intro" …(2)>…(2)</div> to be null // Object.is equality
88
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
89
+ × Given [data-bind-comp="filter-component"] inited > Should render intro but not story section after update viewModel 2ms
90
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
91
+ × Given [data-bind-comp="filter-component"] inited > Should render story and stroyPrice pass through filters | toDiscount | addGst 1ms
92
+ → Cannot read properties of null (reading 'textContent')
93
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
94
+ ❯ test/specs/blurBinding.spec.js (2 tests | 2 failed) 33ms
95
+ × Given [data-bind-comp="blur-component"] initised > should render heading defined in viewModel 30ms
96
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
97
+ × Given [data-bind-comp="blur-component"] initised > should update "blurInput" value after onBlur 2ms
98
+ → Cannot read properties of undefined (reading 'hasOwnProperty')
99
+ ✓ test/specs/textBinding.spec.js (1 test) 25ms
100
+ ❯ test/specs/forOfBinding.spec.js (4 tests | 1 failed) 532ms
101
+ × When search-results-component with forOf binding inited > Then [data-bind-comp="search-results-component"] should have render 525ms
102
+ → expected '' to be 'Featured service providers' // Object.is equality
103
+
104
+ Ignored nodes: comments, script, style
105
+ <html>
106
+ <head />
107
+ <body>
108
+ <div
109
+ class="container"
110
+ >
111
+ 
112
+ 
113
+ <h5>
114
+ For of binding complex demo
115
+ </h5>
116
+ 
117
+ 
118
+ <div
119
+ class="container search-result"
120
+ data-bind-comp="search-results-component"
121
+ >
122
+ 
123
+ 
124
+ <h4
125
+ class="text-center section-title"
126
+ data-bind-text="searchResultTitle"
127
+ id="searchResultTitle"
128
+ />
129
+ 
130
+ 
131
+ <div
132
+ class="card-columns"
133
+ data-bind-tmp="{id: 'searchResultItem', data: 'searchResults'}"
134
+ id="search-result-columns"
135
+ >
136
+ 
137
+ 
138
+ <div
139
+ class="card result-item"
140
+ data-bind-css="result.highlightCss"
141
+ data-bind-for="result in searchResults"
142
+ >
143
+ 
144
+ 
145
+ <img
146
+ class="card-img-top result-item__img"
147
+ data-bind-attr="$root.getResultItemAttr($index)"
148
+ />
149
+ 
150
+ 
151
+ <div
152
+ class="card-body"
153
+ data-bind-tmp="{id: 'searchResultItemBody', data: 'result'}"
154
+ />
155
+ 
156
+ 
157
+ <div
158
+ data-bind-tmp="{id: 'searchResultItemFooter', data: 'result'}"
159
+ />
160
+ 
161
+ 
162
+ </div>
163
+ 
164
+ 
165
+ </div>
166
+ 
167
+ 
168
+ </div>
169
+ 
170
+ 
171
+ </div>
172
+ 
173
+
174
+ 
175
+ 
176
+ 
177
+ <template
178
+ id="searchResultItem"
179
+ />
180
+ 
181
+
182
+ 
183
+ <template
184
+ id="searchResultItemBody"
185
+ />
186
+ 
187
+
188
+ 
189
+ <template
190
+ id="searchResultItemFooter"
191
+ />
192
+ 
193
+
194
+ 
195
+ <template
196
+ id="searchResultItemBookMark"
197
+ />
198
+ </body>
199
+ </html>
200
+ ❯ test/specs/cssBinding.spec.js (3 tests | 3 failed) 543ms
@@ -0,0 +1,224 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Reactive Proxy Test</title>
5
+ <style>
6
+ body { font-family: Arial; padding: 20px; }
7
+ .test { margin: 10px 0; padding: 10px; border: 1px solid #ddd; }
8
+ .pass { background: #d4edda; }
9
+ .fail { background: #f8d7da; }
10
+ pre { background: #f5f5f5; padding: 10px; }
11
+ </style>
12
+ </head>
13
+ <body>
14
+ <h1>Reactive Proxy Test Suite</h1>
15
+ <div id="results"></div>
16
+
17
+ <script src="dist/js/dataBind.min.js"></script>
18
+ <script>
19
+ const results = [];
20
+
21
+ function test(name, fn) {
22
+ try {
23
+ fn();
24
+ results.push({name, status: 'pass', error: null});
25
+ console.log('✅', name);
26
+ } catch (error) {
27
+ results.push({name, status: 'fail', error: error.message});
28
+ console.error('❌', name, error);
29
+ }
30
+ }
31
+
32
+ let renderCount = 0;
33
+ function resetRenderCount() {
34
+ renderCount = 0;
35
+ }
36
+
37
+ // Test 1: Simple property change
38
+ test('1. Simple property change triggers render', () => {
39
+ resetRenderCount();
40
+ const viewModel = {name: 'John', age: 30};
41
+ const component = dataBind.init(document.createElement('div'), viewModel);
42
+ component.render = () => { renderCount++; };
43
+
44
+ component.viewModel.name = 'Jane';
45
+
46
+ setTimeout(() => {
47
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
48
+ }, 100);
49
+ });
50
+
51
+ // Test 2: Nested object change
52
+ test('2. Nested object property change triggers render', () => {
53
+ resetRenderCount();
54
+ const viewModel = {
55
+ user: {
56
+ profile: {
57
+ name: 'John'
58
+ }
59
+ }
60
+ };
61
+ const component = dataBind.init(document.createElement('div'), viewModel);
62
+ component.render = () => { renderCount++; };
63
+
64
+ component.viewModel.user.profile.name = 'Jane';
65
+
66
+ setTimeout(() => {
67
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
68
+ }, 100);
69
+ });
70
+
71
+ // Test 3: Array push
72
+ test('3. Array push triggers render', () => {
73
+ resetRenderCount();
74
+ const viewModel = {items: [1, 2, 3]};
75
+ const component = dataBind.init(document.createElement('div'), viewModel);
76
+ component.render = () => { renderCount++; };
77
+
78
+ component.viewModel.items.push(4);
79
+
80
+ setTimeout(() => {
81
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
82
+ if (component.viewModel.items.length !== 4) throw new Error('Array length incorrect');
83
+ }, 100);
84
+ });
85
+
86
+ // Test 4: Array pop
87
+ test('4. Array pop triggers render', () => {
88
+ resetRenderCount();
89
+ const viewModel = {items: [1, 2, 3]};
90
+ const component = dataBind.init(document.createElement('div'), viewModel);
91
+ component.render = () => { renderCount++; };
92
+
93
+ component.viewModel.items.pop();
94
+
95
+ setTimeout(() => {
96
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
97
+ if (component.viewModel.items.length !== 2) throw new Error('Array length incorrect');
98
+ }, 100);
99
+ });
100
+
101
+ // Test 5: Array splice
102
+ test('5. Array splice triggers render', () => {
103
+ resetRenderCount();
104
+ const viewModel = {items: [1, 2, 3]};
105
+ const component = dataBind.init(document.createElement('div'), viewModel);
106
+ component.render = () => { renderCount++; };
107
+
108
+ component.viewModel.items.splice(1, 1);
109
+
110
+ setTimeout(() => {
111
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
112
+ }, 100);
113
+ });
114
+
115
+ // Test 6: Array index assignment
116
+ test('6. Array index assignment triggers render', () => {
117
+ resetRenderCount();
118
+ const viewModel = {items: [1, 2, 3]};
119
+ const component = dataBind.init(document.createElement('div'), viewModel);
120
+ component.render = () => { renderCount++; };
121
+
122
+ component.viewModel.items[0] = 99;
123
+
124
+ setTimeout(() => {
125
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
126
+ if (component.viewModel.items[0] !== 99) throw new Error('Value not updated');
127
+ }, 100);
128
+ });
129
+
130
+ // Test 7: Array of objects - modify object property
131
+ test('7. Array of objects - modify object property triggers render', () => {
132
+ resetRenderCount();
133
+ const viewModel = {
134
+ todos: [
135
+ {text: 'Task 1', done: false},
136
+ {text: 'Task 2', done: false}
137
+ ]
138
+ };
139
+ const component = dataBind.init(document.createElement('div'), viewModel);
140
+ component.render = () => { renderCount++; };
141
+
142
+ component.viewModel.todos[0].done = true;
143
+
144
+ setTimeout(() => {
145
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
146
+ if (component.viewModel.todos[0].done !== true) throw new Error('Value not updated');
147
+ }, 100);
148
+ });
149
+
150
+ // Test 8: Array of objects - push new object
151
+ test('8. Array of objects - push new object triggers render', () => {
152
+ resetRenderCount();
153
+ const viewModel = {
154
+ todos: [
155
+ {text: 'Task 1', done: false}
156
+ ]
157
+ };
158
+ const component = dataBind.init(document.createElement('div'), viewModel);
159
+ component.render = () => { renderCount++; };
160
+
161
+ component.viewModel.todos.push({text: 'Task 2', done: false});
162
+
163
+ setTimeout(() => {
164
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
165
+ if (component.viewModel.todos.length !== 2) throw new Error('Array length incorrect');
166
+ }, 100);
167
+ });
168
+
169
+ // Test 9: Deep nested array
170
+ test('9. Deep nested array triggers render', () => {
171
+ resetRenderCount();
172
+ const viewModel = {
173
+ data: {
174
+ lists: {
175
+ items: [1, 2, 3]
176
+ }
177
+ }
178
+ };
179
+ const component = dataBind.init(document.createElement('div'), viewModel);
180
+ component.render = () => { renderCount++; };
181
+
182
+ component.viewModel.data.lists.items.push(4);
183
+
184
+ setTimeout(() => {
185
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
186
+ }, 100);
187
+ });
188
+
189
+ // Test 10: Batch updates (multiple changes = 1 render due to RAF)
190
+ test('10. Multiple changes batched into single render', () => {
191
+ resetRenderCount();
192
+ const viewModel = {name: 'John', age: 30, email: 'john@test.com'};
193
+ const component = dataBind.init(document.createElement('div'), viewModel);
194
+ component.render = () => { renderCount++; };
195
+
196
+ component.viewModel.name = 'Jane';
197
+ component.viewModel.age = 25;
198
+ component.viewModel.email = 'jane@test.com';
199
+
200
+ setTimeout(() => {
201
+ // Should only be 1 render due to RAF debouncing
202
+ if (renderCount !== 1) throw new Error(`Expected 1 render, got ${renderCount}`);
203
+ }, 100);
204
+ });
205
+
206
+ // Display results after all tests
207
+ setTimeout(() => {
208
+ const resultsDiv = document.getElementById('results');
209
+ const passCount = results.filter(r => r.status === 'pass').length;
210
+ const failCount = results.filter(r => r.status === 'fail').length;
211
+
212
+ resultsDiv.innerHTML = `
213
+ <h2>Results: ${passCount} passed, ${failCount} failed</h2>
214
+ ${results.map(r => `
215
+ <div class="test ${r.status}">
216
+ <strong>${r.status === 'pass' ? '✅' : '❌'} ${r.name}</strong>
217
+ ${r.error ? `<pre>${r.error}</pre>` : ''}
218
+ </div>
219
+ `).join('')}
220
+ `;
221
+ }, 200);
222
+ </script>
223
+ </body>
224
+ </html>
package/tsconfig.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2015",
4
+ "module": "ESNext",
5
+ "lib": ["ES2015", "DOM"],
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "outDir": "./dist/types",
9
+ "rootDir": "./src",
10
+ "strict": false,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "moduleResolution": "node",
15
+ "resolveJsonModule": true,
16
+ "allowSyntheticDefaultImports": true,
17
+ "noUnusedLocals": false,
18
+ "noUnusedParameters": false,
19
+ "noImplicitAny": false,
20
+ "strictNullChecks": false,
21
+ "strictFunctionTypes": false,
22
+ "strictPropertyInitialization": false,
23
+ "noImplicitThis": false,
24
+ "allowJs": true
25
+ },
26
+ "include": ["src/**/*"],
27
+ "exclude": ["node_modules", "dist", "test"]
28
+ }