diff --git a/src/core/States.js b/src/core/States.js index a70a6300c2..bc5a8a9a41 100644 --- a/src/core/States.js +++ b/src/core/States.js @@ -14,7 +14,7 @@ export class States { this[key] = value; } - getDiff() { + takeDiff() { const diff = this.#modified; this.#modified = {}; return diff; diff --git a/src/core/p5.Renderer.js b/src/core/p5.Renderer.js index 8467695bf8..ae5082644a 100644 --- a/src/core/p5.Renderer.js +++ b/src/core/p5.Renderer.js @@ -135,7 +135,7 @@ class Renderer { // and push it into the push pop stack push() { this._pushPopDepth++; - this._pushPopStack.push(this.states.getDiff()); + this._pushPopStack.push(this.states.takeDiff()); } // Pop the previous states out of the push pop stack and diff --git a/test/unit/core/States.js b/test/unit/core/States.js new file mode 100644 index 0000000000..d4b2b56a35 --- /dev/null +++ b/test/unit/core/States.js @@ -0,0 +1,70 @@ +import { States } from '../../../src/core/States.js'; + +suite('States', function () { + test('initialises with provided state', function () { + const s = new States({ fill: 'red', stroke: 'blue' }); + assert.equal(s.fill, 'red'); + assert.equal(s.stroke, 'blue'); + }); + + test('setValue() updates the value', function () { + const s = new States({ fill: 'red' }); + s.setValue('fill', 'green'); + assert.equal(s.fill, 'green'); + }); + + test('setValue() records the original before first modification', function () { + const s = new States({ fill: 'red' }); + s.setValue('fill', 'green'); + assert.equal(s.getModified().fill, 'red'); + }); + + test('setValue() does not overwrite original on repeated calls', function () { + const s = new States({ fill: 'red' }); + s.setValue('fill', 'green'); + s.setValue('fill', 'blue'); + assert.equal(s.getModified().fill, 'red'); + }); + + test('takeDiff() returns the modified map', function () { + const s = new States({ fill: 'red' }); + s.setValue('fill', 'green'); + const diff = s.takeDiff(); + assert.equal(diff.fill, 'red'); + }); + + test('takeDiff() clears #modified after returning', function () { + const s = new States({ fill: 'red' }); + s.setValue('fill', 'green'); + s.takeDiff(); + assert.deepEqual(s.takeDiff(), {}); + }); + + test('applyDiff() undoes current modifications and replaces #modified', function () { + const s = new States({ fill: 'red' }); + s.setValue('fill', 'green'); + const outerModified = {}; + s.applyDiff(outerModified); + assert.equal(s.fill, 'red'); + assert.deepEqual(s.getModified(), {}); + }); + + test('applyDiff() with a non-empty prevModified replaces #modified', function () { + const s = new States({ fill: 'red', stroke: 'black' }); + s.setValue('fill', 'green'); + const outerModified = { stroke: 'black' }; + s.applyDiff(outerModified); + assert.equal(s.fill, 'red'); + assert.deepEqual(s.getModified(), { stroke: 'black' }); + }); + + test('push/pop cycle: applyDiff restores prior state', function () { + const s = new States({ fill: 'red' }); + const beforePush = s.takeDiff(); + s.setValue('fill', 'green'); + assert.equal(s.fill, 'green'); + s.applyDiff(beforePush); + assert.equal(s.fill, 'red'); + assert.deepEqual(s.getModified(), {}); + }); +}); \ No newline at end of file