test: test for computed optimization

This commit is contained in:
Evan You 2021-07-07 10:10:56 -04:00
parent ebaac9a56d
commit bde855e017
2 changed files with 90 additions and 2 deletions

View File

@ -4,7 +4,8 @@ import {
effect,
ref,
WritableComputedRef,
isReadonly
isReadonly,
setComputedScheduler
} from '../src'
describe('reactivity/computed', () => {
@ -198,4 +199,58 @@ describe('reactivity/computed', () => {
x.effect.stop()
expect(x.value).toBe(1)
})
describe('with scheduler', () => {
const p = Promise.resolve()
const defer = (fn?: any) => (fn ? p.then(fn) : p)
beforeEach(() => {
setComputedScheduler(defer)
})
afterEach(() => {
setComputedScheduler(undefined)
})
test('should only trigger once on multiple mutations', async () => {
const src = ref(0)
const c = computed(() => src.value)
const spy = jest.fn()
effect(() => {
spy(c.value)
})
expect(spy).toHaveBeenCalledTimes(1)
src.value = 1
src.value = 2
src.value = 3
// not called yet
expect(spy).toHaveBeenCalledTimes(1)
await defer()
// should only trigger once
expect(spy).toHaveBeenCalledTimes(2)
expect(spy).toHaveBeenCalledWith(c.value)
})
test('should not trigger if value did not change', async () => {
const src = ref(0)
const c = computed(() => src.value % 2)
const spy = jest.fn()
effect(() => {
spy(c.value)
})
expect(spy).toHaveBeenCalledTimes(1)
src.value = 1
src.value = 2
await defer()
// should not trigger
expect(spy).toHaveBeenCalledTimes(1)
src.value = 3
src.value = 4
src.value = 5
await defer()
// should trigger because latest value changes
expect(spy).toHaveBeenCalledTimes(2)
})
})
})

View File

@ -10,7 +10,8 @@ import {
inject,
Ref,
watch,
SetupContext
SetupContext,
computed
} from '@vue/runtime-test'
describe('renderer: component', () => {
@ -321,4 +322,36 @@ describe('renderer: component', () => {
expect(serializeInner(root)).toBe(``)
expect(ids).toEqual([ids[0], ids[0] + 1, ids[0] + 2])
})
test('computed that did not change should not trigger re-render', async () => {
const src = ref(0)
const c = computed(() => src.value % 2)
const spy = jest.fn()
const App = {
render() {
spy()
return c.value
}
}
const root = nodeOps.createElement('div')
render(h(App), root)
expect(serializeInner(root)).toBe(`0`)
expect(spy).toHaveBeenCalledTimes(1)
// verify it updates
src.value = 1
src.value = 2
src.value = 3
await nextTick()
expect(serializeInner(root)).toBe(`1`)
expect(spy).toHaveBeenCalledTimes(2) // should only update once
// verify it updates
src.value = 4
src.value = 5
await nextTick()
expect(serializeInner(root)).toBe(`1`)
expect(spy).toHaveBeenCalledTimes(2) // should not need to update
})
})