vue3-yuanma/packages/observer/__tests__/computed.spec.ts

140 lines
3.5 KiB
TypeScript
Raw Normal View History

2018-11-14 00:03:35 +08:00
import { computed, observable, effect, stop } from '../src'
2018-09-21 06:03:59 +08:00
describe('observer/computed', () => {
it('should return updated value', () => {
const value: any = observable({})
const cValue = computed(() => value.foo)
expect(cValue()).toBe(undefined)
value.foo = 1
expect(cValue()).toBe(1)
})
it('should compute lazily', () => {
const value: any = observable({})
const getter = jest.fn(() => value.foo)
const cValue = computed(getter)
// lazy
expect(getter).not.toHaveBeenCalled()
expect(cValue()).toBe(undefined)
expect(getter).toHaveBeenCalledTimes(1)
// should not compute again
cValue()
expect(getter).toHaveBeenCalledTimes(1)
// should not compute until needed
value.foo = 1
expect(getter).toHaveBeenCalledTimes(1)
// now it should compute
expect(cValue()).toBe(1)
expect(getter).toHaveBeenCalledTimes(2)
// should not compute again
cValue()
expect(getter).toHaveBeenCalledTimes(2)
})
it('should accept context', () => {
const value: any = observable({})
let callCtx, callArg
const getter = function(arg: any) {
callCtx = this
callArg = arg
return value.foo
}
const ctx = {}
const cValue = computed(getter, ctx)
cValue()
expect(callCtx).toBe(ctx)
expect(callArg).toBe(ctx)
})
2018-11-14 00:03:35 +08:00
it('should trigger effect', () => {
2018-09-21 06:03:59 +08:00
const value: any = observable({})
const cValue = computed(() => value.foo)
let dummy
2018-11-14 00:03:35 +08:00
effect(() => {
2018-09-21 06:03:59 +08:00
dummy = cValue()
})
expect(dummy).toBe(undefined)
value.foo = 1
expect(dummy).toBe(1)
})
it('should work when chained', () => {
const value: any = observable({ foo: 0 })
const c1 = computed(() => value.foo)
const c2 = computed(() => c1() + 1)
expect(c2()).toBe(1)
expect(c1()).toBe(0)
value.foo++
expect(c2()).toBe(2)
expect(c1()).toBe(1)
})
2018-11-14 00:03:35 +08:00
it('should trigger effect when chained', () => {
2018-09-21 06:03:59 +08:00
const value: any = observable({ foo: 0 })
const getter1 = jest.fn(() => value.foo)
const getter2 = jest.fn(() => {
return c1() + 1
})
const c1 = computed(getter1)
const c2 = computed(getter2)
let dummy
2018-11-14 00:03:35 +08:00
effect(() => {
2018-09-21 06:03:59 +08:00
dummy = c2()
})
expect(dummy).toBe(1)
expect(getter1).toHaveBeenCalledTimes(1)
expect(getter2).toHaveBeenCalledTimes(1)
value.foo++
expect(dummy).toBe(2)
// should not result in duplicate calls
expect(getter1).toHaveBeenCalledTimes(2)
expect(getter2).toHaveBeenCalledTimes(2)
})
2018-11-14 00:03:35 +08:00
it('should trigger effect when chained (mixed invocations)', () => {
2018-09-21 06:03:59 +08:00
const value: any = observable({ foo: 0 })
const getter1 = jest.fn(() => value.foo)
const getter2 = jest.fn(() => {
return c1() + 1
})
const c1 = computed(getter1)
const c2 = computed(getter2)
let dummy
2018-11-14 00:03:35 +08:00
effect(() => {
2018-09-21 06:03:59 +08:00
dummy = c1() + c2()
})
expect(dummy).toBe(1)
expect(getter1).toHaveBeenCalledTimes(1)
expect(getter2).toHaveBeenCalledTimes(1)
value.foo++
expect(dummy).toBe(3)
// should not result in duplicate calls
expect(getter1).toHaveBeenCalledTimes(2)
expect(getter2).toHaveBeenCalledTimes(2)
})
it('should no longer update when stopped', () => {
const value: any = observable({})
const cValue = computed(() => value.foo)
let dummy
2018-11-14 00:03:35 +08:00
effect(() => {
2018-09-21 06:03:59 +08:00
dummy = cValue()
})
expect(dummy).toBe(undefined)
value.foo = 1
expect(dummy).toBe(1)
2018-11-14 00:03:35 +08:00
stop(cValue.effect)
2018-09-21 06:03:59 +08:00
value.foo = 2
expect(dummy).toBe(1)
})
})