1+ var Vue = require ( '../../../src/vue' )
2+ var _ = Vue . util
3+
14describe ( 'Async components' , function ( ) {
25
6+ var el
7+ beforeEach ( function ( ) {
8+ el = document . createElement ( 'div' )
9+ document . body . appendChild ( el )
10+ spyOn ( _ , 'warn' )
11+ } )
12+
13+ afterEach ( function ( ) {
14+ document . body . removeChild ( el )
15+ } )
16+
317 describe ( 'v-component' , function ( ) {
4- // - normal
5- // - dynamic
6- // - nested component caching
7- // - invalidate pending callback on teardown
8- // - avoid duplicate requests
18+
19+ it ( 'normal' , function ( done ) {
20+ var vm = new Vue ( {
21+ el : el ,
22+ template : '<div v-component="test"></div>' ,
23+ components : {
24+ test : function ( resolve ) {
25+ setTimeout ( function ( ) {
26+ resolve ( {
27+ template : 'ok'
28+ } )
29+ next ( )
30+ } , 0 )
31+ }
32+ }
33+ } )
34+ function next ( ) {
35+ expect ( el . textContent ) . toBe ( 'ok' )
36+ done ( )
37+ }
38+ } )
39+
40+ it ( 'dynamic' , function ( done ) {
41+ var vm = new Vue ( {
42+ el : el ,
43+ template : '<div v-component="{{view}}"></div>' ,
44+ data : {
45+ view : 'a'
46+ } ,
47+ components : {
48+ a : function ( resolve ) {
49+ setTimeout ( function ( ) {
50+ resolve ( {
51+ template : 'A'
52+ } )
53+ step1 ( )
54+ } , 0 )
55+ } ,
56+ b : function ( resolve ) {
57+ setTimeout ( function ( ) {
58+ resolve ( {
59+ template : 'B'
60+ } )
61+ step2 ( )
62+ } , 0 )
63+ }
64+ }
65+ } )
66+ var aCalled = false
67+ function step1 ( ) {
68+ // ensure A is resolved only once
69+ expect ( aCalled ) . toBe ( false )
70+ aCalled = true
71+ expect ( el . textContent ) . toBe ( 'A' )
72+ vm . view = 'b'
73+ }
74+ function step2 ( ) {
75+ expect ( el . textContent ) . toBe ( 'B' )
76+ vm . view = 'a'
77+ _ . nextTick ( function ( ) {
78+ expect ( el . textContent ) . toBe ( 'A' )
79+ done ( )
80+ } )
81+ }
82+ } )
83+
84+ it ( 'invalidate pending on dynamic switch' , function ( done ) {
85+ var vm = new Vue ( {
86+ el : el ,
87+ template : '<div v-component="{{view}}"></div>' ,
88+ data : {
89+ view : 'a'
90+ } ,
91+ components : {
92+ a : function ( resolve ) {
93+ setTimeout ( function ( ) {
94+ resolve ( {
95+ template : 'A'
96+ } )
97+ step1 ( )
98+ } , 100 )
99+ } ,
100+ b : function ( resolve ) {
101+ setTimeout ( function ( ) {
102+ resolve ( {
103+ template : 'B'
104+ } )
105+ step2 ( )
106+ } , 200 )
107+ }
108+ }
109+ } )
110+ expect ( el . textContent ) . toBe ( '' )
111+ vm . view = 'b'
112+ function step1 ( ) {
113+ // called after A resolves, but A should have been
114+ // invalidated so not cotrId should be set
115+ expect ( vm . _directives [ 0 ] . ctorId ) . toBe ( null )
116+ }
117+ function step2 ( ) {
118+ // B should resolve successfully
119+ expect ( el . textContent ) . toBe ( 'B' )
120+ done ( )
121+ }
122+ } )
123+
124+ it ( 'invalidate pending on teardown' , function ( done ) {
125+ var vm = new Vue ( {
126+ el : el ,
127+ template : '<div v-component="a"></div>' ,
128+ data : {
129+ view : 'a'
130+ } ,
131+ components : {
132+ a : function ( resolve ) {
133+ setTimeout ( function ( ) {
134+ resolve ( {
135+ template : 'A'
136+ } )
137+ next ( )
138+ } , 100 )
139+ }
140+ }
141+ } )
142+ expect ( el . textContent ) . toBe ( '' )
143+ // cache directive isntance before destroy
144+ var dir = vm . _directives [ 0 ]
145+ vm . $destroy ( )
146+ function next ( ) {
147+ // called after A resolves, but A should have been
148+ // invalidated so not cotrId should be set
149+ expect ( dir . ctorId ) . toBe ( null )
150+ done ( )
151+ }
152+ } )
153+
154+ it ( 'avoid duplicate requests' , function ( done ) {
155+ var factoryCallCount = 0
156+ var instanceCount = 0
157+ var vm = new Vue ( {
158+ el : el ,
159+ template :
160+ '<div v-component="a"></div>' +
161+ '<div v-component="a"></div>' ,
162+ components : {
163+ a : factory
164+ }
165+ } )
166+ function factory ( resolve ) {
167+ factoryCallCount ++
168+ setTimeout ( function ( ) {
169+ resolve ( {
170+ template : 'A' ,
171+ created : function ( ) {
172+ instanceCount ++
173+ }
174+ } )
175+ next ( )
176+ } , 0 )
177+ }
178+ function next ( ) {
179+ expect ( factoryCallCount ) . toBe ( 1 )
180+ expect ( el . textContent ) . toBe ( 'AA' )
181+ expect ( instanceCount ) . toBe ( 2 )
182+ done ( )
183+ }
184+ } )
9185 } )
10186
11187 describe ( 'v-repeat' , function ( ) {
12188 // - normal
13189 // - invalidate on teardown
14190 // - warn for dynamic
191+
192+ it ( 'normal' , function ( done ) {
193+ var vm = new Vue ( {
194+ el : el ,
195+ template : '<div v-repeat="list" v-component="test"></div>' ,
196+ data : {
197+ list : [ 1 , 2 , 3 ]
198+ } ,
199+ components : {
200+ test : function ( resolve ) {
201+ setTimeout ( function ( ) {
202+ resolve ( {
203+ template : '{{$value}}'
204+ } )
205+ next ( )
206+ } , 0 )
207+ }
208+ }
209+ } )
210+ function next ( ) {
211+ expect ( el . textContent ) . toBe ( '123' )
212+ done ( )
213+ }
214+ } )
215+
216+ it ( 'only resolve once' , function ( done ) {
217+ var vm = new Vue ( {
218+ el : el ,
219+ template : '<div v-repeat="list" v-component="test"></div>' ,
220+ data : {
221+ list : [ 1 , 2 , 3 ]
222+ } ,
223+ components : {
224+ test : function ( resolve ) {
225+ setTimeout ( function ( ) {
226+ resolve ( {
227+ template : '{{$value}}'
228+ } )
229+ next ( )
230+ } , 100 )
231+ }
232+ }
233+ } )
234+ // hijack realUpdate - this should only be called once
235+ // spyOn doesn't work here
236+ var update = vm . _directives [ 0 ] . realUpdate
237+ var callCount = 0
238+ vm . _directives [ 0 ] . realUpdate = function ( ) {
239+ callCount ++
240+ update . apply ( this , arguments )
241+ }
242+ vm . list = [ 2 , 3 , 4 ]
243+ function next ( ) {
244+ expect ( el . textContent ) . toBe ( '234' )
245+ expect ( callCount ) . toBe ( 1 )
246+ done ( )
247+ }
248+ } )
249+
250+ it ( 'invalidate on teardown' , function ( done ) {
251+ var vm = new Vue ( {
252+ el : el ,
253+ template : '<div v-repeat="list" v-component="test"></div>' ,
254+ data : {
255+ list : [ 1 , 2 , 3 ]
256+ } ,
257+ components : {
258+ test : function ( resolve ) {
259+ setTimeout ( function ( ) {
260+ resolve ( {
261+ template : '{{$value}}'
262+ } )
263+ next ( )
264+ } , 0 )
265+ }
266+ }
267+ } )
268+ var dir = vm . _directives [ 0 ]
269+ vm . $destroy ( )
270+ function next ( ) {
271+ expect ( el . textContent ) . toBe ( '' )
272+ expect ( dir . Ctor ) . toBe ( null )
273+ done ( )
274+ }
275+ } )
276+
277+ it ( 'warn when used with dynamic v-repeat' , function ( ) {
278+ var vm = new Vue ( {
279+ el : el ,
280+ template : '<div v-repeat="list" v-component="{{c}}"></div>' ,
281+ data : {
282+ list : [ 1 , 2 , 3 ] ,
283+ c : 'test'
284+ } ,
285+ components : {
286+ test : function ( resolve ) {
287+ setTimeout ( function ( ) {
288+ resolve ( {
289+ template : '{{$value}}'
290+ } )
291+ } , 0 )
292+ }
293+ }
294+ } )
295+ expect ( hasWarned ( _ , 'Async resolution is not supported' ) ) . toBe ( true )
296+ } )
15297 } )
16298
17299} )
0 commit comments