mirror of
https://github.com/zhigang1992/mobx-utils.git
synced 2026-06-14 17:58:58 +08:00
181 lines
3.9 KiB
TypeScript
181 lines
3.9 KiB
TypeScript
import { computedFn } from "../src/computedFn"
|
|
import {
|
|
observable,
|
|
autorun,
|
|
onBecomeUnobserved,
|
|
action,
|
|
getDependencyTree,
|
|
comparer,
|
|
getObserverTree,
|
|
} from "mobx"
|
|
|
|
const john = {
|
|
name: "john",
|
|
age: 15,
|
|
}
|
|
const jane = {
|
|
name: "jane",
|
|
age: 45,
|
|
}
|
|
const able = {
|
|
name: "able",
|
|
age: 12,
|
|
}
|
|
|
|
class Store {
|
|
persons = observable([john, jane, able])
|
|
|
|
constructor(public events: string[]) {}
|
|
|
|
filter(age: number, firstLetter: string) {
|
|
this.events.push(`f ${age} ${firstLetter}`)
|
|
return this.persons.filter((p) => {
|
|
return p.age > age && (!firstLetter || p.name[0] === firstLetter)
|
|
})
|
|
}
|
|
}
|
|
|
|
test("basics - kept alive", () => {
|
|
const events: string[] = []
|
|
const s = new Store(events)
|
|
|
|
onBecomeUnobserved(s.persons, () => {
|
|
events.push("unobserved persons")
|
|
})
|
|
|
|
s.filter = computedFn(s.filter, true)
|
|
|
|
expect(s.filter(20, "")).toEqual([jane])
|
|
expect(s.filter(1, "j")).toEqual([john, jane])
|
|
expect(s.filter(20, "")).toEqual([jane])
|
|
|
|
expect(events.splice(0)).toEqual(["f 20 ", "f 1 j"])
|
|
|
|
const d = autorun(() => {
|
|
events.push(
|
|
s
|
|
.filter(1, "j")
|
|
.map((p) => p.name)
|
|
.join("-")
|
|
)
|
|
})
|
|
|
|
s.persons[2].name = "jable"
|
|
s.persons[1].name = "ane"
|
|
|
|
s.persons[2].age = 0
|
|
|
|
d()
|
|
|
|
expect(s.filter(20, "")).toEqual([{ name: "ane", age: 45 }])
|
|
expect(s.filter(20, "")).toEqual([{ name: "ane", age: 45 }])
|
|
|
|
expect(events.splice(0)).toEqual([
|
|
"john-jane",
|
|
"f 1 j",
|
|
"john-jane-jable",
|
|
"f 1 j",
|
|
"john-jable",
|
|
"f 1 j",
|
|
"john",
|
|
"f 20 ",
|
|
])
|
|
})
|
|
|
|
test("basics - auto suspend", () => {
|
|
const events: string[] = []
|
|
const s = new Store(events)
|
|
|
|
onBecomeUnobserved(s.persons, () => {
|
|
events.push("unobserved persons")
|
|
})
|
|
|
|
s.filter = computedFn(s.filter, false)
|
|
|
|
expect(s.filter(20, "")).toEqual([jane])
|
|
expect(s.filter(1, "j")).toEqual([john, jane])
|
|
expect(s.filter(20, "")).toEqual([jane])
|
|
|
|
expect(events.splice(0)).toEqual([
|
|
"f 20 ",
|
|
"f 1 j",
|
|
"f 20 ", //suspended
|
|
])
|
|
|
|
const d = autorun(() => {
|
|
events.push(
|
|
s
|
|
.filter(1, "j")
|
|
.map((p) => p.name)
|
|
.join("-")
|
|
)
|
|
})
|
|
|
|
s.persons[2].name = "jable"
|
|
s.persons[1].name = "ane"
|
|
|
|
s.persons[2].age = 0
|
|
|
|
d()
|
|
|
|
expect(s.filter(20, "")).toEqual([{ name: "ane", age: 45 }])
|
|
expect(s.filter(20, "")).toEqual([{ name: "ane", age: 45 }])
|
|
|
|
expect(events.splice(0)).toEqual([
|
|
"f 1 j", // was suspended
|
|
"john-jane",
|
|
"f 1 j",
|
|
"john-jane-jable",
|
|
"f 1 j",
|
|
"john-jable",
|
|
"f 1 j",
|
|
"john",
|
|
"unobserved persons", // all suspended!
|
|
"f 20 ",
|
|
"f 20 ",
|
|
])
|
|
})
|
|
|
|
test("make sure the fn is cached", () => {
|
|
const events: string[] = []
|
|
|
|
const store = observable({
|
|
a: 1,
|
|
b: 2,
|
|
c: 3,
|
|
m: computedFn(function m(x) {
|
|
expect(this).toBe(store)
|
|
events.push("calc " + x)
|
|
return this.a * this.b * x
|
|
}),
|
|
})
|
|
|
|
const d = autorun(() => {
|
|
events.push("autorun " + store.m(3) * store.c)
|
|
})
|
|
|
|
expect(getDependencyTree(d)).toMatchSnapshot()
|
|
|
|
store.b = 3
|
|
store.c = 4
|
|
|
|
expect(events).toEqual(["calc 3", "autorun 18", "calc 3", "autorun 27", "autorun 36"])
|
|
})
|
|
|
|
test("supports options", () => {
|
|
const events: number[][] = []
|
|
const xs = observable([1, 2, 3])
|
|
const xsLessThan = computedFn((n) => xs.filter((x) => x < n), { equals: comparer.structural })
|
|
|
|
autorun(() => events.push(xsLessThan(3)))
|
|
expect(events).toEqual([[1, 2]])
|
|
|
|
events.length = 0
|
|
xs.push(4)
|
|
expect(events).toEqual([])
|
|
})
|
|
|
|
test("should not allow actions", () => {
|
|
expect(() => computedFn(action(() => {}))).toThrow("action")
|
|
})
|