Skip to content

Commit

Permalink
feat: createDraft/finishDraft functions
Browse files Browse the repository at this point in the history
Closes #302
  • Loading branch information
mweststrate authored and aleclarson committed Feb 2, 2019
1 parent ed6dfcc commit e2eb0a8
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 0 deletions.
148 changes: 148 additions & 0 deletions __tests__/manual.js
@@ -0,0 +1,148 @@
"use strict"
import {setUseProxies, createDraft, finishDraft, produce} from "../src/index"

runTests("proxy", true)
runTests("es5", false)

function runTests(name, useProxies) {
describe("manual - " + name, () => {
setUseProxies(useProxies)

it("should check arguments", () => {
expect(() => createDraft(3)).toThrow(
"argument to createDraft should be a plain"
)
expect(() => createDraft(new Buffer([]))).toThrow(
"argument to createDraft should be a plain"
)
expect(() => finishDraft({})).toThrow(
"First argument to finishDraft should be "
)
})

it("should support manual drafts", () => {
const state = [{}, {}, {}]

const draft = createDraft(state)
draft.forEach((item, index) => {
item.index = index
})

const result = finishDraft(draft)

expect(result).not.toBe(state)
expect(result).toEqual([{index: 0}, {index: 1}, {index: 2}])
expect(state).toEqual([{}, {}, {}])
})

it("cannot modify after finish", () => {
const state = {a: 1}

const draft = createDraft(state)
draft.a = 2
expect(finishDraft(draft)).toEqual({a: 2})
expect(() => {
draft.a = 3
}).toThrow("Cannot use a proxy that has been revoked")
})

it("should support patches drafts", () => {
const state = {a: 1}

const draft = createDraft(state)
draft.a = 2
draft.b = 3

const patches = []
const result = finishDraft(draft, (p, ip) => {
patches.push(p, ip)
})

expect(result).not.toBe(state)
expect(result).toEqual({a: 2, b: 3})
expect(patches).toEqual([
[
{
op: "replace",
path: ["a"],
value: 2
},
{
op: "add",
path: ["b"],
value: 3
}
],
[
{
op: "replace",
path: ["a"],
value: 1
},
{
op: "remove",
path: ["b"]
}
]
])
})

it("should handle multiple create draft calls", () => {
const state = {a: 1}

const draft = createDraft(state)
draft.a = 2

const draft2 = createDraft(state)
draft2.b = 3

const result = finishDraft(draft)

expect(result).not.toBe(state)
expect(result).toEqual({a: 2})

draft2.a = 4
const result2 = finishDraft(draft2)
expect(result2).not.toBe(result)
expect(result2).toEqual({a: 4, b: 3})
})

it("combines with produce - 1", () => {
const state = {a: 1}

const draft = createDraft(state)
draft.a = 2
const res1 = produce(draft, d => {
d.b = 3
})
draft.b = 4
const res2 = finishDraft(draft)
expect(res1).toEqual({a: 2, b: 3})
expect(res2).toEqual({a: 2, b: 4})
})

it("combines with produce - 2", () => {
const state = {a: 1}

const res1 = produce(state, draft => {
draft.b = 3
const draft2 = createDraft(draft)
draft.c = 4
draft2.d = 5
const res2 = finishDraft(draft2)
expect(res2).toEqual({
a: 1,
b: 3,
d: 5
})
draft.d = 2
})
expect(res1).toEqual({
a: 1,
b: 3,
c: 4,
d: 2
})
})
})
}
13 changes: 13 additions & 0 deletions src/immer.js
Expand Up @@ -86,6 +86,19 @@ export class Immer {
return result !== NOTHING ? result : undefined
}
}
createPublicDraft(value) {
if (!isDraftable(value)) throw new Error("First argument to createDraft should be a plain-, or immerable object, or array.") // prettier-ignore
const scope = ImmerScope.enter()
const draft = this.createDraft(value)
scope.leave()
return draft
}
finishPublicDraft(draft, patchListener) {
if (!isDraft(draft)) throw new Error("First argument to finishDraft should be an object created with createDraft.") // prettier-ignore
const {scope} = draft[DRAFT_STATE]
scope.usePatches(patchListener)
return this.processResult(undefined, scope)
}
setAutoFreeze(value) {
this.autoFreeze = value
}
Expand Down
4 changes: 4 additions & 0 deletions src/index.js
Expand Up @@ -46,6 +46,10 @@ export const setUseProxies = immer.setUseProxies.bind(immer)
*/
export const applyPatches = immer.applyPatches.bind(immer)

export const createDraft = immer.createPublicDraft.bind(immer)

export const finishDraft = immer.finishPublicDraft.bind(immer)

export {
original,
isDraft,
Expand Down

0 comments on commit e2eb0a8

Please sign in to comment.