1+ import { isObservableArray } from '../utils/knockout'
12import { initDotvvm } from './helper'
23
34const viewModel = {
@@ -6,7 +7,8 @@ const viewModel = {
67 ComplexObj : {
78 A : 1 ,
89 B : [ 1 , 2 , 3 ]
9- }
10+ } ,
11+ NullField : null
1012}
1113initDotvvm ( { viewModel} )
1214
@@ -131,3 +133,87 @@ it.each([
131133 if ( requiresSync ) dotvvm . rootStateManager . doUpdateNow ( )
132134 expect ( context . Obj . state ) . toStrictEqual ( { Something : { ...viewModel . ComplexObj , A : 43210 } , Arr : [ 1 , 2 ] } )
133135} )
136+
137+ it . each ( [
138+ [ "[1,2]" , true , false ] ,
139+ [ "ko.observableArray([1, 2])" , true , true ] ,
140+ [ "ComplexObj().B" , true , true ] ,
141+ [ "ComplexObj().B()" , true , false ] ,
142+ [ "ComplexObj().B().map(_ => 1)" , true , false ] ,
143+ [ "ComplexObj().B().length" , false , false ] ,
144+ [ "ComplexObj" , false , false ] ,
145+ [ "ComplexObj()" , false , false ] ,
146+ [ "null" , false , false ] ,
147+ [ "NullField" , false , false ] ,
148+ ] ) ( "dotvvm-with-control-properties makes observable array before its touched (%s)" , ( binding , isArray , tryObservableArray ) => {
149+ dotvvm . setState ( viewModel ) ; dotvvm . rootStateManager . doUpdateNow ( )
150+
151+ const div = document . createElement ( "div" )
152+ div . innerHTML = `
153+ <div data-bind="dotvvm-with-control-properties: {
154+ Arr: ${ binding }
155+ }">
156+ <span id=x />
157+ <div data-bind="dotvvm-with-control-properties: { Arr: $control.Arr }">
158+ <span id=y />
159+ </div>
160+ </div>
161+ `
162+
163+ ko . applyBindings ( dotvvm . viewModelObservables . root , div )
164+
165+ const x = div . querySelector ( "#x" ) !
166+ const y = div . querySelector ( "#y" ) !
167+ const contextX : any = ko . contextFor ( x ) . $control
168+ const contextY : any = ko . contextFor ( y ) . $control
169+
170+ expect ( contextX . Arr ) . observable ( )
171+ expect ( contextY . Arr ) . observable ( )
172+
173+ expect ( isObservableArray ( contextX . Arr ) ) . toBe ( isArray )
174+ expect ( isObservableArray ( contextY . Arr ) ) . toBe ( isArray )
175+
176+ if ( tryObservableArray ) {
177+ contextX . Arr . unshift ( 99 )
178+ const ix = contextX . Arr . indexOf ( contextX . Arr ( ) [ 0 ] )
179+ const ix2 = contextY . Arr . indexOf ( contextX . Arr ( ) [ 0 ] )
180+ expect ( ix2 ) . toEqual ( ix )
181+ }
182+ } )
183+
184+ test ( "dotvvm-with-control-properties correctly wraps null changed to array" , ( ) => {
185+ dotvvm . setState ( viewModel )
186+
187+ dotvvm . patchState ( { ComplexObj : null } )
188+ dotvvm . rootStateManager . doUpdateNow ( )
189+
190+ const div = document . createElement ( "div" )
191+ div . innerHTML = `
192+ <div data-bind="dotvvm-with-control-properties: {
193+ Arr: ComplexObj()?.B
194+ }"> <span id=x /> </div>
195+ `
196+ ko . applyBindings ( dotvvm . viewModelObservables . root , div )
197+ const x = div . querySelector ( "#x" ) !
198+ const context : any = ko . contextFor ( x ) . $control
199+ expect ( context . Arr ) . observable ( )
200+ expect ( context . Arr . state ) . toEqual ( undefined )
201+ expect ( context . Arr ( ) ) . toEqual ( undefined )
202+ expect ( "push" in context . Arr ) . toBe ( false )
203+
204+ dotvvm . patchState ( { ComplexObj : { B : [ 1 , 2 ] } } )
205+ dotvvm . rootStateManager . doUpdateNow ( )
206+
207+ expect ( context . Arr ( ) ?. map ( ( x : any ) => x ( ) ) ) . toStrictEqual ( [ 1 , 2 ] )
208+ expect ( context . Arr . state ) . toStrictEqual ( [ 1 , 2 ] )
209+ expect ( "push" in context . Arr ) . toBe ( true )
210+
211+ context . Arr . push ( 3 )
212+ expect ( context . Arr ( ) ?. map ( ( x :any ) => x ( ) ) ) . toStrictEqual ( [ 1 , 2 , 3 ] )
213+ expect ( dotvvm . state . ComplexObj . B ) . toStrictEqual ( [ 1 , 2 , 3 ] )
214+
215+ context . Arr . unshift ( 0 )
216+ context . Arr . splice ( 1 , 1 )
217+
218+ expect ( dotvvm . state . ComplexObj . B ) . toStrictEqual ( [ 0 , 2 , 3 ] )
219+ } )
0 commit comments