@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.
- package/.editorconfig +14 -14
- package/.vscode/launch.json +12 -12
- package/CONFIGURATION.md +294 -0
- package/REACTIVE_MODE.md +553 -0
- package/README.md +266 -829
- package/babel.config.json +30 -0
- package/dist/js/_escape.d.ts +14 -0
- package/dist/js/_escape.d.ts.map +1 -0
- package/dist/js/applyBinding.d.ts +11 -0
- package/dist/js/applyBinding.d.ts.map +1 -0
- package/dist/js/attrBinding.d.ts +12 -0
- package/dist/js/attrBinding.d.ts.map +1 -0
- package/dist/js/binder.d.ts +67 -0
- package/dist/js/binder.d.ts.map +1 -0
- package/dist/js/changeBinding.d.ts +19 -0
- package/dist/js/changeBinding.d.ts.map +1 -0
- package/dist/js/commentWrapper.d.ts +39 -0
- package/dist/js/commentWrapper.d.ts.map +1 -0
- package/dist/js/config.d.ts +55 -0
- package/dist/js/config.d.ts.map +1 -0
- package/dist/js/createBindingOption.d.ts +32 -0
- package/dist/js/createBindingOption.d.ts.map +1 -0
- package/dist/js/createEventBinding.d.ts +10 -0
- package/dist/js/createEventBinding.d.ts.map +1 -0
- package/dist/js/cssBinding.d.ts +15 -0
- package/dist/js/cssBinding.d.ts.map +1 -0
- package/dist/js/dataBind.js +2756 -2530
- package/dist/js/dataBind.min.js +8 -1
- package/dist/js/dataBind.min.js.map +1 -1
- package/dist/js/domWalker.d.ts +9 -0
- package/dist/js/domWalker.d.ts.map +1 -0
- package/dist/js/forOfBinding.d.ts +12 -0
- package/dist/js/forOfBinding.d.ts.map +1 -0
- package/dist/js/hoverBinding.d.ts +13 -0
- package/dist/js/hoverBinding.d.ts.map +1 -0
- package/dist/js/ifBinding.d.ts +12 -0
- package/dist/js/ifBinding.d.ts.map +1 -0
- package/dist/js/index.d.ts +10 -0
- package/dist/js/index.d.ts.map +1 -0
- package/dist/js/modelBinding.d.ts +12 -0
- package/dist/js/modelBinding.d.ts.map +1 -0
- package/dist/js/postProcess.d.ts +3 -0
- package/dist/js/postProcess.d.ts.map +1 -0
- package/dist/js/pubSub.d.ts +11 -0
- package/dist/js/pubSub.d.ts.map +1 -0
- package/dist/js/reactiveProxy.d.ts +28 -0
- package/dist/js/reactiveProxy.d.ts.map +1 -0
- package/dist/js/renderForOfBinding.d.ts +8 -0
- package/dist/js/renderForOfBinding.d.ts.map +1 -0
- package/dist/js/renderIfBinding.d.ts +22 -0
- package/dist/js/renderIfBinding.d.ts.map +1 -0
- package/dist/js/renderIteration.d.ts +16 -0
- package/dist/js/renderIteration.d.ts.map +1 -0
- package/dist/js/renderTemplate.d.ts +14 -0
- package/dist/js/renderTemplate.d.ts.map +1 -0
- package/dist/js/renderTemplatesBinding.d.ts +19 -0
- package/dist/js/renderTemplatesBinding.d.ts.map +1 -0
- package/dist/js/showBinding.d.ts +13 -0
- package/dist/js/showBinding.d.ts.map +1 -0
- package/dist/js/switchBinding.d.ts +13 -0
- package/dist/js/switchBinding.d.ts.map +1 -0
- package/dist/js/textBinding.d.ts +13 -0
- package/dist/js/textBinding.d.ts.map +1 -0
- package/dist/js/types/_escape.d.ts +14 -0
- package/dist/js/types/_escape.d.ts.map +1 -0
- package/dist/js/types/applyBinding.d.ts +11 -0
- package/dist/js/types/applyBinding.d.ts.map +1 -0
- package/dist/js/types/attrBinding.d.ts +12 -0
- package/dist/js/types/attrBinding.d.ts.map +1 -0
- package/dist/js/types/binder.d.ts +67 -0
- package/dist/js/types/binder.d.ts.map +1 -0
- package/dist/js/types/changeBinding.d.ts +19 -0
- package/dist/js/types/changeBinding.d.ts.map +1 -0
- package/dist/js/types/commentWrapper.d.ts +39 -0
- package/dist/js/types/commentWrapper.d.ts.map +1 -0
- package/dist/js/types/config.d.ts +55 -0
- package/dist/js/types/config.d.ts.map +1 -0
- package/dist/js/types/createBindingOption.d.ts +32 -0
- package/dist/js/types/createBindingOption.d.ts.map +1 -0
- package/dist/js/types/createEventBinding.d.ts +10 -0
- package/dist/js/types/createEventBinding.d.ts.map +1 -0
- package/dist/js/types/cssBinding.d.ts +15 -0
- package/dist/js/types/cssBinding.d.ts.map +1 -0
- package/dist/js/types/domWalker.d.ts +9 -0
- package/dist/js/types/domWalker.d.ts.map +1 -0
- package/dist/js/types/forOfBinding.d.ts +12 -0
- package/dist/js/types/forOfBinding.d.ts.map +1 -0
- package/dist/js/types/hoverBinding.d.ts +13 -0
- package/dist/js/types/hoverBinding.d.ts.map +1 -0
- package/dist/js/types/ifBinding.d.ts +12 -0
- package/dist/js/types/ifBinding.d.ts.map +1 -0
- package/dist/js/types/index.d.ts +10 -0
- package/dist/js/types/index.d.ts.map +1 -0
- package/dist/js/types/modelBinding.d.ts +12 -0
- package/dist/js/types/modelBinding.d.ts.map +1 -0
- package/dist/js/types/postProcess.d.ts +3 -0
- package/dist/js/types/postProcess.d.ts.map +1 -0
- package/dist/js/types/pubSub.d.ts +11 -0
- package/dist/js/types/pubSub.d.ts.map +1 -0
- package/dist/js/types/reactiveProxy.d.ts +28 -0
- package/dist/js/types/reactiveProxy.d.ts.map +1 -0
- package/dist/js/types/renderForOfBinding.d.ts +8 -0
- package/dist/js/types/renderForOfBinding.d.ts.map +1 -0
- package/dist/js/types/renderIfBinding.d.ts +22 -0
- package/dist/js/types/renderIfBinding.d.ts.map +1 -0
- package/dist/js/types/renderIteration.d.ts +16 -0
- package/dist/js/types/renderIteration.d.ts.map +1 -0
- package/dist/js/types/renderTemplate.d.ts +14 -0
- package/dist/js/types/renderTemplate.d.ts.map +1 -0
- package/dist/js/types/renderTemplatesBinding.d.ts +19 -0
- package/dist/js/types/renderTemplatesBinding.d.ts.map +1 -0
- package/dist/js/types/showBinding.d.ts +13 -0
- package/dist/js/types/showBinding.d.ts.map +1 -0
- package/dist/js/types/switchBinding.d.ts +13 -0
- package/dist/js/types/switchBinding.d.ts.map +1 -0
- package/dist/js/types/textBinding.d.ts +13 -0
- package/dist/js/types/textBinding.d.ts.map +1 -0
- package/dist/js/types/types.d.ts +111 -0
- package/dist/js/types/types.d.ts.map +1 -0
- package/dist/js/types/util.d.ts +119 -0
- package/dist/js/types/util.d.ts.map +1 -0
- package/dist/js/types.d.ts +111 -0
- package/dist/js/types.d.ts.map +1 -0
- package/dist/js/util.d.ts +119 -0
- package/dist/js/util.d.ts.map +1 -0
- package/eslint.config.js +124 -0
- package/examples/DBMONSTER_COMPARISON.md +123 -0
- package/examples/afterRenderDemo.html +119 -0
- package/examples/bootstrap/css/animate.css +1579 -1579
- package/examples/bootstrap/css/bootstrap.min.css +6 -6
- package/examples/bootstrap/css/homeservices.css +378 -390
- package/examples/bootstrap/css/open-iconic.css +511 -511
- package/examples/bootstrap/fonts/open-iconic.svg +543 -543
- package/examples/bootstrap/js/compMessageDialog.js +20 -19
- package/examples/bootstrap/js/compSearchBar.js +12 -19
- package/examples/bootstrap/js/compSearchResults.js +50 -46
- package/examples/bootstrap/js/featureAdsResult.json +65 -65
- package/examples/bootstrap/js/searchResult.json +57 -57
- package/examples/bootstrap.html +343 -332
- package/examples/css/baseTodo.css +141 -141
- package/examples/css/dbMonsterStyles.css +27 -27
- package/examples/css/indexTodo.css +374 -374
- package/examples/dbmonsterForOfReactive.html +40 -0
- package/examples/dbmonsterReact.html +19 -0
- package/examples/forOfBindingSimpleDebug.html +45 -0
- package/examples/globalConfig.html +131 -0
- package/examples/js/afterRenderDemo.js +190 -0
- package/examples/js/appTodo.js +46 -46
- package/examples/js/attrBindingDemo.js +2 -2
- package/examples/js/dbMonApp.js +24 -26
- package/examples/js/dbMonAppReact.jsx +79 -0
- package/examples/js/dbMonAppReactive.js +28 -0
- package/examples/js/fiberDemo.js +4 -4
- package/examples/js/filtersDemo.js +8 -8
- package/examples/js/forOfDemo.js +7 -9
- package/examples/js/forOfDemoComplex.js +44 -17
- package/examples/js/form.js +14 -14
- package/examples/js/globalConfig.js +117 -0
- package/examples/js/ifBindingDemo.js +16 -16
- package/examples/js/reactiveDemo.js +119 -0
- package/examples/js/switchBindingDemo.js +8 -8
- package/examples/react-dbmonster/dist/bundle.js +43 -0
- package/examples/react-dbmonster/package-lock.json +537 -0
- package/examples/react-dbmonster/package.json +16 -0
- package/examples/react-dbmonster/src/index.jsx +80 -0
- package/examples/reactiveDemo.html +127 -0
- package/examples/refreshRateTest.html +75 -75
- package/index.html +841 -0
- package/package.json +31 -34
- package/rollup.config.js +79 -36
- package/src/{_escape.js → _escape.ts} +19 -17
- package/src/{applyBinding.js → applyBinding.ts} +27 -18
- package/src/{attrBinding.js → attrBinding.ts} +14 -13
- package/src/{binder.js → binder.ts} +289 -181
- package/src/changeBinding.ts +93 -0
- package/src/{commentWrapper.js → commentWrapper.ts} +33 -30
- package/src/config.ts +107 -0
- package/src/{createBindingOption.js → createBindingOption.ts} +39 -15
- package/src/createEventBinding.ts +88 -0
- package/src/{cssBinding.js → cssBinding.ts} +13 -11
- package/src/{domWalker.js → domWalker.ts} +44 -30
- package/src/{forOfBinding.js → forOfBinding.ts} +4 -3
- package/src/hoverBinding.ts +84 -0
- package/src/{ifBinding.js → ifBinding.ts} +14 -12
- package/src/index.ts +53 -0
- package/src/{modelBinding.js → modelBinding.ts} +11 -9
- package/src/{postProcess.js → postProcess.ts} +6 -4
- package/src/{pubSub.js → pubSub.ts} +24 -21
- package/src/reactiveProxy.ts +285 -0
- package/src/{renderForOfBinding.js → renderForOfBinding.ts} +54 -32
- package/src/{renderIfBinding.js → renderIfBinding.ts} +41 -19
- package/src/{renderIteration.js → renderIteration.ts} +24 -8
- package/src/renderTemplate.ts +165 -0
- package/src/renderTemplatesBinding.ts +73 -0
- package/src/{showBinding.js → showBinding.ts} +4 -3
- package/src/{switchBinding.js → switchBinding.ts} +18 -15
- package/src/{textBinding.js → textBinding.ts} +5 -4
- package/src/types.ts +124 -0
- package/src/util.ts +810 -0
- package/test/css/reporter.css +9 -9
- package/test/globals.d.ts +19 -0
- package/test/helpers/testHelper.js +46 -11
- package/test/mocks/featureAdsResult.json +65 -65
- package/test/mocks/searchResult.json +57 -57
- package/test/specs/{attrBinding.spec.js → attrBinding.spec.ts} +103 -106
- package/test/specs/{binder.spec.js → binder.spec.ts} +29 -27
- package/test/specs/blurBinding.spec.ts +60 -0
- package/test/specs/chainableUse.spec.ts +125 -0
- package/test/specs/clickBinding.spec.ts +194 -0
- package/test/specs/{cssBinding.spec.js → cssBinding.spec.ts} +72 -79
- package/test/specs/{dataBindBootstrap.spec.js → dataBindBootstrap.spec.ts} +332 -313
- package/test/specs/{filter.spec.js → filter.spec.ts} +75 -76
- package/test/specs/{forOfBinding.spec.js → forOfBinding.spec.ts} +208 -219
- package/test/specs/formBinding.spec.ts +272 -0
- package/test/specs/ifBinding.spec.ts +165 -0
- package/test/specs/{nestedComponent.spec.js → nestedComponent.spec.ts} +88 -88
- package/test/specs/reactiveProxy.spec.ts +465 -0
- package/test/specs/{showBinding.spec.js → showBinding.spec.ts} +148 -149
- package/test/specs/{switchBinding.spec.js → switchBinding.spec.ts} +172 -173
- package/test/specs/templateBinding.spec.ts +273 -0
- package/test/specs/{textBinding.spec.js → textBinding.spec.ts} +47 -48
- package/test/tsconfig.json +31 -0
- package/test-output.txt +200 -0
- package/test-reactive.html +224 -0
- package/tsconfig.json +28 -0
- package/vendors/lodash.custom.js +4577 -4577
- package/vendors/lodash.custom.min.js +45 -45
- package/vitest.config.js +27 -0
- package/.eslintrc.js +0 -1
- package/.grunt/grunt-contrib-jasmine/boot.js +0 -161
- package/.grunt/grunt-contrib-jasmine/dist/js/dataBind.js +0 -9
- package/.grunt/grunt-contrib-jasmine/grunt-template-jasmine-istanbul/reporter.js +0 -23
- package/.grunt/grunt-contrib-jasmine/jasmine-html.js +0 -853
- package/.grunt/grunt-contrib-jasmine/jasmine.css +0 -271
- package/.grunt/grunt-contrib-jasmine/jasmine.js +0 -9761
- package/.grunt/grunt-contrib-jasmine/jasmine_favicon.png +0 -0
- package/.grunt/grunt-contrib-jasmine/json2.js +0 -489
- package/.grunt/grunt-contrib-jasmine/reporter.js +0 -107
- package/coverage/coverage.json +0 -1
- package/coverage/lcov/lcov-report/base.css +0 -213
- package/coverage/lcov/lcov-report/index.html +0 -93
- package/coverage/lcov/lcov-report/js/dataBind.js.html +0 -6596
- package/coverage/lcov/lcov-report/js/index.html +0 -93
- package/coverage/lcov/lcov-report/prettify.css +0 -1
- package/coverage/lcov/lcov-report/prettify.js +0 -1
- package/coverage/lcov/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov/lcov-report/sorter.js +0 -158
- package/coverage/lcov/lcov.info +0 -1991
- package/eslintrc.json +0 -40
- package/examples/bootstrap/js/bootstrap.min.js +0 -6
- package/examples/bootstrap/js/popper.min.js +0 -5
- package/examples/bootstrap/js/searchSuggestion.js +0 -58
- package/examples/bootstrap/js/typeahead.jquery.js +0 -1538
- package/gruntfile.js +0 -92
- package/gulpfile.js +0 -32
- package/src/applyBindingExport.js +0 -5
- package/src/changeBinding.js +0 -63
- package/src/config.js +0 -66
- package/src/createEventBinding.js +0 -46
- package/src/eventSystem.js +0 -46
- package/src/hoverBinding.js +0 -57
- package/src/index.js +0 -26
- package/src/renderTemplate.js +0 -128
- package/src/renderTemplatesBinding.js +0 -44
- package/src/util.js +0 -648
- package/test/specs/blurBinding.spec.js +0 -57
- package/test/specs/formBinding.spec.js +0 -316
- package/test/specs/ifBinding.spec.js +0 -169
- package/test/specs/templateBinding.spec.js +0 -117
- package/vendors/jasmine-jquery.js +0 -841
- package/vendors/jquery-3.2.1.min.js +0 -4
|
@@ -1,173 +1,172 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{title: '
|
|
39
|
-
{title: 'The
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('Should render only switch default case', (
|
|
93
|
-
|
|
94
|
-
// check child non switch binding element still exists
|
|
95
|
-
expect(document.getElementById('switch-component-heading')
|
|
96
|
-
|
|
97
|
-
expect(document.getElementById('default-case')).toBeDefined();
|
|
98
|
-
expect(document.getElementById('case1')).toBe(null);
|
|
99
|
-
expect(document.getElementById('case2')).toBe(null);
|
|
100
|
-
expect(document.getElementById('case3')).toBe(null);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
it('When selectedStory = s1 it then should render case1', (
|
|
106
|
-
namespace.viewModel.onSelectedStory('s1');
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const $
|
|
111
|
-
const $
|
|
112
|
-
const $
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
expect($
|
|
121
|
-
expect($
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
expect(document.getElementById('
|
|
125
|
-
expect(document.getElementById('
|
|
126
|
-
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const $
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
expect($
|
|
145
|
-
|
|
146
|
-
expect(
|
|
147
|
-
|
|
148
|
-
expect(document.getElementById('
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const $defaultCase = document.getElementById('default-case')
|
|
158
|
-
const $defaultCaseTextContent = $defaultCase.querySelector('p')
|
|
159
|
-
const defatulCaseText = 'No story found...';
|
|
160
|
-
|
|
161
|
-
// check child non switch binding element still exists
|
|
162
|
-
expect(document.getElementById('switch-component-heading')
|
|
163
|
-
|
|
164
|
-
// check other binding within this switch binding
|
|
165
|
-
expect($defaultCase).toBeDefined();
|
|
166
|
-
expect($defaultCaseTextContent).toBe(defatulCaseText);
|
|
167
|
-
expect(document.getElementById('case1')).toBe(null);
|
|
168
|
-
expect(document.getElementById('case2')).toBe(null);
|
|
169
|
-
expect(document.getElementById('case3')).toBe(null);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
});
|
|
1
|
+
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
2
|
+
import {waitFor} from '@testing-library/dom';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
describe('Given [data-bind-comp="switch-component"] inited', () => {
|
|
6
|
+
const namespace: any = {};
|
|
7
|
+
|
|
8
|
+
// stories data
|
|
9
|
+
const storiesData: any = {
|
|
10
|
+
s1: {
|
|
11
|
+
title: 'Hansel and Gretel',
|
|
12
|
+
pic:
|
|
13
|
+
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRLxVHKpB93yhxRUb8Wbc1NkUA4Nf8QBMPieKeeL1ugcZivy82INw',
|
|
14
|
+
description:
|
|
15
|
+
'"Hansel and Gretel" (also known as Hansel and Grettel, Hansel and Grethel, or Little Brother and Little Sister) is a well-known fairy tale of German origin, recorded by the Brothers Grimm and published in 1812. Hansel and Gretel are a young brother and sister kidnapped by a cannibalistic witch living deep in the forest in a house constructed of cake and confectionery. The two children escape with their lives by outwitting her. The tale has been adapted to various media, most notably the opera Hänsel und Gretel (1893) by Engelbert Humperdinck. Under the Aarne–Thompson classification system, "Hansel and Gretel" is classified under Class 327.',
|
|
16
|
+
},
|
|
17
|
+
s2: {
|
|
18
|
+
title: 'The Ugly Duckling',
|
|
19
|
+
description:
|
|
20
|
+
'"The Ugly Duckling" (Danish: Den grimme ælling) is a literary fairy tale by Danish poet and author Hans Christian Andersen (1805–1875). The story tells of a homely little bird born in a barnyard who suffers abuse from the others around him until, much to his delight (and to the surprise of others), he matures into a beautiful swan, the most beautiful bird of all. The story is beloved around the world as a tale about personal transformation for the better. "The Ugly Duckling" was first published 11 November 1843, with three other tales by Andersen in Copenhagen, Denmark to great critical acclaim. The tale has been adapted to various media including opera, musical, and animated film. The tale is completely Andersen\'s invention and owes no debt to fairy tales or folklore.',
|
|
21
|
+
},
|
|
22
|
+
s3: {
|
|
23
|
+
title: 'The Giving Tree',
|
|
24
|
+
pic: 'https://images-na.ssl-images-amazon.com/images/I/51EDtk%2B1rNL._SX384_BO1,204,203,200_.jpg',
|
|
25
|
+
description:
|
|
26
|
+
'Published by Harper and Row in 1964, The Giving Tree is a children\'s book written and demonstrated by an American author of children\'s books Shel Silverstein. It was one of Silverstein\'s best children books that has been translated into over 30 languages.',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
beforeEach(async () => {
|
|
31
|
+
loadFixture('test/fixtures/switchBinding.html');
|
|
32
|
+
|
|
33
|
+
namespace.viewModel = {
|
|
34
|
+
heading: 'This heading is inside switch binding',
|
|
35
|
+
selectedStory: '',
|
|
36
|
+
story: {},
|
|
37
|
+
storyOptions: [
|
|
38
|
+
{title: 'Hansel and Gretel', value: 's1'},
|
|
39
|
+
{title: 'The Ugly Duckling', value: 's2'},
|
|
40
|
+
{title: 'The Giving Tree', value: 's3'},
|
|
41
|
+
],
|
|
42
|
+
onSelectedStory(newValue: string) {
|
|
43
|
+
const id = newValue;
|
|
44
|
+
|
|
45
|
+
if (storiesData[id] && id !== this.selectedStory) {
|
|
46
|
+
this.story = storiesData[id];
|
|
47
|
+
this.selectedStory = id;
|
|
48
|
+
} else {
|
|
49
|
+
this.story = {};
|
|
50
|
+
this.selectedStory = '';
|
|
51
|
+
}
|
|
52
|
+
this.updateView();
|
|
53
|
+
},
|
|
54
|
+
setStoryImgAttr() {
|
|
55
|
+
const picPath = this.story.pic || '';
|
|
56
|
+
const ret: any = {
|
|
57
|
+
alt: this.story.title,
|
|
58
|
+
width: 100,
|
|
59
|
+
height: 'auto',
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (picPath) {
|
|
63
|
+
ret.src = picPath;
|
|
64
|
+
}
|
|
65
|
+
return ret;
|
|
66
|
+
},
|
|
67
|
+
updateView(opt?: any) {
|
|
68
|
+
this.APP.render(opt);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
namespace.mySwitchComponent = dataBind.init(document.querySelector('[data-bind-comp="switch-component"]'), namespace.viewModel);
|
|
73
|
+
|
|
74
|
+
await namespace.mySwitchComponent.render();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
afterEach(() => {
|
|
78
|
+
// clean up all app/components
|
|
79
|
+
for (const prop in namespace) {
|
|
80
|
+
if (Object.prototype.hasOwnProperty.call(namespace, prop)) {
|
|
81
|
+
delete namespace[prop];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('Then [data-bind-comp="mySwitchComponent"] should have render', async () => {
|
|
87
|
+
await waitFor(() => {
|
|
88
|
+
expect(document.getElementById('switch-component-heading')!.textContent).toBe(namespace.viewModel.heading);
|
|
89
|
+
}, {timeout: 500});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('Should render only switch default case', async () => {
|
|
93
|
+
await waitFor(() => {
|
|
94
|
+
// check child non switch binding element still exists
|
|
95
|
+
expect(document.getElementById('switch-component-heading')!.textContent).toBe(namespace.viewModel.heading);
|
|
96
|
+
|
|
97
|
+
expect(document.getElementById('default-case')).toBeDefined();
|
|
98
|
+
expect(document.getElementById('case1')).toBe(null);
|
|
99
|
+
expect(document.getElementById('case2')).toBe(null);
|
|
100
|
+
expect(document.getElementById('case3')).toBe(null);
|
|
101
|
+
}, {timeout: 500});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
it('When selectedStory = s1 it then should render case1', async () => {
|
|
106
|
+
namespace.viewModel.onSelectedStory('s1');
|
|
107
|
+
await namespace.mySwitchComponent.render();
|
|
108
|
+
|
|
109
|
+
await waitFor(() => {
|
|
110
|
+
const $case1 = document.getElementById('case1')!;
|
|
111
|
+
const $storyTitle = $case1.querySelector('h4')!;
|
|
112
|
+
const $storyImg = $case1.querySelector('img') as HTMLImageElement;
|
|
113
|
+
const $storyDescription = $case1.querySelector('p')!;
|
|
114
|
+
|
|
115
|
+
// check child non switch binding element still exists
|
|
116
|
+
expect(document.getElementById('switch-component-heading')!.textContent).toBe(namespace.viewModel.heading);
|
|
117
|
+
|
|
118
|
+
expect($case1).toBeDefined();
|
|
119
|
+
// check other binding within this switch binding
|
|
120
|
+
expect($storyTitle.textContent).toBe(storiesData.s1.title);
|
|
121
|
+
expect($storyImg.getAttribute('src')).toBe(storiesData.s1.pic);
|
|
122
|
+
expect($storyDescription.textContent).toBe(storiesData.s1.description);
|
|
123
|
+
|
|
124
|
+
expect(document.getElementById('case2')).toBe(null);
|
|
125
|
+
expect(document.getElementById('case3')).toBe(null);
|
|
126
|
+
expect(document.getElementById('default-case')).toBe(null);
|
|
127
|
+
}, {timeout: 500});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
it('When selectedStory = s2 it then should render case2 without image', async () => {
|
|
132
|
+
namespace.viewModel.onSelectedStory('s2');
|
|
133
|
+
await namespace.mySwitchComponent.render();
|
|
134
|
+
|
|
135
|
+
await waitFor(() => {
|
|
136
|
+
const $case2 = document.getElementById('case2')!;
|
|
137
|
+
const $storyTitle = $case2.querySelector('h4')!;
|
|
138
|
+
const $storyDescription = $case2.querySelector('p')!;
|
|
139
|
+
|
|
140
|
+
// check child non switch binding element still exists
|
|
141
|
+
expect(document.getElementById('switch-component-heading')!.textContent).toBe(namespace.viewModel.heading);
|
|
142
|
+
|
|
143
|
+
// check other binding within this switch binding
|
|
144
|
+
expect($storyTitle.textContent).toBe(storiesData.s2.title);
|
|
145
|
+
// expect($storyImg).toBe(null);
|
|
146
|
+
expect($storyDescription.textContent).toBe(storiesData.s2.description);
|
|
147
|
+
|
|
148
|
+
expect(document.getElementById('case1')).toBe(null);
|
|
149
|
+
expect(document.getElementById('case3')).toBe(null);
|
|
150
|
+
expect(document.getElementById('default-case')).toBe(null);
|
|
151
|
+
}, {timeout: 500});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
it('When selectedStory non exists it then should render default case', async () => {
|
|
156
|
+
await waitFor(() => {
|
|
157
|
+
const $defaultCase = document.getElementById('default-case')!;
|
|
158
|
+
const $defaultCaseTextContent = $defaultCase.querySelector('p')!.textContent;
|
|
159
|
+
const defatulCaseText = 'No story found...';
|
|
160
|
+
|
|
161
|
+
// check child non switch binding element still exists
|
|
162
|
+
expect(document.getElementById('switch-component-heading')!.textContent).toBe(namespace.viewModel.heading);
|
|
163
|
+
|
|
164
|
+
// check other binding within this switch binding
|
|
165
|
+
expect($defaultCase).toBeDefined();
|
|
166
|
+
expect($defaultCaseTextContent).toBe(defatulCaseText);
|
|
167
|
+
expect(document.getElementById('case1')).toBe(null);
|
|
168
|
+
expect(document.getElementById('case2')).toBe(null);
|
|
169
|
+
expect(document.getElementById('case3')).toBe(null);
|
|
170
|
+
}, {timeout: 500});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
2
|
+
import {waitFor} from '@testing-library/dom';
|
|
3
|
+
|
|
4
|
+
describe('Given [data-bind-comp="temp-component"] inited', () => {
|
|
5
|
+
const namespace: any = {};
|
|
6
|
+
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
loadFixture('test/fixtures/templateBinding.html');
|
|
9
|
+
|
|
10
|
+
namespace.finishTemplateRender = 0;
|
|
11
|
+
|
|
12
|
+
namespace.viewModel = {
|
|
13
|
+
heading: 'Test data-bind-temp binding',
|
|
14
|
+
description: 'This is template binding that also support underscore syntax',
|
|
15
|
+
content: 'test text',
|
|
16
|
+
contentNest1: {
|
|
17
|
+
info: 'Nested content 1',
|
|
18
|
+
},
|
|
19
|
+
contentNest2: {
|
|
20
|
+
info: 'Nested content 2',
|
|
21
|
+
},
|
|
22
|
+
contentNest3: {
|
|
23
|
+
info: 'Nested content 3',
|
|
24
|
+
},
|
|
25
|
+
afterTemplateRender() {
|
|
26
|
+
namespace.finishTemplateRender += 1;
|
|
27
|
+
},
|
|
28
|
+
updateView(opt?: any) {
|
|
29
|
+
this.APP.render(opt);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
namespace.myComponent = dataBind.init(document.querySelector('[data-bind-comp="temp-component"]'), namespace.viewModel);
|
|
34
|
+
|
|
35
|
+
await namespace.myComponent.render();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
// clean up all app/components
|
|
40
|
+
for (const prop in namespace) {
|
|
41
|
+
if (Object.prototype.hasOwnProperty.call(namespace, prop)) {
|
|
42
|
+
delete namespace[prop];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('Then [data-bind-comp="temp-component"] should have render', async () => {
|
|
48
|
+
await waitFor(() => {
|
|
49
|
+
expect(document.getElementById('heading')!.textContent).toBe(namespace.viewModel.heading);
|
|
50
|
+
// afterTemplateRender is called once per template completion
|
|
51
|
+
// With nested templates now working, it's called multiple times
|
|
52
|
+
expect(namespace.finishTemplateRender).toBeGreaterThan(0);
|
|
53
|
+
}, {timeout: 500});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('Should render template1 with viewModel data', async () => {
|
|
57
|
+
await waitFor(() => {
|
|
58
|
+
const viewModel = namespace.viewModel;
|
|
59
|
+
const $compSection = document.getElementById('compSection')!;
|
|
60
|
+
const $heading = document.getElementById('heading')!;
|
|
61
|
+
const $description = document.getElementById('description')!;
|
|
62
|
+
const $content = document.getElementById('content')!;
|
|
63
|
+
const $contentNest1 = document.getElementById('contentNest1')!;
|
|
64
|
+
|
|
65
|
+
expect($compSection.children.length).not.toBe(0);
|
|
66
|
+
expect($heading.textContent).toBe(viewModel.heading);
|
|
67
|
+
expect($description.textContent).toBe(viewModel.description);
|
|
68
|
+
expect($content.textContent).toBe(viewModel.content);
|
|
69
|
+
expect($contentNest1.children.length).not.toBe(0);
|
|
70
|
+
}, {timeout: 500});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
it('Should render nested templates with standard dataBindings', async () => {
|
|
75
|
+
await waitFor(() => {
|
|
76
|
+
const viewModel = namespace.viewModel;
|
|
77
|
+
const $compSection = document.getElementById('compSection')!;
|
|
78
|
+
const $contentNest1 = $compSection.querySelector('#contentNest1')!;
|
|
79
|
+
const $contentNest1Info = $compSection.querySelector('#contentNest1Info')!;
|
|
80
|
+
const $nestPrepend = $compSection.querySelector('#nestPrepend')!;
|
|
81
|
+
const $nestAppend = $compSection.querySelector('#nestAppend')!;
|
|
82
|
+
|
|
83
|
+
expect($contentNest1.children.length).not.toBe(0);
|
|
84
|
+
expect($contentNest1Info.textContent).toBe(viewModel.contentNest1.info);
|
|
85
|
+
expect($nestPrepend.children.length).toBeGreaterThan(1);
|
|
86
|
+
expect($nestAppend.children.length).toBeGreaterThan(1);
|
|
87
|
+
}, {timeout: 2000});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
it('Should render nested template prepend option', async () => {
|
|
92
|
+
await waitFor(() => {
|
|
93
|
+
const viewModel = namespace.viewModel;
|
|
94
|
+
const $compSection = document.getElementById('compSection')!;
|
|
95
|
+
const $nestPrepend = $compSection.querySelector('#nestPrepend')!;
|
|
96
|
+
const $nestPrependHeading = $compSection.querySelector('#nestPrependHeading');
|
|
97
|
+
const $contentNest2Info = $compSection.querySelector('#contentNest2Info')!;
|
|
98
|
+
|
|
99
|
+
expect($nestPrepend.children.length).toBeGreaterThan(1);
|
|
100
|
+
expect($nestPrependHeading).not.toBe(null);
|
|
101
|
+
expect($nestPrependHeading!.previousElementSibling).toBe($contentNest2Info);
|
|
102
|
+
expect($contentNest2Info.textContent).toBe(viewModel.contentNest2.info);
|
|
103
|
+
}, {timeout: 2000});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
it('Should render nested template append option', async () => {
|
|
108
|
+
await waitFor(() => {
|
|
109
|
+
const viewModel = namespace.viewModel;
|
|
110
|
+
const $compSection = document.getElementById('compSection')!;
|
|
111
|
+
const $nestAppend = $compSection.querySelector('#nestAppend')!;
|
|
112
|
+
const $nestAppendHeading = $compSection.querySelector('#nestAppendHeading');
|
|
113
|
+
const $contentNest3Info = $compSection.querySelector('#contentNest3Info')!;
|
|
114
|
+
|
|
115
|
+
expect($nestAppend.children.length).toBeGreaterThan(1);
|
|
116
|
+
expect($nestAppendHeading).not.toBe(null);
|
|
117
|
+
expect($nestAppendHeading!.nextElementSibling).toBe($contentNest3Info);
|
|
118
|
+
expect($contentNest3Info.textContent).toBe(viewModel.contentNest3.info);
|
|
119
|
+
}, {timeout: 2000});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('Should perform minimal DOM updates on re-render (preserve unchanged elements)', async () => {
|
|
123
|
+
// Wait for initial render
|
|
124
|
+
await waitFor(() => {
|
|
125
|
+
expect(document.getElementById('heading')).not.toBe(null);
|
|
126
|
+
}, {timeout: 500});
|
|
127
|
+
|
|
128
|
+
// Get reference to existing DOM elements
|
|
129
|
+
const $headingBefore = document.getElementById('heading');
|
|
130
|
+
const $descriptionBefore = document.getElementById('description');
|
|
131
|
+
const $contentBefore = document.getElementById('content');
|
|
132
|
+
|
|
133
|
+
// Mark elements to track if they are replaced
|
|
134
|
+
$headingBefore!.setAttribute('data-test-marker', 'original-heading');
|
|
135
|
+
$descriptionBefore!.setAttribute('data-test-marker', 'original-description');
|
|
136
|
+
$contentBefore!.setAttribute('data-test-marker', 'original-content');
|
|
137
|
+
|
|
138
|
+
// Change only one property in viewModel
|
|
139
|
+
namespace.viewModel.content = 'updated text';
|
|
140
|
+
|
|
141
|
+
// Re-render
|
|
142
|
+
await namespace.myComponent.render();
|
|
143
|
+
|
|
144
|
+
await waitFor(() => {
|
|
145
|
+
const $headingAfter = document.getElementById('heading');
|
|
146
|
+
const $descriptionAfter = document.getElementById('description');
|
|
147
|
+
const $contentAfter = document.getElementById('content');
|
|
148
|
+
|
|
149
|
+
// Verify heading and description are the SAME DOM elements (not replaced)
|
|
150
|
+
expect($headingAfter).toBe($headingBefore);
|
|
151
|
+
expect($descriptionAfter).toBe($descriptionBefore);
|
|
152
|
+
|
|
153
|
+
// These elements should still have their original markers
|
|
154
|
+
expect($headingAfter!.getAttribute('data-test-marker')).toBe('original-heading');
|
|
155
|
+
expect($descriptionAfter!.getAttribute('data-test-marker')).toBe('original-description');
|
|
156
|
+
|
|
157
|
+
// Content should be the same element but with updated text
|
|
158
|
+
expect($contentAfter).toBe($contentBefore);
|
|
159
|
+
expect($contentAfter!.textContent).toBe('updated text');
|
|
160
|
+
expect($contentAfter!.getAttribute('data-test-marker')).toBe('original-content');
|
|
161
|
+
}, {timeout: 500});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('Should replace only changed attributes during re-render', async () => {
|
|
165
|
+
// Wait for initial render
|
|
166
|
+
await waitFor(() => {
|
|
167
|
+
expect(document.getElementById('heading')).not.toBe(null);
|
|
168
|
+
}, {timeout: 500});
|
|
169
|
+
|
|
170
|
+
const $heading = document.getElementById('heading');
|
|
171
|
+
|
|
172
|
+
// Add a custom attribute
|
|
173
|
+
$heading!.setAttribute('data-custom', 'custom-value');
|
|
174
|
+
|
|
175
|
+
// Store reference to check if it's the same DOM node
|
|
176
|
+
const originalHeading = $heading;
|
|
177
|
+
|
|
178
|
+
// Change heading text
|
|
179
|
+
namespace.viewModel.heading = 'Updated heading text';
|
|
180
|
+
|
|
181
|
+
// Re-render
|
|
182
|
+
await namespace.myComponent.render();
|
|
183
|
+
|
|
184
|
+
await waitFor(() => {
|
|
185
|
+
const $headingAfter = document.getElementById('heading');
|
|
186
|
+
|
|
187
|
+
// Should be the same DOM element
|
|
188
|
+
expect($headingAfter).toBe(originalHeading);
|
|
189
|
+
|
|
190
|
+
// Text should be updated
|
|
191
|
+
expect($headingAfter!.textContent).toBe('Updated heading text');
|
|
192
|
+
|
|
193
|
+
// Original attributes should remain
|
|
194
|
+
expect($headingAfter!.className).toBe('display-4');
|
|
195
|
+
expect($headingAfter!.getAttribute('data-bind-text')).toBe('heading');
|
|
196
|
+
}, {timeout: 500});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('Should preserve root template elements but allow nested templates to re-render', async () => {
|
|
200
|
+
// Wait for initial render with nested templates
|
|
201
|
+
await waitFor(() => {
|
|
202
|
+
expect(document.getElementById('contentNest1Info')).not.toBe(null);
|
|
203
|
+
}, {timeout: 2000});
|
|
204
|
+
|
|
205
|
+
// Get references to root and nested template elements
|
|
206
|
+
const $contentNest1 = document.getElementById('contentNest1');
|
|
207
|
+
const $heading = document.getElementById('heading');
|
|
208
|
+
|
|
209
|
+
// Mark root template container element
|
|
210
|
+
$contentNest1!.setAttribute('data-test-nested1', 'original-nest1-container');
|
|
211
|
+
$heading!.setAttribute('data-test-heading', 'original-heading');
|
|
212
|
+
|
|
213
|
+
// Update nested property
|
|
214
|
+
namespace.viewModel.contentNest1.info = 'Updated nested content 1';
|
|
215
|
+
|
|
216
|
+
// Re-render
|
|
217
|
+
await namespace.myComponent.render();
|
|
218
|
+
|
|
219
|
+
await waitFor(() => {
|
|
220
|
+
const $contentNest1After = document.getElementById('contentNest1');
|
|
221
|
+
const $headingAfter = document.getElementById('heading');
|
|
222
|
+
const $contentNest1InfoAfter = document.getElementById('contentNest1Info');
|
|
223
|
+
|
|
224
|
+
// Root template elements should be preserved (minimal DOM updates)
|
|
225
|
+
expect($contentNest1After).toBe($contentNest1);
|
|
226
|
+
expect($headingAfter).toBe($heading);
|
|
227
|
+
expect($contentNest1After!.getAttribute('data-test-nested1')).toBe('original-nest1-container');
|
|
228
|
+
expect($headingAfter!.getAttribute('data-test-heading')).toBe('original-heading');
|
|
229
|
+
|
|
230
|
+
// Nested template content should be updated
|
|
231
|
+
expect($contentNest1InfoAfter!.textContent).toBe('Updated nested content 1');
|
|
232
|
+
}, {timeout: 2000});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('Should preserve root template structure across multiple re-renders', async () => {
|
|
236
|
+
// Wait for initial render
|
|
237
|
+
await waitFor(() => {
|
|
238
|
+
expect(document.getElementById('heading')).not.toBe(null);
|
|
239
|
+
}, {timeout: 500});
|
|
240
|
+
|
|
241
|
+
const $heading = document.getElementById('heading');
|
|
242
|
+
const originalHeading = $heading;
|
|
243
|
+
|
|
244
|
+
// Multiple re-renders with different data
|
|
245
|
+
namespace.viewModel.heading = 'First update';
|
|
246
|
+
await namespace.myComponent.render();
|
|
247
|
+
|
|
248
|
+
await waitFor(() => {
|
|
249
|
+
const $element1 = document.getElementById('heading');
|
|
250
|
+
expect($element1).toBe(originalHeading);
|
|
251
|
+
expect($element1!.textContent).toBe('First update');
|
|
252
|
+
}, {timeout: 500});
|
|
253
|
+
|
|
254
|
+
namespace.viewModel.heading = 'Second update';
|
|
255
|
+
await namespace.myComponent.render();
|
|
256
|
+
|
|
257
|
+
await waitFor(() => {
|
|
258
|
+
const $element2 = document.getElementById('heading');
|
|
259
|
+
expect($element2).toBe(originalHeading);
|
|
260
|
+
expect($element2!.textContent).toBe('Second update');
|
|
261
|
+
}, {timeout: 500});
|
|
262
|
+
|
|
263
|
+
namespace.viewModel.heading = 'Third update';
|
|
264
|
+
await namespace.myComponent.render();
|
|
265
|
+
|
|
266
|
+
await waitFor(() => {
|
|
267
|
+
const $element3 = document.getElementById('heading');
|
|
268
|
+
// Should still be the same DOM element after 3 re-renders
|
|
269
|
+
expect($element3).toBe(originalHeading);
|
|
270
|
+
expect($element3!.textContent).toBe('Third update');
|
|
271
|
+
}, {timeout: 500});
|
|
272
|
+
});
|
|
273
|
+
});
|