github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/test/unit/specs/transition/transition_spec.js (about)

     1  var Vue = require('src')
     2  var _ = require('src/util')
     3  var transition = require('src/transition')
     4  var Transition = require('src/transition/transition')
     5  
     6  if (!_.isIE9) {
     7    describe('Transition', function () {
     8      // insert a test css
     9      function insertCSS (text) {
    10        var cssEl = document.createElement('style')
    11        cssEl.textContent = text
    12        document.head.appendChild(cssEl)
    13      }
    14  
    15      var duration = 100
    16      insertCSS(
    17        '.test {\
    18          transition: opacity ' + duration + 'ms ease;\
    19          -webkit-transition: opacity ' + duration + 'ms ease;}'
    20      )
    21      insertCSS('.test-enter, .test-leave { opacity: 0; }')
    22      insertCSS(
    23        '.test-anim-enter {\
    24          animation: test-enter ' + duration + 'ms;\
    25          -webkit-animation: test-enter ' + duration + 'ms;}\
    26        .test-anim-leave {\
    27          animation: test-leave ' + duration + 'ms;\
    28          -webkit-animation: test-leave ' + duration + 'ms;}\
    29        @keyframes test-enter {\
    30          from { opacity: 0 }\
    31          to { opacity: 1 }}\
    32        @-webkit-keyframes test-enter {\
    33          from { opacity: 0 }\
    34          to { opacity: 1 }}\
    35        @keyframes test-leave {\
    36          from { opacity: 1 }\
    37          to { opacity: 0 }}\
    38        @-webkit-keyframes test-leave {\
    39          from { opacity: 1 }\
    40          to { opacity: 0 }}'
    41      )
    42  
    43      describe('Wrapper methods', function () {
    44        var spy, el, target, parent, vm
    45        beforeEach(function () {
    46          el = document.createElement('div')
    47          target = document.createElement('div')
    48          parent = document.createElement('div')
    49          parent.appendChild(target)
    50          spy = jasmine.createSpy('transition skip')
    51          vm = new Vue()
    52          spyOn(transition, 'applyTransition')
    53        })
    54  
    55        it('append', function () {
    56          transition.appendWithTransition(el, parent, vm, spy)
    57          expect(parent.lastChild).toBe(el)
    58          expect(spy).toHaveBeenCalled()
    59        })
    60  
    61        it('before', function () {
    62          transition.beforeWithTransition(el, target, vm, spy)
    63          expect(parent.firstChild).toBe(el)
    64          expect(el.nextSibling).toBe(target)
    65          expect(spy).toHaveBeenCalled()
    66        })
    67  
    68        it('remove', function () {
    69          transition.removeWithTransition(target, vm, spy)
    70          expect(parent.childNodes.length).toBe(0)
    71          expect(spy).toHaveBeenCalled()
    72        })
    73      })
    74  
    75      describe('Skipping', function () {
    76        var el, vm, op, cb
    77        beforeEach(function () {
    78          el = document.createElement('div')
    79          el.textContent = 'hello'
    80          op = jasmine.createSpy('transition skip op')
    81          cb = jasmine.createSpy('transition skip cb')
    82          vm = new Vue()
    83        })
    84  
    85        it('skip el with no transition data', function () {
    86          transition.applyTransition(el, 1, op, vm, cb)
    87          expect(op).toHaveBeenCalled()
    88          expect(cb).toHaveBeenCalled()
    89        })
    90  
    91        it('skip vm still being compiled', function () {
    92          el.__v_trans = new Transition(el, 'test', null, vm)
    93          transition.applyTransition(el, 1, op, vm, cb)
    94          expect(op).toHaveBeenCalled()
    95          expect(cb).toHaveBeenCalled()
    96        })
    97  
    98        it('skip vm with parent still being compiled', function () {
    99          el.__v_trans = new Transition(el, 'test', null, vm)
   100          var child = new Vue({
   101            el: el,
   102            parent: vm
   103          })
   104          expect(child._isCompiled).toBe(true)
   105          transition.applyTransition(el, 1, op, child, cb)
   106          expect(op).toHaveBeenCalled()
   107          expect(cb).toHaveBeenCalled()
   108        })
   109  
   110        it('skip when css transition is not supported', function () {
   111          var e = _.transitionEndEvent
   112          _.transitionEndEvent = null
   113          el.__v_trans = new Transition(el, 'test', null, vm)
   114          vm.$mount(el)
   115          transition.applyTransition(el, 1, op, vm, cb)
   116          expect(op).toHaveBeenCalled()
   117          expect(cb).toHaveBeenCalled()
   118          _.transitionEndEvent = e
   119        })
   120      })
   121  
   122      describe('CSS transitions', function () {
   123        var vm, el, op, cb, hooks
   124        beforeEach(function () {
   125          el = document.createElement('div')
   126          el.textContent = 'hello'
   127          vm = new Vue({ el: el })
   128          op = jasmine.createSpy('css op')
   129          cb = jasmine.createSpy('css cb')
   130          document.body.appendChild(el)
   131          hooks = {
   132            beforeEnter: jasmine.createSpy('beforeEnter'),
   133            enter: jasmine.createSpy('enter'),
   134            afterEnter: jasmine.createSpy('afterEnter'),
   135            beforeLeave: jasmine.createSpy('beforeLeave'),
   136            leave: jasmine.createSpy('leave'),
   137            afterLeave: jasmine.createSpy('afterLeave')
   138          }
   139          // !IMPORTANT!
   140          // this ensures we force a layout for every test.
   141          /* eslint-disable no-unused-vars */
   142          var f = document.body.offsetHeight
   143          /* eslint-enable no-unused-vars */
   144        })
   145  
   146        afterEach(function () {
   147          document.body.removeChild(el)
   148        })
   149  
   150        it('skip on 0s duration (execute right at next frame)', function (done) {
   151          el.__v_trans = new Transition(el, 'test', hooks, vm)
   152          el.style.transition =
   153          el.style.WebkitTransition = 'opacity 0s ease'
   154          transition.applyTransition(el, 1, op, vm, cb)
   155          expect(hooks.beforeEnter).toHaveBeenCalled()
   156          expect(hooks.enter).toHaveBeenCalled()
   157          _.nextTick(function () {
   158            expect(op).toHaveBeenCalled()
   159            expect(cb).toHaveBeenCalled()
   160            expect(hooks.afterEnter).toHaveBeenCalled()
   161            expect(el.classList.contains('test-enter')).toBe(false)
   162            transition.applyTransition(el, -1, op, vm, cb)
   163            expect(hooks.beforeLeave).toHaveBeenCalled()
   164            expect(hooks.leave).toHaveBeenCalled()
   165            _.nextTick(function () {
   166              expect(op.calls.count()).toBe(2)
   167              expect(cb.calls.count()).toBe(2)
   168              expect(hooks.afterLeave).toHaveBeenCalled()
   169              expect(el.classList.contains('test-leave')).toBe(false)
   170              done()
   171            })
   172          })
   173        })
   174  
   175        it('skip when no transition available', function (done) {
   176          el.__v_trans = new Transition(el, 'test-no-trans', hooks, vm)
   177          transition.applyTransition(el, 1, op, vm, cb)
   178          expect(hooks.beforeEnter).toHaveBeenCalled()
   179          expect(hooks.enter).toHaveBeenCalled()
   180          _.nextTick(function () {
   181            expect(op).toHaveBeenCalled()
   182            expect(cb).toHaveBeenCalled()
   183            expect(hooks.afterEnter).toHaveBeenCalled()
   184            expect(el.classList.contains('test-no-trans-enter')).toBe(false)
   185            // wait until transition.justEntered flag is off
   186            setTimeout(function () {
   187              transition.applyTransition(el, -1, op, vm, cb)
   188              expect(hooks.beforeLeave).toHaveBeenCalled()
   189              expect(hooks.leave).toHaveBeenCalled()
   190              _.nextTick(function () {
   191                expect(op.calls.count()).toBe(2)
   192                expect(cb.calls.count()).toBe(2)
   193                expect(hooks.afterLeave).toHaveBeenCalled()
   194                expect(el.classList.contains('test-no-trans-leave')).toBe(false)
   195                done()
   196              })
   197            }, 50)
   198          })
   199        })
   200  
   201        it('transition enter', function (done) {
   202          document.body.removeChild(el)
   203          el.__v_trans = new Transition(el, 'test', hooks, vm)
   204          // inline style
   205          el.style.transition =
   206          el.style.WebkitTransition = 'opacity ' + duration + 'ms ease'
   207          transition.applyTransition(el, 1, function () {
   208            document.body.appendChild(el)
   209            op()
   210          }, vm, cb)
   211          expect(hooks.beforeEnter).toHaveBeenCalled()
   212          expect(hooks.enter).toHaveBeenCalled()
   213          expect(op).toHaveBeenCalled()
   214          expect(cb).not.toHaveBeenCalled()
   215          _.nextTick(function () {
   216            expect(el.classList.contains('test-enter')).toBe(false)
   217            expect(hooks.afterEnter).not.toHaveBeenCalled()
   218            _.on(el, _.transitionEndEvent, function () {
   219              expect(cb).toHaveBeenCalled()
   220              expect(hooks.afterEnter).toHaveBeenCalled()
   221              done()
   222            })
   223          })
   224        })
   225  
   226        it('transition enter for svg', function (done) {
   227          el.innerHTML = '<svg><circle cx="0" cy="0" r="10"></circle></svg>'
   228          var svg = el.querySelector('svg')
   229          var circle = el.querySelector('circle')
   230          svg.removeChild(circle)
   231          circle.__v_trans = new Transition(circle, 'test', hooks, vm)
   232          // inline style
   233          circle.style.transition =
   234          circle.style.WebkitTransition = 'opacity ' + duration + 'ms ease'
   235          transition.applyTransition(circle, 1, function () {
   236            svg.appendChild(circle)
   237            op()
   238          }, vm, cb)
   239          expect(hooks.beforeEnter).toHaveBeenCalled()
   240          expect(hooks.enter).toHaveBeenCalled()
   241          expect(op).toHaveBeenCalled()
   242          expect(cb).not.toHaveBeenCalled()
   243          _.nextTick(function () {
   244            expect(circle.getAttribute('class').indexOf('test-enter') > -1).toBe(false)
   245            expect(hooks.afterEnter).not.toHaveBeenCalled()
   246            _.on(circle, _.transitionEndEvent, function () {
   247              expect(cb).toHaveBeenCalled()
   248              expect(hooks.afterEnter).toHaveBeenCalled()
   249              done()
   250            })
   251          })
   252        })
   253  
   254        it('transition leave', function (done) {
   255          el.__v_trans = new Transition(el, 'test', hooks, vm)
   256          // cascaded class style
   257          el.classList.add('test')
   258          // force a layout here so the transition can be triggered
   259          /* eslint-disable no-unused-vars */
   260          var f = el.offsetHeight
   261          /* eslint-enable no-unused-vars */
   262          transition.applyTransition(el, -1, op, vm, cb)
   263          expect(hooks.beforeLeave).toHaveBeenCalled()
   264          expect(hooks.leave).toHaveBeenCalled()
   265          _.nextTick(function () {
   266            expect(op).not.toHaveBeenCalled()
   267            expect(cb).not.toHaveBeenCalled()
   268            expect(hooks.afterLeave).not.toHaveBeenCalled()
   269            expect(el.classList.contains('test-leave')).toBe(true)
   270            _.on(el, _.transitionEndEvent, function () {
   271              expect(op).toHaveBeenCalled()
   272              expect(cb).toHaveBeenCalled()
   273              expect(el.classList.contains('test-leave')).toBe(false)
   274              expect(hooks.afterLeave).toHaveBeenCalled()
   275              done()
   276            })
   277          })
   278        })
   279  
   280        it('transition leave for svg', function (done) {
   281          el.innerHTML = '<svg><circle cx="0" cy="0" r="10" class="test"></circle></svg>'
   282          var circle = el.querySelector('circle')
   283          circle.__v_trans = new Transition(circle, 'test', hooks, vm)
   284          // force a layout here so the transition can be triggered
   285          /* eslint-disable no-unused-vars */
   286          var f = el.offsetHeight
   287          /* eslint-enable no-unused-vars */
   288          transition.applyTransition(circle, -1, op, vm, cb)
   289          expect(hooks.beforeLeave).toHaveBeenCalled()
   290          expect(hooks.leave).toHaveBeenCalled()
   291          _.nextTick(function () {
   292            expect(op).not.toHaveBeenCalled()
   293            expect(cb).not.toHaveBeenCalled()
   294            expect(hooks.afterLeave).not.toHaveBeenCalled()
   295            expect(circle.getAttribute('class').indexOf('test-leave') > -1).toBe(true)
   296            _.on(circle, _.transitionEndEvent, function () {
   297              expect(op).toHaveBeenCalled()
   298              expect(cb).toHaveBeenCalled()
   299              expect(circle.getAttribute('class').indexOf('test-leave') > -1).toBe(false)
   300              expect(hooks.afterLeave).toHaveBeenCalled()
   301              done()
   302            })
   303          })
   304        })
   305  
   306        it('animation enter', function (done) {
   307          document.body.removeChild(el)
   308          el.__v_trans = new Transition(el, 'test-anim', hooks, vm)
   309          transition.applyTransition(el, 1, function () {
   310            document.body.appendChild(el)
   311            op()
   312          }, vm, cb)
   313          expect(hooks.beforeEnter).toHaveBeenCalled()
   314          expect(hooks.enter).toHaveBeenCalled()
   315          _.nextTick(function () {
   316            expect(op).toHaveBeenCalled()
   317            expect(cb).not.toHaveBeenCalled()
   318            expect(el.classList.contains('test-anim-enter')).toBe(true)
   319            expect(hooks.afterEnter).not.toHaveBeenCalled()
   320            _.on(el, _.animationEndEvent, function () {
   321              expect(el.classList.contains('test-anim-enter')).toBe(false)
   322              expect(cb).toHaveBeenCalled()
   323              expect(hooks.afterEnter).toHaveBeenCalled()
   324              done()
   325            })
   326          })
   327        })
   328  
   329        it('animation leave', function (done) {
   330          el.__v_trans = new Transition(el, 'test-anim', hooks, vm)
   331          transition.applyTransition(el, -1, op, vm, cb)
   332          expect(hooks.beforeLeave).toHaveBeenCalled()
   333          expect(hooks.leave).toHaveBeenCalled()
   334          _.nextTick(function () {
   335            expect(op).not.toHaveBeenCalled()
   336            expect(cb).not.toHaveBeenCalled()
   337            expect(el.classList.contains('test-anim-leave')).toBe(true)
   338            expect(hooks.afterLeave).not.toHaveBeenCalled()
   339            _.on(el, _.animationEndEvent, function () {
   340              expect(op).toHaveBeenCalled()
   341              expect(cb).toHaveBeenCalled()
   342              expect(el.classList.contains('test-anim-leave')).toBe(false)
   343              expect(hooks.afterLeave).toHaveBeenCalled()
   344              done()
   345            })
   346          })
   347        })
   348  
   349        it('css + js hook with callback', function (done) {
   350          document.body.removeChild(el)
   351          el.classList.add('test')
   352  
   353          // enter hook that expects a second argument
   354          // indicates the user wants to control when the
   355          // transition ends.
   356          var enterCalled = false
   357          hooks.enter = function (el, enterDone) {
   358            enterCalled = true
   359            setTimeout(function () {
   360              enterDone()
   361              testDone()
   362            }, duration * 1.5)
   363          }
   364  
   365          el.__v_trans = new Transition(el, 'test', hooks, vm)
   366          transition.applyTransition(el, 1, function () {
   367            document.body.appendChild(el)
   368            op()
   369          }, vm, cb)
   370          expect(hooks.beforeEnter).toHaveBeenCalled()
   371          expect(op).toHaveBeenCalled()
   372          expect(cb).not.toHaveBeenCalled()
   373          expect(enterCalled).toBe(true)
   374          _.nextTick(function () {
   375            expect(el.classList.contains('test-enter')).toBe(false)
   376            expect(hooks.afterEnter).not.toHaveBeenCalled()
   377            _.on(el, _.transitionEndEvent, function () {
   378              // should wait until js callback is called!
   379              expect(cb).not.toHaveBeenCalled()
   380              expect(hooks.afterEnter).not.toHaveBeenCalled()
   381            })
   382          })
   383  
   384          // this is called by the enter hook
   385          function testDone () {
   386            expect(cb).toHaveBeenCalled()
   387            expect(hooks.afterEnter).toHaveBeenCalled()
   388            done()
   389          }
   390        })
   391  
   392        it('css + js hook with callback before transitionend', function (done) {
   393          document.body.removeChild(el)
   394          el.classList.add('test')
   395  
   396          // enter hook that expects a second argument
   397          // indicates the user wants to control when the
   398          // transition ends.
   399          var enterCalled = false
   400          hooks.enter = function (el, enterDone) {
   401            enterCalled = true
   402            setTimeout(function () {
   403              enterDone()
   404              testDone()
   405            }, duration / 2)
   406          }
   407  
   408          el.__v_trans = new Transition(el, 'test', hooks, vm)
   409          transition.applyTransition(el, 1, function () {
   410            document.body.appendChild(el)
   411            op()
   412          }, vm, cb)
   413          expect(hooks.beforeEnter).toHaveBeenCalled()
   414          expect(op).toHaveBeenCalled()
   415          expect(cb).not.toHaveBeenCalled()
   416          expect(enterCalled).toBe(true)
   417          _.nextTick(function () {
   418            expect(el.classList.contains('test-enter')).toBe(false)
   419            expect(hooks.afterEnter).not.toHaveBeenCalled()
   420            _.on(el, _.transitionEndEvent, function () {
   421              // callback should have been called, but only once, by the js callback
   422              expect(cb).toHaveBeenCalled()
   423              expect(cb.calls.count()).toBe(1)
   424              expect(hooks.afterEnter).toHaveBeenCalled()
   425              done()
   426            })
   427          })
   428  
   429          // this is called by the enter hook
   430          function testDone () {
   431            expect(cb).toHaveBeenCalled()
   432            expect(hooks.afterEnter).toHaveBeenCalled()
   433          }
   434        })
   435  
   436        it('clean up unfinished css callback', function (done) {
   437          el.__v_trans = new Transition(el, 'test', null, vm)
   438          el.classList.add('test')
   439          transition.applyTransition(el, -1, function () {
   440            document.body.removeChild(el)
   441          }, vm, cb)
   442          // cancel early
   443          _.nextTick(function () {
   444            expect(el.__v_trans.pendingCssCb).toBeTruthy()
   445            expect(el.classList.contains('test-leave')).toBe(true)
   446            transition.applyTransition(el, 1, function () {
   447              document.body.appendChild(el)
   448            }, vm)
   449            expect(cb).not.toHaveBeenCalled()
   450            expect(el.classList.contains('test-leave')).toBe(false)
   451            expect(el.__v_trans.pendingCssCb).toBeNull()
   452            // IMPORTANT
   453            // Let the queue flush finish before enter the next
   454            // test. Don't remove the nextTick.
   455            _.nextTick(done)
   456          })
   457        })
   458  
   459        it('cache transition sniff results', function (done) {
   460          el.__v_trans = new Transition(el, 'test', null, vm)
   461          el.classList.add('test')
   462          transition.applyTransition(el, 1, op, vm)
   463          _.nextTick(function () {
   464            expect(el.__v_trans.typeCache['test-enter']).not.toBeUndefined()
   465            // for some reason window.getComputedStyle cannot be spied on in
   466            // phantomjs after the refactor...
   467            var calls = 0
   468            Object.defineProperty(el.__v_trans.typeCache, 'test-enter', {
   469              get: function () {
   470                calls++
   471                return 1
   472              }
   473            })
   474            transition.applyTransition(el, 1, op, vm)
   475            _.nextTick(function () {
   476              expect(calls).toBe(1)
   477              done()
   478            })
   479          })
   480        })
   481      })
   482  
   483      describe('JavaScript only transitions', function () {
   484        var el, vm, op, cb, hooks
   485        beforeEach(function () {
   486          hooks = {}
   487          el = document.createElement('div')
   488          el.textContent = 'hello'
   489          document.body.appendChild(el)
   490          op = jasmine.createSpy('js transition op')
   491          cb = jasmine.createSpy('js transition cb')
   492          vm = new Vue({ el: el })
   493        })
   494  
   495        afterEach(function () {
   496          document.body.removeChild(el)
   497        })
   498  
   499        it('beforeEnter', function () {
   500          var spy = jasmine.createSpy('js transition beforeEnter')
   501          hooks.beforeEnter = function (el) {
   502            spy(this, el)
   503          }
   504          el.__v_trans = new Transition(el, 'test', hooks, vm)
   505          transition.applyTransition(el, 1, op, vm, cb)
   506          expect(spy).toHaveBeenCalledWith(vm, el)
   507        })
   508  
   509        it('enter', function () {
   510          var spy = jasmine.createSpy('js enter')
   511          hooks.enter = function (e, done) {
   512            expect(e).toBe(el)
   513            expect(op).toHaveBeenCalled()
   514            done()
   515            expect(cb).toHaveBeenCalled()
   516            spy(this)
   517          }
   518          el.__v_trans = new Transition(el, 'test', hooks, vm)
   519          transition.applyTransition(el, 1, op, vm, cb)
   520          expect(spy).toHaveBeenCalledWith(vm)
   521        })
   522  
   523        it('leave', function () {
   524          var spy = jasmine.createSpy('js leave')
   525          hooks.leave = function (e, done) {
   526            expect(e).toBe(el)
   527            done()
   528            expect(op).toHaveBeenCalled()
   529            expect(cb).toHaveBeenCalled()
   530            spy(this)
   531          }
   532          el.__v_trans = new Transition(el, 'test', hooks, vm)
   533          transition.applyTransition(el, -1, op, vm, cb)
   534          expect(spy).toHaveBeenCalledWith(vm)
   535        })
   536  
   537        it('no def', function (done) {
   538          el.__v_trans = new Transition(el, 'test', null, vm)
   539          transition.applyTransition(el, 1, op, vm, cb)
   540          _.nextTick(function () {
   541            expect(op).toHaveBeenCalled()
   542            expect(cb).toHaveBeenCalled()
   543            transition.applyTransition(el, -1, op, vm, cb)
   544            _.nextTick(function () {
   545              expect(op.calls.count()).toBe(2)
   546              expect(cb.calls.count()).toBe(2)
   547              done()
   548            })
   549          })
   550        })
   551  
   552        it('cancel hook', function (done) {
   553          var cleanupSpy = jasmine.createSpy('js cleanup')
   554          var leaveSpy = jasmine.createSpy('js leave')
   555          var timeout
   556          hooks.enter = function (el, done) {
   557            timeout = setTimeout(done, duration / 2)
   558          }
   559          hooks.enterCancelled = function () {
   560            clearTimeout(timeout)
   561            cleanupSpy()
   562          }
   563          hooks.leave = function (el, done) {
   564            expect(cleanupSpy).toHaveBeenCalled()
   565            leaveSpy()
   566            done()
   567          }
   568          el.__v_trans = new Transition(el, 'test', hooks, vm)
   569          transition.applyTransition(el, 1, op, vm, cb)
   570          setTimeout(function () {
   571            transition.applyTransition(el, -1, op, vm)
   572            expect(leaveSpy).toHaveBeenCalled()
   573            setTimeout(function () {
   574              expect(cb).not.toHaveBeenCalled()
   575              done()
   576            }, duration / 2)
   577          }, duration / 4)
   578        })
   579      })
   580    })
   581  }