test: wip tests for BaseTransition
This commit is contained in:
		
							parent
							
								
									460b053f74
								
							
						
					
					
						commit
						bb39910e8e
					
				| @ -0,0 +1,176 @@ | |||||||
|  | import { | ||||||
|  |   nodeOps, | ||||||
|  |   render, | ||||||
|  |   h, | ||||||
|  |   BaseTransition, | ||||||
|  |   BaseTransitionProps, | ||||||
|  |   ref, | ||||||
|  |   nextTick, | ||||||
|  |   serializeInner | ||||||
|  | } from '@vue/runtime-test' | ||||||
|  | 
 | ||||||
|  | function mount(props: BaseTransitionProps, slot: () => any) { | ||||||
|  |   const root = nodeOps.createElement('div') | ||||||
|  |   render(h(BaseTransition, props, slot), root) | ||||||
|  |   return root | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function mockProps() { | ||||||
|  |   const cbs = { | ||||||
|  |     doneEnter: () => {}, | ||||||
|  |     doneLeave: () => {} | ||||||
|  |   } | ||||||
|  |   const props: BaseTransitionProps = { | ||||||
|  |     onBeforeEnter: jest.fn(el => { | ||||||
|  |       expect(el.parentNode).toBeNull() | ||||||
|  |     }), | ||||||
|  |     onEnter: jest.fn((el, done) => { | ||||||
|  |       cbs.doneEnter = done | ||||||
|  |     }), | ||||||
|  |     onAfterEnter: jest.fn(), | ||||||
|  |     onEnterCancelled: jest.fn(), | ||||||
|  |     onBeforeLeave: jest.fn(), | ||||||
|  |     onLeave: jest.fn((el, done) => { | ||||||
|  |       cbs.doneLeave = done | ||||||
|  |     }), | ||||||
|  |     onAfterLeave: jest.fn(), | ||||||
|  |     onLeaveCancelled: jest.fn() | ||||||
|  |   } | ||||||
|  |   return { | ||||||
|  |     props, | ||||||
|  |     cbs | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function assertCalls( | ||||||
|  |   props: BaseTransitionProps, | ||||||
|  |   calls: Record<string, number> | ||||||
|  | ) { | ||||||
|  |   Object.keys(calls).forEach((key: keyof BaseTransitionProps) => { | ||||||
|  |     expect(props[key]).toHaveBeenCalledTimes(calls[key]) | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | describe('BaseTransition', () => { | ||||||
|  |   describe('with elements', () => { | ||||||
|  |     test('toggle on-off', async () => { | ||||||
|  |       const toggle = ref(true) | ||||||
|  |       const { props, cbs } = mockProps() | ||||||
|  |       const root = mount(props, () => (toggle.value ? h('div') : null)) | ||||||
|  | 
 | ||||||
|  |       // without appear: true, enter hooks should not be called on mount
 | ||||||
|  |       expect(props.onBeforeEnter).not.toHaveBeenCalled() | ||||||
|  |       expect(props.onEnter).not.toHaveBeenCalled() | ||||||
|  |       expect(props.onAfterEnter).not.toHaveBeenCalled() | ||||||
|  | 
 | ||||||
|  |       toggle.value = false | ||||||
|  |       await nextTick() | ||||||
|  |       // comment placeholder enters immediately
 | ||||||
|  |       expect(serializeInner(root)).toBe('<div></div><!---->') | ||||||
|  |       expect(props.onBeforeLeave).toHaveBeenCalledTimes(1) | ||||||
|  |       expect(props.onLeave).toHaveBeenCalledTimes(1) | ||||||
|  |       expect(props.onAfterLeave).not.toHaveBeenCalled() | ||||||
|  |       cbs.doneLeave() | ||||||
|  |       expect(serializeInner(root)).toBe('<!---->') | ||||||
|  |       expect(props.onAfterLeave).toHaveBeenCalledTimes(1) | ||||||
|  | 
 | ||||||
|  |       toggle.value = true | ||||||
|  |       await nextTick() | ||||||
|  |       expect(serializeInner(root)).toBe('<div></div>') | ||||||
|  |       // before enter spy asserts node has no parent when it's called
 | ||||||
|  |       expect(props.onBeforeEnter).toHaveBeenCalledTimes(1) | ||||||
|  |       expect(props.onEnter).toHaveBeenCalledTimes(1) | ||||||
|  |       expect(props.onAfterEnter).not.toHaveBeenCalled() | ||||||
|  |       cbs.doneEnter() | ||||||
|  |       expect(props.onAfterEnter).toHaveBeenCalledTimes(1) | ||||||
|  | 
 | ||||||
|  |       assertCalls(props, { | ||||||
|  |         onBeforeEnter: 1, | ||||||
|  |         onEnter: 1, | ||||||
|  |         onAfterEnter: 1, | ||||||
|  |         onEnterCancelled: 0, | ||||||
|  |         onBeforeLeave: 1, | ||||||
|  |         onLeave: 1, | ||||||
|  |         onAfterLeave: 1, | ||||||
|  |         onLeaveCancelled: 0 | ||||||
|  |       }) | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     test('toggle before finish', async () => { | ||||||
|  |       const toggle = ref(false) | ||||||
|  |       const { props, cbs } = mockProps() | ||||||
|  |       const root = mount(props, () => (toggle.value ? h('div') : null)) | ||||||
|  | 
 | ||||||
|  |       // start enter
 | ||||||
|  |       toggle.value = true | ||||||
|  |       await nextTick() | ||||||
|  |       expect(serializeInner(root)).toBe(`<div></div>`) | ||||||
|  |       expect(props.onBeforeEnter).toHaveBeenCalledTimes(1) | ||||||
|  |       expect(props.onEnter).toHaveBeenCalledTimes(1) | ||||||
|  | 
 | ||||||
|  |       // leave before enter finishes
 | ||||||
|  |       toggle.value = false | ||||||
|  |       await nextTick() | ||||||
|  |       expect(serializeInner(root)).toBe(`<div></div><!---->`) | ||||||
|  |       expect(props.onEnterCancelled).toHaveBeenCalled() | ||||||
|  |       expect(props.onBeforeLeave).toHaveBeenCalledTimes(1) | ||||||
|  |       expect(props.onLeave).toHaveBeenCalledTimes(1) | ||||||
|  |       expect(props.onAfterLeave).not.toHaveBeenCalled() | ||||||
|  |       // calling doneEnter now should have no effect
 | ||||||
|  |       cbs.doneEnter() | ||||||
|  |       expect(props.onAfterEnter).not.toHaveBeenCalled() | ||||||
|  | 
 | ||||||
|  |       // enter again before leave finishes
 | ||||||
|  |       toggle.value = true | ||||||
|  |       await nextTick() | ||||||
|  |       expect(props.onBeforeEnter).toHaveBeenCalledTimes(2) | ||||||
|  |       expect(props.onEnter).toHaveBeenCalledTimes(2) | ||||||
|  |       // 1. should remove the previous leaving <div> so there is only one <div>
 | ||||||
|  |       // 2. should remove the comment placeholder for the off branch
 | ||||||
|  |       expect(serializeInner(root)).toBe(`<div></div>`) | ||||||
|  |       // note onLeaveCancelled is NOT called because it was a forced early
 | ||||||
|  |       // removal instead of a cancel. Instead, onAfterLeave should be called.
 | ||||||
|  |       expect(props.onAfterLeave).toHaveBeenCalledTimes(1) | ||||||
|  |       // calling doneLeave again should have no effect now
 | ||||||
|  |       cbs.doneLeave() | ||||||
|  |       expect(props.onAfterLeave).toHaveBeenCalledTimes(1) | ||||||
|  |       cbs.doneEnter() | ||||||
|  |       expect(props.onAfterEnter).toHaveBeenCalledTimes(1) | ||||||
|  | 
 | ||||||
|  |       assertCalls(props, { | ||||||
|  |         onBeforeEnter: 2, | ||||||
|  |         onEnter: 2, | ||||||
|  |         onAfterEnter: 1, | ||||||
|  |         onEnterCancelled: 1, | ||||||
|  |         onBeforeLeave: 1, | ||||||
|  |         onLeave: 1, | ||||||
|  |         onAfterLeave: 1, | ||||||
|  |         onLeaveCancelled: 0 | ||||||
|  |       }) | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     test('toggle between branches', () => {}) | ||||||
|  | 
 | ||||||
|  |     test('toggle between branches before finish', () => {}) | ||||||
|  | 
 | ||||||
|  |     test('persisted: true', () => { | ||||||
|  |       // test onLeaveCancelled
 | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     test('appear: true', () => {}) | ||||||
|  | 
 | ||||||
|  |     test('mode: "out-in"', () => {}) | ||||||
|  | 
 | ||||||
|  |     test('mode: "out-in" toggle before finish', () => {}) | ||||||
|  | 
 | ||||||
|  |     test('mode: "in-out" toggle before finish', () => {}) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   describe('with components', () => { | ||||||
|  |     // TODO
 | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   describe('with KeepAlive', () => { | ||||||
|  |     // TODO
 | ||||||
|  |   }) | ||||||
|  | }) | ||||||
| @ -11,7 +11,7 @@ import { | |||||||
| } from '@vue/runtime-test' | } from '@vue/runtime-test' | ||||||
| import { KeepAliveProps } from '../../src/components/KeepAlive' | import { KeepAliveProps } from '../../src/components/KeepAlive' | ||||||
| 
 | 
 | ||||||
| describe('keep-alive', () => { | describe('KeepAlive', () => { | ||||||
|   let one: ComponentOptions |   let one: ComponentOptions | ||||||
|   let two: ComponentOptions |   let two: ComponentOptions | ||||||
|   let views: Record<string, ComponentOptions> |   let views: Record<string, ComponentOptions> | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ import { | |||||||
|   onErrorCaptured |   onErrorCaptured | ||||||
| } from '@vue/runtime-test' | } from '@vue/runtime-test' | ||||||
| 
 | 
 | ||||||
| describe('renderer: suspense', () => { | describe('Suspense', () => { | ||||||
|   const deps: Promise<any>[] = [] |   const deps: Promise<any>[] = [] | ||||||
| 
 | 
 | ||||||
|   beforeEach(() => { |   beforeEach(() => { | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ export interface BaseTransitionProps { | |||||||
|   onBeforeLeave?: (el: any) => void |   onBeforeLeave?: (el: any) => void | ||||||
|   onLeave?: (el: any, done: () => void) => void |   onLeave?: (el: any, done: () => void) => void | ||||||
|   onAfterLeave?: (el: any) => void |   onAfterLeave?: (el: any) => void | ||||||
|   onLeaveCancelled?: (el: any) => void |   onLeaveCancelled?: (el: any) => void // only fired in persisted mode
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface TransitionHooks { | export interface TransitionHooks { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user