From 7cd2dc1acceb69c00fc2dbd10ce8fae1085eb6c5 Mon Sep 17 00:00:00 2001
From: Michel Weststrate <mweststrate@gmail.com>
Date: Fri, 2 Aug 2019 16:14:14 +0200
Subject: [PATCH] fix: If a property is added, then deleted, don't produce a
 patch

---
 __tests__/patch.js | 75 ++++++++++++++++++++++++++++++++++++++++++++--
 src/proxy.js       |  3 ++
 2 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/__tests__/patch.js b/__tests__/patch.js
index fa38724a..d50db90a 100644
--- a/__tests__/patch.js
+++ b/__tests__/patch.js
@@ -4,6 +4,8 @@ import produce, {setUseProxies, applyPatches} from "../src/index"
 jest.setTimeout(1000)
 
 function runPatchTest(base, producer, patches, inversePathes) {
+	let resultProxies, resultEs5
+
 	function runPatchTestHelper() {
 		let recordedPatches
 		let recordedInversePatches
@@ -24,17 +26,24 @@ function runPatchTest(base, producer, patches, inversePathes) {
 		test("patches can be reversed", () => {
 			expect(applyPatches(res, recordedInversePatches)).toEqual(base)
 		})
+
+		return res
 	}
 
 	describe(`proxy`, () => {
 		setUseProxies(true)
-		runPatchTestHelper()
+		resultProxies = runPatchTestHelper()
 	})
 
 	describe(`es5`, () => {
 		setUseProxies(false)
-		runPatchTestHelper()
+		resultEs5 = runPatchTestHelper()
+		test("ES5 and Proxy implementation yield same result", () => {
+			expect(resultEs5).toEqual(resultProxies)
+		})
 	})
+
+	return resultProxies
 }
 
 describe("applyPatches", () => {
@@ -414,3 +423,65 @@ describe("simple delete", () => {
 		]
 	)
 })
+
+describe("patch compressions yields correct results", () => {
+	let p1, p2
+	runPatchTest(
+		{},
+		d => {
+			d.x = {test: true}
+		},
+		(p1 = [
+			{
+				op: "add",
+				path: ["x"],
+				value: {
+					test: true
+				}
+			}
+		])
+	)
+	runPatchTest(
+		{x: {test: true}},
+		d => {
+			delete d.x
+		},
+		(p2 = [
+			{
+				op: "remove",
+				path: ["x"]
+			}
+		])
+	)
+	const res = runPatchTest(
+		{},
+		d => {
+			debugger
+			applyPatches(d, [...p1, ...p2])
+		},
+		[]
+	)
+
+	expect(res).toEqual({})
+})
+
+describe("change then delete property", () => {
+	const res = runPatchTest(
+		{
+			x: 1
+		},
+		d => {
+			d.x = 2
+			delete d.x
+		},
+		[
+			{
+				op: "remove",
+				path: ["x"]
+			}
+		]
+	)
+	test("valid result", () => {
+		expect(res).toEqual({})
+	})
+})
diff --git a/src/proxy.js b/src/proxy.js
index f4caefde..33d7ed40 100644
--- a/src/proxy.js
+++ b/src/proxy.js
@@ -156,6 +156,9 @@ function deleteProperty(state, prop) {
 	if (peek(state.base, prop) !== undefined || prop in state.base) {
 		state.assigned[prop] = false
 		markChanged(state)
+	} else if (state.assigned[prop]) {
+		// if an originally not assigned property was deleted
+		delete state.assigned[prop]
 	}
 	if (state.copy) delete state.copy[prop]
 	return true