Skip to content

Commit 0fdbb5e

Browse files
author
Lee Richmond
committed
Split isPersisted() and reset()
Vue will avoid firing the setter if the getter returns the same value. This ensures we do not rely on the setter's side-effect, but manually call reset() to fix the issue.
1 parent b01f50b commit 0fdbb5e

File tree

4 files changed

+62
-0
lines changed

4 files changed

+62
-0
lines changed

src/model.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,10 @@ export class JSORMBase {
405405
}
406406
set isPersisted(val: boolean) {
407407
this._persisted = val
408+
this.reset()
409+
}
410+
411+
reset() : void {
408412
this._originalAttributes = cloneDeep(this._attributes)
409413
this._originalRelationships = this.relationshipResourceIdentifiers(
410414
Object.keys(this.relationships)

src/util/deserialize.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class Deserializer {
148148

149149
// came from server, must be persisted
150150
instance.isPersisted = true
151+
instance.reset()
151152

152153
return instance
153154
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { sinon, expect, fetchMock } from "../test-helper"
2+
import { Person, Author, Book } from "../fixtures"
3+
import { IResultProxy } from "../../src/proxies/index"
4+
5+
afterEach(() => {
6+
fetchMock.restore()
7+
})
8+
9+
let responsePayload = (firstName: string) => {
10+
return {
11+
data: {
12+
id: "1",
13+
type: "people",
14+
attributes: { firstName }
15+
}
16+
}
17+
}
18+
19+
beforeEach(() => {
20+
let url = "http://example.com/api/v1/authors"
21+
fetchMock.post(url, responsePayload('John'))
22+
fetchMock.put(`${url}/1`, responsePayload('Jake'))
23+
})
24+
25+
// This is a Vue-specific test. Since isPersisted is already true,
26+
// Vue will prevent the setter from firing. We cannot rely on
27+
// side-effect behavior of model.isPersisted = true
28+
// So, ensure we at least call reset() explicitly
29+
describe("Dirty tracking", () => {
30+
describe("when persisted, dirty, updated", () => {
31+
it("calls reset()", async () => {
32+
let instance = new Author({ firstName: 'John' })
33+
await instance.save()
34+
expect(instance.isPersisted).to.eq(true)
35+
expect(instance.isDirty()).to.eq(false)
36+
instance.firstName = 'Jake'
37+
expect(instance.isDirty()).to.eq(true)
38+
let spy = sinon.spy()
39+
instance.reset = spy
40+
await instance.save()
41+
expect(spy.callCount).to.eq(2)
42+
})
43+
})
44+
})

test/unit/model.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,19 @@ describe("Model", () => {
817817
})
818818
})
819819

820+
describe('when previously persisted, dirty, then persisted again', () => {
821+
it('is no longer dirty', () => {
822+
const instance = new Author({ id: 1 })
823+
instance.firstName = "foo"
824+
instance.isPersisted = true
825+
expect(instance.isDirty()).to.eq(false)
826+
instance.firstName = "bar"
827+
expect(instance.isDirty()).to.eq(true)
828+
instance.isPersisted = true
829+
expect(instance.isDirty()).to.eq(false)
830+
})
831+
})
832+
820833
describe("when marked for destruction", () => {
821834
it("is dirty", () => {
822835
const instance = new Author()

0 commit comments

Comments
 (0)