github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/test/unit/specs/directives/internal/component_spec.js (about) 1 var _ = require('src/util') 2 var Vue = require('src') 3 4 describe('Component', function () { 5 var el 6 beforeEach(function () { 7 el = document.createElement('div') 8 document.body.appendChild(el) 9 }) 10 11 afterEach(function () { 12 document.body.removeChild(el) 13 }) 14 15 it('static', function () { 16 new Vue({ 17 el: el, 18 template: '<test></test>', 19 components: { 20 test: { 21 data: function () { 22 return { a: 123 } 23 }, 24 template: '{{a}}' 25 } 26 } 27 }) 28 expect(el.innerHTML).toBe('<test>123</test>') 29 }) 30 31 it('replace', function () { 32 new Vue({ 33 el: el, 34 template: '<test></test>', 35 components: { 36 test: { 37 replace: true, 38 data: function () { 39 return { a: 123 } 40 }, 41 template: '<p>{{a}}</p>' 42 } 43 } 44 }) 45 expect(el.innerHTML).toBe('<p>123</p>') 46 }) 47 48 it('"is" on table elements', function () { 49 var vm = new Vue({ 50 el: el, 51 template: '<table><tbody><tr is="test"></tr></tbody></table>', 52 components: { 53 test: { 54 data: function () { 55 return { a: 123 } 56 }, 57 template: '<td>{{a}}</td>' 58 } 59 } 60 }) 61 expect(el.innerHTML).toBe(vm.$options.template.replace(/<tr.*\/tr>/, '<tr><td>123</td></tr>')) 62 expect(getWarnCount()).toBe(0) 63 }) 64 65 it('inline-template', function () { 66 new Vue({ 67 el: el, 68 template: '<test inline-template>{{a}}</test>', 69 data: { 70 a: 'parent' 71 }, 72 components: { 73 test: { 74 data: function () { 75 return { a: 'child' } 76 }, 77 template: 'child option template' 78 } 79 } 80 }) 81 expect(el.innerHTML).toBe('<test>child</test>') 82 }) 83 84 it('block replace', function () { 85 new Vue({ 86 el: el, 87 template: '<test></test>', 88 components: { 89 test: { 90 replace: true, 91 data: function () { 92 return { a: 123, b: 234 } 93 }, 94 template: '<p>{{a}}</p><p>{{b}}</p>' 95 } 96 } 97 }) 98 expect(el.innerHTML).toBe('<p>123</p><p>234</p>') 99 }) 100 101 it('dynamic', function (done) { 102 var vm = new Vue({ 103 el: el, 104 template: '<component :is="view" :view="view"></component>', 105 data: { 106 view: 'view-a' 107 }, 108 components: { 109 'view-a': { 110 template: '<div>foo</div>', 111 replace: true, 112 data: function () { 113 return { view: 'a' } 114 } 115 }, 116 'view-b': { 117 template: '<div>bar</div>', 118 replace: true, 119 data: function () { 120 return { view: 'b' } 121 } 122 } 123 } 124 }) 125 expect(el.innerHTML).toBe('<div view="view-a">foo</div>') 126 vm.view = 'view-b' 127 _.nextTick(function () { 128 expect(el.innerHTML).toBe('<div view="view-b">bar</div>') 129 vm.view = '' 130 _.nextTick(function () { 131 expect(el.innerHTML).toBe('') 132 done() 133 }) 134 }) 135 }) 136 137 it(':is using raw component constructor', function () { 138 new Vue({ 139 el: el, 140 template: 141 '<component :is="$options.components.test"></component>' + 142 '<component :is="$options.components.async"></component>', 143 components: { 144 test: { 145 template: 'foo' 146 }, 147 async: function (resolve) { 148 resolve({ 149 template: 'bar' 150 }) 151 } 152 } 153 }) 154 expect(el.textContent).toBe('foobar') 155 }) 156 157 it('keep-alive', function (done) { 158 var spyA = jasmine.createSpy() 159 var spyB = jasmine.createSpy() 160 var vm = new Vue({ 161 el: el, 162 template: '<component :is="view" keep-alive></component>', 163 data: { 164 view: 'view-a' 165 }, 166 components: { 167 'view-a': { 168 created: spyA, 169 template: '<div>foo</div>', 170 replace: true 171 }, 172 'view-b': { 173 created: spyB, 174 template: '<div>bar</div>', 175 replace: true 176 } 177 } 178 }) 179 expect(el.innerHTML).toBe('<div>foo</div>') 180 expect(spyA.calls.count()).toBe(1) 181 expect(spyB.calls.count()).toBe(0) 182 vm.view = 'view-b' 183 _.nextTick(function () { 184 expect(el.innerHTML).toBe('<div>bar</div>') 185 expect(spyA.calls.count()).toBe(1) 186 expect(spyB.calls.count()).toBe(1) 187 vm.view = 'view-a' 188 _.nextTick(function () { 189 expect(el.innerHTML).toBe('<div>foo</div>') 190 expect(spyA.calls.count()).toBe(1) 191 expect(spyB.calls.count()).toBe(1) 192 vm.view = 'view-b' 193 _.nextTick(function () { 194 expect(el.innerHTML).toBe('<div>bar</div>') 195 expect(spyA.calls.count()).toBe(1) 196 expect(spyB.calls.count()).toBe(1) 197 done() 198 }) 199 }) 200 }) 201 }) 202 203 it('should compile parent template directives & content in parent scope', function (done) { 204 var vm = new Vue({ 205 el: el, 206 data: { 207 ok: false, 208 message: 'hello' 209 }, 210 template: '<test v-show="ok">{{message}}</test>', 211 components: { 212 test: { 213 template: '<div><slot></slot> {{message}}</div>', 214 replace: true, 215 data: function () { 216 return { 217 message: 'world' 218 } 219 } 220 } 221 } 222 }) 223 expect(el.firstChild.style.display).toBe('none') 224 expect(el.firstChild.textContent).toBe('hello world') 225 vm.ok = true 226 vm.message = 'bye' 227 _.nextTick(function () { 228 expect(el.firstChild.style.display).toBe('') 229 expect(el.firstChild.textContent).toBe('bye world') 230 done() 231 }) 232 }) 233 234 it('parent content + v-if', function (done) { 235 var vm = new Vue({ 236 el: el, 237 data: { 238 ok: false, 239 message: 'hello' 240 }, 241 template: '<test v-if="ok">{{message}}</test>', 242 components: { 243 test: { 244 template: '<slot></slot> {{message}}', 245 data: function () { 246 return { 247 message: 'world' 248 } 249 } 250 } 251 } 252 }) 253 expect(el.textContent).toBe('') 254 expect(vm.$children.length).toBe(0) 255 expect(vm._directives.length).toBe(1) // v-if 256 vm.ok = true 257 _.nextTick(function () { 258 expect(vm.$children.length).toBe(1) 259 expect(vm._directives.length).toBe(3) // v-if, component, v-text 260 expect(el.textContent).toBe('hello world') 261 done() 262 }) 263 }) 264 265 it('props', function () { 266 new Vue({ 267 el: el, 268 data: { 269 list: [{a: 1}, {a: 2}] 270 }, 271 template: '<test :collection="list"></test>', 272 components: { 273 test: { 274 template: '<ul><li v-for="item in collection">{{item.a}}</li></ul>', 275 replace: true, 276 props: ['collection'] 277 } 278 } 279 }) 280 expect(el.innerHTML).toBe('<ul><li>1</li><li>2</li></ul>') 281 }) 282 283 it('activate hook for static component', function (done) { 284 new Vue({ 285 el: el, 286 template: '<view-a></view-a>', 287 components: { 288 'view-a': { 289 template: 'foo', 290 activate: function (ready) { 291 setTimeout(function () { 292 expect(el.textContent).toBe('') 293 ready() 294 expect(el.textContent).toBe('foo') 295 done() 296 }, 0) 297 } 298 } 299 } 300 }) 301 }) 302 303 it('multiple activate hooks', function (done) { 304 var mixinSpy = jasmine.createSpy('mixin activate') 305 new Vue({ 306 el: el, 307 template: '<view-a></view-a>', 308 components: { 309 'view-a': { 310 template: 'foo', 311 mixins: [{ 312 activate: function (done) { 313 expect(el.textContent).toBe('') 314 mixinSpy() 315 done() 316 } 317 }], 318 activate: function (ready) { 319 setTimeout(function () { 320 expect(mixinSpy).toHaveBeenCalled() 321 expect(el.textContent).toBe('') 322 ready() 323 expect(el.textContent).toBe('foo') 324 done() 325 }, 0) 326 } 327 } 328 } 329 }) 330 }) 331 332 it('activate hook for dynamic components', function (done) { 333 var next 334 var vm = new Vue({ 335 el: el, 336 data: { 337 view: 'view-a' 338 }, 339 template: '<component :is="view"></component>', 340 components: { 341 'view-a': { 342 template: 'foo', 343 activate: function (ready) { 344 next = ready 345 } 346 }, 347 'view-b': { 348 template: 'bar', 349 activate: function (ready) { 350 next = ready 351 } 352 } 353 } 354 }) 355 expect(next).toBeTruthy() 356 expect(el.textContent).toBe('') 357 next() 358 expect(el.textContent).toBe('foo') 359 vm.view = 'view-b' 360 _.nextTick(function () { 361 expect(el.textContent).toBe('foo') 362 // old vm is already removed, this is the new vm 363 expect(vm.$children.length).toBe(1) 364 next() 365 expect(el.textContent).toBe('bar') 366 // ensure switching before ready event correctly 367 // cleans up the component being waited on. 368 // see #1152 369 vm.view = 'view-a' 370 // store the ready callback for view-a 371 var callback = next 372 _.nextTick(function () { 373 vm.view = 'view-b' 374 _.nextTick(function () { 375 expect(vm.$children.length).toBe(1) 376 expect(vm.$children[0].$el.textContent).toBe('bar') 377 // calling view-a's ready callback here should not throw 378 // because it should've been cancelled (#1994) 379 expect(callback).not.toThrow() 380 done() 381 }) 382 }) 383 }) 384 }) 385 386 it('activate hook + keep-alive', function (done) { 387 var next 388 var vm = new Vue({ 389 el: el, 390 data: { 391 view: 'view-a' 392 }, 393 template: '<component :is="view" keep-alive></component>', 394 components: { 395 'view-a': { 396 template: 'foo', 397 activate: function (ready) { 398 next = ready 399 } 400 }, 401 'view-b': { 402 template: 'bar', 403 activate: function (ready) { 404 next = ready 405 } 406 } 407 } 408 }) 409 next() 410 expect(el.textContent).toBe('foo') 411 vm.view = 'view-b' 412 _.nextTick(function () { 413 expect(vm.$children.length).toBe(2) 414 next() 415 expect(el.textContent).toBe('bar') 416 vm.view = 'view-a' 417 _.nextTick(function () { 418 // should switch without the need to emit 419 // because of keep-alive 420 expect(el.textContent).toBe('foo') 421 done() 422 }) 423 }) 424 }) 425 426 it('transition-mode: in-out', function (done) { 427 var spy1 = jasmine.createSpy('enter') 428 var spy2 = jasmine.createSpy('leave') 429 var next 430 var vm = new Vue({ 431 el: el, 432 data: { 433 view: 'view-a' 434 }, 435 template: '<component :is="view" transition="test" transition-mode="in-out"></component>', 436 components: { 437 'view-a': { template: 'foo' }, 438 'view-b': { template: 'bar' } 439 }, 440 transitions: { 441 test: { 442 enter: function (el, done) { 443 spy1() 444 next = done 445 }, 446 leave: function (el, done) { 447 spy2() 448 _.nextTick(done) 449 } 450 } 451 } 452 }) 453 expect(el.textContent).toBe('foo') 454 vm.view = 'view-b' 455 _.nextTick(function () { 456 expect(spy1).toHaveBeenCalled() 457 expect(spy2).not.toHaveBeenCalled() 458 expect(el.textContent).toBe('foobar') 459 next() 460 _.nextTick(function () { 461 expect(spy2).toHaveBeenCalled() 462 _.nextTick(function () { 463 expect(el.textContent).toBe('bar') 464 done() 465 }) 466 }) 467 }) 468 }) 469 470 it('transition-mode: out-in', function (done) { 471 var spy1 = jasmine.createSpy('enter') 472 var spy2 = jasmine.createSpy('leave') 473 var next 474 var vm = new Vue({ 475 el: el, 476 data: { 477 view: 'view-a' 478 }, 479 template: '<component :is="view" transition="test" transition-mode="out-in"></component>', 480 components: { 481 'view-a': { template: 'foo' }, 482 'view-b': { template: 'bar' } 483 }, 484 transitions: { 485 test: { 486 enter: function (el, done) { 487 spy2() 488 _.nextTick(done) 489 }, 490 leave: function (el, done) { 491 spy1() 492 next = done 493 } 494 } 495 } 496 }) 497 expect(el.textContent).toBe('foo') 498 vm.view = 'view-b' 499 _.nextTick(function () { 500 expect(spy1).toHaveBeenCalled() 501 expect(spy2).not.toHaveBeenCalled() 502 expect(el.textContent).toBe('foo') 503 next() 504 expect(spy2).toHaveBeenCalled() 505 expect(el.textContent).toBe('bar') 506 done() 507 }) 508 }) 509 510 it('teardown', function (done) { 511 var vm = new Vue({ 512 el: el, 513 template: '<component :is="view" keep-alive></component>', 514 data: { 515 view: 'test' 516 }, 517 components: { 518 test: {}, 519 test2: {} 520 } 521 }) 522 vm.view = 'test2' 523 _.nextTick(function () { 524 expect(vm.$children.length).toBe(2) 525 var child = vm.$children[0] 526 var child2 = vm.$children[1] 527 vm._directives[0].unbind() 528 expect(vm._directives[0].cache).toBeNull() 529 expect(vm.$children.length).toBe(0) 530 expect(child._isDestroyed).toBe(true) 531 expect(child2._isDestroyed).toBe(true) 532 done() 533 }) 534 }) 535 536 it('already mounted warn', function () { 537 new Vue({ 538 el: document.createElement('test'), 539 components: { 540 test: {} 541 } 542 }) 543 expect('cannot mount component "test" on already mounted element').toHaveBeenWarned() 544 }) 545 546 it('not found component should not throw', function () { 547 expect(function () { 548 new Vue({ 549 el: el, 550 template: '<div is="non-existent"></div>' 551 }) 552 }).not.toThrow() 553 }) 554 555 it('warn possible camelCase components', function () { 556 new Vue({ 557 el: document.createElement('div'), 558 template: '<HelloWorld></HelloWorld>', 559 components: { 560 'hello-world': {} 561 } 562 }) 563 expect('did you mean <hello-world>?').toHaveBeenWarned() 564 }) 565 })