|
|
@@ -0,0 +1,339 @@
|
|
|
+var Vue = require('../../../src/vue')
|
|
|
+var _ = require('../../../src/util')
|
|
|
+var transition = require('../../../src/transition')
|
|
|
+
|
|
|
+if (_.inBrowser && !_.isIE9) {
|
|
|
+ describe('Transition', function () {
|
|
|
+
|
|
|
+ describe('Wrapper methods', function () {
|
|
|
+
|
|
|
+ var spy, el, target, parent, vm
|
|
|
+ beforeEach(function () {
|
|
|
+ el = document.createElement('div')
|
|
|
+ target = document.createElement('div')
|
|
|
+ parent = document.createElement('div')
|
|
|
+ parent.appendChild(target)
|
|
|
+ spy = jasmine.createSpy('transition skip')
|
|
|
+ vm = new Vue()
|
|
|
+ spyOn(transition, 'apply')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('append', function () {
|
|
|
+ transition.append(el, parent, vm, spy)
|
|
|
+ expect(parent.lastChild).toBe(el)
|
|
|
+ expect(spy).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('before', function () {
|
|
|
+ transition.before(el, target, vm, spy)
|
|
|
+ expect(parent.firstChild).toBe(el)
|
|
|
+ expect(el.nextSibling).toBe(target)
|
|
|
+ expect(spy).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('remove', function () {
|
|
|
+ transition.remove(target, vm, spy)
|
|
|
+ expect(parent.childNodes.length).toBe(0)
|
|
|
+ expect(spy).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('removeThenAppend', function () {
|
|
|
+ transition.removeThenAppend(target, el, vm, spy)
|
|
|
+ expect(parent.childNodes.length).toBe(0)
|
|
|
+ expect(el.firstChild).toBe(target)
|
|
|
+ expect(spy).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ describe('Skipping', function () {
|
|
|
+
|
|
|
+ var el, vm, op, cb
|
|
|
+ beforeEach(function () {
|
|
|
+ el = document.createElement('div')
|
|
|
+ op = jasmine.createSpy('transition skip op')
|
|
|
+ cb = jasmine.createSpy('transition skip cb')
|
|
|
+ vm = new Vue()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('skip el with no transition data', function () {
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('skip vm still being compiled', function () {
|
|
|
+ el.__v_trans = { id: 'test' }
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('skip vm with parent still being compiled', function () {
|
|
|
+ el.__v_trans = { id: 'test' }
|
|
|
+ var child = vm.$addChild({
|
|
|
+ el: el
|
|
|
+ })
|
|
|
+ expect(child._isCompiled).toBe(true)
|
|
|
+ transition.apply(el, 1, op, child, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('skip when no transition available', function () {
|
|
|
+ var e = _.transitionEndEvent
|
|
|
+ _.transitionEndEvent = null
|
|
|
+ el.__v_trans = { id: 'test' }
|
|
|
+ vm.$mount(el)
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ _.transitionEndEvent = e
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ describe('CSS transitions', function () {
|
|
|
+
|
|
|
+ // insert a test css
|
|
|
+ function insertCSS (text) {
|
|
|
+ var cssEl = document.createElement('style')
|
|
|
+ cssEl.textContent = text
|
|
|
+ document.head.appendChild(cssEl)
|
|
|
+ }
|
|
|
+
|
|
|
+ insertCSS('.test {transition: opacity 16ms ease; -webkit-transition: opacity 20ms ease;}')
|
|
|
+ insertCSS('.test-enter, .test-leave { opacity: 0; }')
|
|
|
+ insertCSS(
|
|
|
+ '.test-anim-enter {\
|
|
|
+ animation: test-enter 16ms;\
|
|
|
+ -webkit-animation: test-enter 16ms;}\
|
|
|
+ .test-anim-leave {\
|
|
|
+ animation: test-leave 16ms;\
|
|
|
+ -webkit-animation: test-leave 16ms;}\
|
|
|
+ @keyframes test-enter {\
|
|
|
+ from { opacity: 0 }\
|
|
|
+ to { opacity: 1 }}\
|
|
|
+ @-webkit-keyframes test-enter {\
|
|
|
+ from { opacity: 0 }\
|
|
|
+ to { opacity: 1 }}\
|
|
|
+ @keyframes test-leave {\
|
|
|
+ from { opacity: 1 }\
|
|
|
+ to { opacity: 0 }}\
|
|
|
+ @-webkit-keyframes test-leave {\
|
|
|
+ from { opacity: 1 }\
|
|
|
+ to { opacity: 0 }}'
|
|
|
+ )
|
|
|
+
|
|
|
+ var vm, el, op, cb
|
|
|
+ beforeEach(function (done) {
|
|
|
+ el = document.createElement('div')
|
|
|
+ el.__v_trans = {}
|
|
|
+ vm = new Vue({ el: el })
|
|
|
+ op = jasmine.createSpy('css op')
|
|
|
+ cb = jasmine.createSpy('css cb')
|
|
|
+ document.body.appendChild(el)
|
|
|
+ // !IMPORTANT!
|
|
|
+ // this ensures we force a layout for every test.
|
|
|
+ _.nextTick(done)
|
|
|
+ })
|
|
|
+
|
|
|
+ afterEach(function () {
|
|
|
+ document.body.removeChild(el)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('skip on 0s duration', function () {
|
|
|
+ el.__v_trans.id = 'test'
|
|
|
+ el.style.transition =
|
|
|
+ el.style.WebkitTransition = 'opacity 0s ease'
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-enter')).toBe(false)
|
|
|
+ transition.apply(el, -1, op, vm, cb)
|
|
|
+ expect(op.calls.count()).toBe(2)
|
|
|
+ expect(cb.calls.count()).toBe(2)
|
|
|
+ expect(el.classList.contains('test-leave')).toBe(false)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('skip when no transition available', function () {
|
|
|
+ el.__v_trans.id = 'test-no-trans'
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-no-trans-enter')).toBe(false)
|
|
|
+ transition.apply(el, -1, op, vm, cb)
|
|
|
+ expect(op.calls.count()).toBe(2)
|
|
|
+ expect(cb.calls.count()).toBe(2)
|
|
|
+ expect(el.classList.contains('test-no-trans-leave')).toBe(false)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('transition enter', function (done) {
|
|
|
+ el.__v_trans.id = 'test'
|
|
|
+ // inline style
|
|
|
+ el.style.transition =
|
|
|
+ el.style.WebkitTransition = 'opacity .2s ease'
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).not.toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-enter')).toBe(false)
|
|
|
+ _.on(el, _.transitionEndEvent, function () {
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ done()
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it('transition leave', function (done) {
|
|
|
+ el.__v_trans.id = 'test'
|
|
|
+ // cascaded class style
|
|
|
+ el.classList.add('test')
|
|
|
+ transition.apply(el, -1, op, vm, cb)
|
|
|
+ expect(op).not.toHaveBeenCalled()
|
|
|
+ expect(cb).not.toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-leave')).toBe(true)
|
|
|
+ _.on(el, _.transitionEndEvent, function () {
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-leave')).toBe(false)
|
|
|
+ done()
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it('animation enter', function (done) {
|
|
|
+ el.__v_trans.id = 'test-anim'
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).not.toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-anim-enter')).toBe(true)
|
|
|
+ _.on(el, _.animationEndEvent, function () {
|
|
|
+ expect(el.classList.contains('test-anim-enter')).toBe(false)
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ done()
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it('animation leave', function (done) {
|
|
|
+ el.__v_trans.id = 'test-anim'
|
|
|
+ transition.apply(el, -1, op, vm, cb)
|
|
|
+ expect(op).not.toHaveBeenCalled()
|
|
|
+ expect(cb).not.toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-anim-leave')).toBe(true)
|
|
|
+ _.on(el, _.animationEndEvent, function () {
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-anim-leave')).toBe(false)
|
|
|
+ done()
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it('clean up unfinished callback', function (done) {
|
|
|
+ el.__v_trans.id = 'test'
|
|
|
+ el.classList.add('test')
|
|
|
+ transition.apply(el, -1, op, vm, cb)
|
|
|
+ expect(el.__v_trans.callback).toBeTruthy()
|
|
|
+ expect(el.classList.contains('test-leave')).toBe(true)
|
|
|
+ _.nextTick(function () {
|
|
|
+ transition.apply(el, 1, op, vm)
|
|
|
+ expect(cb).not.toHaveBeenCalled()
|
|
|
+ expect(el.classList.contains('test-leave')).toBe(false)
|
|
|
+ expect(el.__v_trans.callback).toBeNull()
|
|
|
+ done()
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ describe('JavaScript transitions', function () {
|
|
|
+
|
|
|
+ var el, vm, op, cb, def, emitter
|
|
|
+ beforeEach(function () {
|
|
|
+ emitter = {}
|
|
|
+ el = document.createElement('div')
|
|
|
+ el.__v_trans = { id: 'test' }
|
|
|
+ document.body.appendChild(el)
|
|
|
+ op = jasmine.createSpy('js transition op')
|
|
|
+ cb = jasmine.createSpy('js transition cb')
|
|
|
+ def = {}
|
|
|
+ vm = new Vue({
|
|
|
+ el: el,
|
|
|
+ transitions: {
|
|
|
+ test: def
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ afterEach(function () {
|
|
|
+ document.body.removeChild(el)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('beforeEnter', function () {
|
|
|
+ def.beforeEnter = jasmine.createSpy('js transition beforeEnter')
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(def.beforeEnter).toHaveBeenCalledWith(el)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('enter', function () {
|
|
|
+ var spy = jasmine.createSpy('js enter')
|
|
|
+ def.enter = function (e, done) {
|
|
|
+ expect(e).toBe(el)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ done()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ spy()
|
|
|
+ }
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(spy).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('leave', function () {
|
|
|
+ var spy = jasmine.createSpy('js leave')
|
|
|
+ def.leave = function (e, done) {
|
|
|
+ expect(e).toBe(el)
|
|
|
+ done()
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ spy()
|
|
|
+ }
|
|
|
+ transition.apply(el, -1, op, vm, cb)
|
|
|
+ expect(spy).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('no def', function () {
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ expect(op).toHaveBeenCalled()
|
|
|
+ expect(cb).toHaveBeenCalled()
|
|
|
+ transition.apply(el, -1, op, vm, cb)
|
|
|
+ expect(op.calls.count()).toBe(2)
|
|
|
+ expect(cb.calls.count()).toBe(2)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('optional cleanup callback', function (done) {
|
|
|
+ var cleanupSpy = jasmine.createSpy('js cleanup')
|
|
|
+ var leaveSpy = jasmine.createSpy('js leave')
|
|
|
+ def.enter = function (el, done) {
|
|
|
+ var to = setTimeout(done, 10)
|
|
|
+ return function () {
|
|
|
+ clearTimeout(to)
|
|
|
+ cleanupSpy()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ def.leave = function (el, done) {
|
|
|
+ expect(cleanupSpy).toHaveBeenCalled()
|
|
|
+ leaveSpy()
|
|
|
+ done()
|
|
|
+ }
|
|
|
+ transition.apply(el, 1, op, vm, cb)
|
|
|
+ setTimeout(function () {
|
|
|
+ transition.apply(el, -1, op, vm)
|
|
|
+ expect(leaveSpy).toHaveBeenCalled()
|
|
|
+ setTimeout(function () {
|
|
|
+ expect(cb).not.toHaveBeenCalled()
|
|
|
+ done()
|
|
|
+ }, 10)
|
|
|
+ }, 1)
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+}
|