test(transition): test for mode: out-in
This commit is contained in:
parent
7209fb66c2
commit
7aac3418c0
@ -16,7 +16,7 @@ function mount(props: BaseTransitionProps, slot: () => any) {
|
|||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
function mockProps() {
|
function mockProps(extra: BaseTransitionProps = {}) {
|
||||||
const cbs: {
|
const cbs: {
|
||||||
doneEnter: Record<string, () => void>
|
doneEnter: Record<string, () => void>
|
||||||
doneLeave: Record<string, () => void>
|
doneLeave: Record<string, () => void>
|
||||||
@ -38,7 +38,8 @@ function mockProps() {
|
|||||||
cbs.doneLeave[serialize(el)] = done
|
cbs.doneLeave[serialize(el)] = done
|
||||||
}),
|
}),
|
||||||
onAfterLeave: jest.fn(),
|
onAfterLeave: jest.fn(),
|
||||||
onLeaveCancelled: jest.fn()
|
onLeaveCancelled: jest.fn(),
|
||||||
|
...extra
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
props,
|
props,
|
||||||
@ -66,6 +67,28 @@ interface ToggleOptions {
|
|||||||
falseSerialized: string
|
falseSerialized: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function runTestWithElements(tester: (o: ToggleOptions) => void) {
|
||||||
|
await tester({
|
||||||
|
trueBranch: () => h('div'),
|
||||||
|
falseBranch: () => h('span'),
|
||||||
|
trueSerialized: `<div></div>`,
|
||||||
|
falseSerialized: `<span></span>`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runTestWithComponents(tester: (o: ToggleOptions) => void) {
|
||||||
|
const CompA = ({ msg }: { msg: string }) => h('div', msg)
|
||||||
|
// test HOC
|
||||||
|
const CompB = ({ msg }: { msg: string }) => h(CompC, { msg })
|
||||||
|
const CompC = ({ msg }: { msg: string }) => h('span', msg)
|
||||||
|
await tester({
|
||||||
|
trueBranch: () => h(CompA, { msg: 'foo' }),
|
||||||
|
falseBranch: () => h(CompB, { msg: 'bar' }),
|
||||||
|
trueSerialized: `<div>foo</div>`,
|
||||||
|
falseSerialized: `<span>bar</span>`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
describe('BaseTransition', () => {
|
describe('BaseTransition', () => {
|
||||||
describe('toggle on-off', () => {
|
describe('toggle on-off', () => {
|
||||||
async function testToggleOnOff({
|
async function testToggleOnOff({
|
||||||
@ -317,25 +340,11 @@ describe('BaseTransition', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test('w/ elements', async () => {
|
test('w/ elements', async () => {
|
||||||
await testToggleBranches({
|
await runTestWithElements(testToggleBranches)
|
||||||
trueBranch: () => h('div'),
|
|
||||||
falseBranch: () => h('span'),
|
|
||||||
trueSerialized: `<div></div>`,
|
|
||||||
falseSerialized: `<span></span>`
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('w/ components', async () => {
|
test('w/ components', async () => {
|
||||||
const CompA = ({ msg }: { msg: string }) => h('div', msg)
|
await runTestWithComponents(testToggleBranches)
|
||||||
// test HOC
|
|
||||||
const CompB = ({ msg }: { msg: string }) => h(CompC, { msg })
|
|
||||||
const CompC = ({ msg }: { msg: string }) => h('span', msg)
|
|
||||||
await testToggleBranches({
|
|
||||||
trueBranch: () => h(CompA, { msg: 'foo' }),
|
|
||||||
falseBranch: () => h(CompB, { msg: 'bar' }),
|
|
||||||
trueSerialized: `<div>foo</div>`,
|
|
||||||
falseSerialized: `<span>bar</span>`
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -441,31 +450,249 @@ describe('BaseTransition', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test('w/ elements', async () => {
|
test('w/ elements', async () => {
|
||||||
await testToggleBranchesBeforeFinish({
|
await runTestWithElements(testToggleBranchesBeforeFinish)
|
||||||
trueBranch: () => h('div'),
|
|
||||||
falseBranch: () => h('span'),
|
|
||||||
trueSerialized: `<div></div>`,
|
|
||||||
falseSerialized: `<span></span>`
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('w/ components', async () => {
|
test('w/ components', async () => {
|
||||||
const CompA = ({ msg }: { msg: string }) => h('div', msg)
|
await runTestWithComponents(testToggleBranchesBeforeFinish)
|
||||||
// test HOC
|
|
||||||
const CompB = ({ msg }: { msg: string }) => h(CompC, { msg })
|
|
||||||
const CompC = ({ msg }: { msg: string }) => h('span', msg)
|
|
||||||
await testToggleBranchesBeforeFinish({
|
|
||||||
trueBranch: () => h(CompA, { msg: 'foo' }),
|
|
||||||
falseBranch: () => h(CompB, { msg: 'bar' }),
|
|
||||||
trueSerialized: `<div>foo</div>`,
|
|
||||||
falseSerialized: `<span>bar</span>`
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('mode: "out-in"', () => {})
|
describe('mode: "out-in"', () => {
|
||||||
|
async function testOutIn({
|
||||||
|
trueBranch,
|
||||||
|
falseBranch,
|
||||||
|
trueSerialized,
|
||||||
|
falseSerialized
|
||||||
|
}: ToggleOptions) {
|
||||||
|
const toggle = ref(true)
|
||||||
|
const { props, cbs } = mockProps({ mode: 'out-in' })
|
||||||
|
const root = mount(
|
||||||
|
props,
|
||||||
|
() => (toggle.value ? trueBranch() : falseBranch())
|
||||||
|
)
|
||||||
|
|
||||||
describe('mode: "out-in" toggle before finish', () => {})
|
// trigger toggle
|
||||||
|
toggle.value = false
|
||||||
|
await nextTick()
|
||||||
|
// a placeholder is injected until the leave finishes
|
||||||
|
expect(serializeInner(root)).toBe(`${trueSerialized}<!---->`)
|
||||||
|
expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onBeforeLeave, trueSerialized)
|
||||||
|
expect(props.onLeave).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onLeave, trueSerialized)
|
||||||
|
expect(props.onAfterLeave).not.toHaveBeenCalled()
|
||||||
|
// enter should not have started
|
||||||
|
expect(props.onBeforeEnter).not.toHaveBeenCalled()
|
||||||
|
expect(props.onEnter).not.toHaveBeenCalled()
|
||||||
|
expect(props.onAfterEnter).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
cbs.doneLeave[trueSerialized]()
|
||||||
|
expect(props.onAfterLeave).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onAfterLeave, trueSerialized)
|
||||||
|
// have to wait for a tick because this triggers an update
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toBe(falseSerialized)
|
||||||
|
// enter should start
|
||||||
|
expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onBeforeEnter, falseSerialized)
|
||||||
|
expect(props.onEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onEnter, falseSerialized)
|
||||||
|
expect(props.onAfterEnter).not.toHaveBeenCalled()
|
||||||
|
// finish enter
|
||||||
|
cbs.doneEnter[falseSerialized]()
|
||||||
|
expect(props.onAfterEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onAfterEnter, falseSerialized)
|
||||||
|
|
||||||
|
// toggele again
|
||||||
|
toggle.value = true
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toBe(`${falseSerialized}<!---->`)
|
||||||
|
expect(props.onBeforeLeave).toHaveBeenCalledTimes(2)
|
||||||
|
assertCalledWithEl(props.onBeforeLeave, falseSerialized, 1)
|
||||||
|
expect(props.onLeave).toHaveBeenCalledTimes(2)
|
||||||
|
assertCalledWithEl(props.onLeave, falseSerialized, 1)
|
||||||
|
expect(props.onAfterLeave).toHaveBeenCalledTimes(1)
|
||||||
|
// enter should not have started
|
||||||
|
expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)
|
||||||
|
expect(props.onEnter).toHaveBeenCalledTimes(1)
|
||||||
|
expect(props.onAfterEnter).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
cbs.doneLeave[falseSerialized]()
|
||||||
|
expect(props.onAfterLeave).toHaveBeenCalledTimes(2)
|
||||||
|
assertCalledWithEl(props.onAfterLeave, falseSerialized, 1)
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toBe(trueSerialized)
|
||||||
|
// enter should start
|
||||||
|
expect(props.onBeforeEnter).toHaveBeenCalledTimes(2)
|
||||||
|
assertCalledWithEl(props.onBeforeEnter, trueSerialized, 1)
|
||||||
|
expect(props.onEnter).toHaveBeenCalledTimes(2)
|
||||||
|
assertCalledWithEl(props.onEnter, trueSerialized, 1)
|
||||||
|
expect(props.onAfterEnter).toHaveBeenCalledTimes(1)
|
||||||
|
// finish enter
|
||||||
|
cbs.doneEnter[trueSerialized]()
|
||||||
|
expect(props.onAfterEnter).toHaveBeenCalledTimes(2)
|
||||||
|
assertCalledWithEl(props.onAfterEnter, trueSerialized, 1)
|
||||||
|
|
||||||
|
assertCalls(props, {
|
||||||
|
onBeforeEnter: 2,
|
||||||
|
onEnter: 2,
|
||||||
|
onAfterEnter: 2,
|
||||||
|
onEnterCancelled: 0,
|
||||||
|
onBeforeLeave: 2,
|
||||||
|
onLeave: 2,
|
||||||
|
onAfterLeave: 2,
|
||||||
|
onLeaveCancelled: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
test('w/ elements', async () => {
|
||||||
|
await runTestWithElements(testOutIn)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('w/ components', async () => {
|
||||||
|
await runTestWithComponents(testOutIn)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('mode: "out-in" toggle before finish', () => {
|
||||||
|
async function testOutInBeforeFinish({
|
||||||
|
trueBranch,
|
||||||
|
falseBranch,
|
||||||
|
trueSerialized,
|
||||||
|
falseSerialized
|
||||||
|
}: ToggleOptions) {
|
||||||
|
const toggle = ref(true)
|
||||||
|
const { props, cbs } = mockProps({ mode: 'out-in' })
|
||||||
|
const root = mount(
|
||||||
|
props,
|
||||||
|
() => (toggle.value ? trueBranch() : falseBranch())
|
||||||
|
)
|
||||||
|
|
||||||
|
// trigger toggle
|
||||||
|
toggle.value = false
|
||||||
|
await nextTick()
|
||||||
|
// toggle again before finish
|
||||||
|
toggle.value = true
|
||||||
|
await nextTick()
|
||||||
|
// expected behavior: the previous true branch is preserved,
|
||||||
|
// and a placeholder is injected for the replacement.
|
||||||
|
// the leaving node is repalced with the replace node (of the same branch)
|
||||||
|
// when it finishes leaving
|
||||||
|
expect(serializeInner(root)).toBe(`${trueSerialized}<!---->`)
|
||||||
|
// enter hooks should never be called (for neither branch)
|
||||||
|
expect(props.onBeforeEnter).not.toHaveBeenCalled()
|
||||||
|
expect(props.onEnter).not.toHaveBeenCalled()
|
||||||
|
expect(props.onAfterEnter).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
// finish leave
|
||||||
|
cbs.doneLeave[trueSerialized]()
|
||||||
|
expect(props.onAfterLeave).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onAfterLeave, trueSerialized)
|
||||||
|
await nextTick()
|
||||||
|
// leaving node and placeholder removed, enter node injected
|
||||||
|
expect(serializeInner(root)).toBe(trueSerialized)
|
||||||
|
// enter should start
|
||||||
|
expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onBeforeEnter, trueSerialized)
|
||||||
|
expect(props.onEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onEnter, trueSerialized)
|
||||||
|
expect(props.onAfterEnter).not.toHaveBeenCalled()
|
||||||
|
// finish enter
|
||||||
|
cbs.doneEnter[trueSerialized]()
|
||||||
|
expect(props.onAfterEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onAfterEnter, trueSerialized)
|
||||||
|
|
||||||
|
assertCalls(props, {
|
||||||
|
onBeforeEnter: 1,
|
||||||
|
onEnter: 1,
|
||||||
|
onAfterEnter: 1,
|
||||||
|
onEnterCancelled: 0,
|
||||||
|
onBeforeLeave: 1,
|
||||||
|
onLeave: 1,
|
||||||
|
onAfterLeave: 1,
|
||||||
|
onLeaveCancelled: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
test('w/ elements', async () => {
|
||||||
|
await runTestWithElements(testOutInBeforeFinish)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('w/ components', async () => {
|
||||||
|
await runTestWithComponents(testOutInBeforeFinish)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('mode: "out-in" double quick toggle', () => {
|
||||||
|
async function testOutInDoubleToggle({
|
||||||
|
trueBranch,
|
||||||
|
falseBranch,
|
||||||
|
trueSerialized,
|
||||||
|
falseSerialized
|
||||||
|
}: ToggleOptions) {
|
||||||
|
const toggle = ref(true)
|
||||||
|
const { props, cbs } = mockProps({ mode: 'out-in' })
|
||||||
|
const root = mount(
|
||||||
|
props,
|
||||||
|
() => (toggle.value ? trueBranch() : falseBranch())
|
||||||
|
)
|
||||||
|
|
||||||
|
// double quick toggle
|
||||||
|
toggle.value = false
|
||||||
|
await nextTick()
|
||||||
|
toggle.value = true
|
||||||
|
await nextTick()
|
||||||
|
toggle.value = false
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
// expected behavior: the leaving true branch is preserved no matter
|
||||||
|
// how many times the state is toggled as long as the leave isn't finished
|
||||||
|
// yet. A placeholder is injected for the replacement.
|
||||||
|
expect(serializeInner(root)).toBe(`${trueSerialized}<!---->`)
|
||||||
|
// enter hooks should never be called (for neither branch)
|
||||||
|
expect(props.onBeforeEnter).not.toHaveBeenCalled()
|
||||||
|
expect(props.onEnter).not.toHaveBeenCalled()
|
||||||
|
expect(props.onAfterEnter).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
// finish leave
|
||||||
|
cbs.doneLeave[trueSerialized]()
|
||||||
|
expect(props.onAfterLeave).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onAfterLeave, trueSerialized)
|
||||||
|
await nextTick()
|
||||||
|
// leaving node and placeholder removed, enter node injected
|
||||||
|
expect(serializeInner(root)).toBe(falseSerialized)
|
||||||
|
// enter should start
|
||||||
|
expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onBeforeEnter, falseSerialized)
|
||||||
|
expect(props.onEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onEnter, falseSerialized)
|
||||||
|
expect(props.onAfterEnter).not.toHaveBeenCalled()
|
||||||
|
// finish enter
|
||||||
|
cbs.doneEnter[falseSerialized]()
|
||||||
|
expect(props.onAfterEnter).toHaveBeenCalledTimes(1)
|
||||||
|
assertCalledWithEl(props.onAfterEnter, falseSerialized)
|
||||||
|
|
||||||
|
assertCalls(props, {
|
||||||
|
onBeforeEnter: 1,
|
||||||
|
onEnter: 1,
|
||||||
|
onAfterEnter: 1,
|
||||||
|
onEnterCancelled: 0,
|
||||||
|
onBeforeLeave: 1,
|
||||||
|
onLeave: 1,
|
||||||
|
onAfterLeave: 1,
|
||||||
|
onLeaveCancelled: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
test('w/ elements', async () => {
|
||||||
|
await runTestWithElements(testOutInDoubleToggle)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('w/ components', async () => {
|
||||||
|
await runTestWithComponents(testOutInDoubleToggle)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('mode: "in-out"', () => {})
|
describe('mode: "in-out"', () => {})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user