Skip to content

Commit

Permalink
Finished hook composition tests. Fixes #252
Browse files Browse the repository at this point in the history
  • Loading branch information
mweststrate committed Aug 23, 2017
1 parent a49783c commit 5514751
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -730,7 +730,7 @@ types
| Hook | Meaning |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `preProcessSnapshot` | Before creating an instance or applying a snapshot to an existing instance, this hook is called to give the option to transform the snapshot before it is applied. The hook should bea _pure_ function that returns a new snapshot. This can be useful to do some data conversion, enrichment, property renames etc. This hook is not called for individual property updates. _**Note that unlike the other hooks, this one is _not_ created as part of the `actions` initializer, but directly on the type!**_ |
| `preProcessSnapshot` | Before creating an instance or applying a snapshot to an existing instance, this hook is called to give the option to transform the snapshot before it is applied. The hook should bea _pure_ function that returns a new snapshot. This can be useful to do some data conversion, enrichment, property renames etc. This hook is not called for individual property updates. _**Note 1: Unlike the other hooks, this one is _not_ created as part of the `actions` initializer, but directly on the type!**_ _**Note 2: The `preProcessSnapshot` transformation must be pure; it is should not modify it's original input argument!**_ |
| `afterCreate` | Immediately after an instance is created and initial values are applied. Children will fire this event before parents |
| `afterAttach` | As soon as the _direct_ parent is assigned (this node is attached to an other node) |
| `postProcessSnapshot` | This hook is called every time a new snapshot is being generated. Typically it is the inverse function of `preProcessSnapshot`. This function should be a pure function that returns a new snapshot.
Expand Down
4 changes: 4 additions & 0 deletions changelog.md
@@ -1,3 +1,7 @@
# 0.10.3

* Redefining lifecycle hooks will now automatically compose them, implements [#252](https://github.com/mobxjs/mobx-state-tree/issues/252)

# 0.10.2

* Object model instances no longer share a prototype.
Expand Down
2 changes: 1 addition & 1 deletion src/types/complex-types/object.ts
Expand Up @@ -231,7 +231,7 @@ export class ObjectType<S, T> extends ComplexType<S, T> implements IModelType<S,
if (!currentPreprocessor) return this.extend({ preProcessor })
else
return this.extend({
preProcessor: snapshot => preProcessor(currentPreprocessor(snapshot))
preProcessor: snapshot => currentPreprocessor(preProcessor(snapshot))
})
}

Expand Down
98 changes: 82 additions & 16 deletions test/hooks.ts
Expand Up @@ -159,22 +159,88 @@ test("it should postprocess snapshots when generating snapshot", t => {
})

test("base hooks can be composed", t => {
const Todo = types.model("Todo", { title: "" }).actions(self => {
function afterCreate() {
listener("new todo: " + self.title)
}
function beforeDestroy() {
listener("destroy todo: " + self.title)
}
function afterAttach() {
listener("attach todo: " + self.title)
}
function beforeDetach() {
listener("detach todo: " + self.title)
}
return { afterCreate, beforeDestroy, afterAttach, beforeDetach }
})
const events: string[] = []
function listener(message) {
events.push(message)
}

const Todo = types
.model("Todo", { title: "" })
.actions(self => {
function afterCreate() {
listener("aftercreate1")
}
function beforeDestroy() {
listener("beforedestroy1")
}
function afterAttach() {
listener("afterattach1")
}
function beforeDetach() {
listener("beforedetach1")
}
return { afterCreate, beforeDestroy, afterAttach, beforeDetach }
})
.actions(self => {
function afterCreate() {
listener("aftercreate2")
}
function beforeDestroy() {
listener("beforedestroy2")
}
function afterAttach() {
listener("afterattach2")
}
function beforeDetach() {
listener("beforedetach2")
}
return { afterCreate, beforeDestroy, afterAttach, beforeDetach }
})

const Store = types.model("Store", { todos: types.array(Todo) })

const store = Store.create({ todos: [] })
const todo = Todo.create()
unprotect(store)
store.todos.push(todo)
detach(todo)
destroy(todo)
t.deepEqual(events, [
"aftercreate1",
"aftercreate2",
"afterattach1",
"afterattach2",
"beforedetach1",
"beforedetach2",
"beforedestroy1",
"beforedestroy2"
])
})

test("snapshot processors can be composed", t => {})
test("snapshot processors can be composed", t => {
const X = types
.model({
x: 1
})
.actions(self => ({
postProcessSnapshot(s) {
s.x += 3
return s
}
}))
.preProcessSnapshot((s: any) => ({
x: s.x - 3
}))
.actions(self => ({
postProcessSnapshot(s) {
s.x *= 5
return s
}
}))
.preProcessSnapshot((s: any) => ({
x: s.x / 5
}))
const x = X.create({ x: 25 })
t.is(x.x, 2)
t.is(getSnapshot(x).x, 25)
})

0 comments on commit 5514751

Please sign in to comment.