Repository: hustcc/jest-canvas-mock
Pull request #52 (2019-11-04 14:45:56)

fix(transform): slice transform on save, node 13
Apparently I don't have write access to the repo, but that's fine. I can submit pull requests like this.

Changes:

- Add support for node 13
- remove support for node 6 and 7
- add slice to transform push (adds more memory usage but is compliant with spec
- update babel env to target node 8
- update node packages
- cleanup changelog docs

Please check my work and publish at your convenience.

I didn't include the version bump to 2.2.0, but you should definitely do this when you're ready.

Fixes: #50 
Fixes: #53 


Patch:
diff --git a/.babelrc b/.babelrc
index 39a24a7..f59b277 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,4 +1,13 @@
 {
-  "presets": ["@babel/env"],
+  "presets": [
+    [
+      "@babel/env",
+      {
+        "targets": {
+          "node": "8"
+        }
+      }
+    ]
+  ],
   "plugins": ["@babel/proposal-class-properties", "version"]
 }
diff --git a/.travis.yml b/.travis.yml
index a6a8263..22c2578 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,10 @@
 language: node_js
 node_js:
-    - "6"
-    - "7"
     - "8"
     - "9"
     - "10"
     - "11"
     - "12"
+    - "13"
 after_success:
     - npm run coveralls
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8fa7ef1..7d4d50c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,19 @@
 # CHANGELOG
 
-# Version 2.1.1
+## Version 2.2.0
 
-- Feature: Support for ImageData instantiation using a source array(#45)
+- Bug: Slice canvas transform value when pushing (#50)
+- Remove support for node 6 and 7
+- switch babel env to target node 8
+- add support for node 13
+- update package versions
+- fix lineWidth bug
 
-# Version 2.1.0
+## Version 2.1.1
+
+- Feature: Support for ImageData instantiation using a source array (#45)
+
+## Version 2.1.0
 
 This minor version bump now has some major snapshot support but is backwards compatible.
 
@@ -29,13 +38,13 @@ Changes:
 - Feature: Add `_path` and `_events` to `Path2D`
 - Testing: Add and test snapshot outputs
 
-# Version 2.0.0
+## Version 2.0.0
 
 Just publish a stable version.
 
-# Version 2.0.0-beta.1
+## Version 2.0.0-beta.1
 
-## Class Instances
+### Class Instances
 
 The Version 2.0.0-beta.1 of `jest-canvas-mock` is a complete overhaul of the mocking strategy entirely. Originally, the `canvas.getCanvas('2d')` method would return a single object that contained a set of methods without any property definitions. This caused problems for people who wanted to use `jest` to test and verify `instanceof` checks.
 
@@ -47,7 +56,7 @@ const ctx = document.createElement('canvas').getContext('2d');
 expect(ctx).toBeInstanceOf(CanvasRenderingContext2D);
 ```
 
-## Bound Mock Functions
+### Bound Mock Functions
 
 When each `CanvasRenderingContext2D` object is created, all the methods are properly mocked with the `jest.fn()` method, and bound to the instance. It's still possible to verify that a function was called on the context. The main difference now is that the methods actually perform runtime checks on the passed parameters.
 
@@ -64,7 +73,7 @@ expect(ctx.arc).toBeCalledWith(0, 0, 100, 0, PI_2);
 expect(() => ctx.arc(0, 0, -10, 0, PI_2)).toThrow(DOMExpection);
 ```
 
-# Parsing Colors and Fonts, Saving, Restoring
+### Parsing Colors and Fonts, Saving, Restoring
 
 Another really big change is that the mocking strategy now attempts to conform to the html living specification. In order to do this, two packages were added as dependencies so that css colors and fonts can be more properly parsed. This is not perfect, and any problems with the color parser or font parser should be reported in the Issues tab.
 
@@ -99,7 +108,7 @@ expect(ctx.font).toBe('10px sans-serif');
 
 For all these reasons, the `jest-canvas-mock` package was bumped a major version to `2.0.0`.
 
-## CanvasRenderingContext2D prototype
+### CanvasRenderingContext2D prototype
 
 - Implemented Stack Properties for the following items:
   - `direction`
@@ -371,7 +380,7 @@ For all these reasons, the `jest-canvas-mock` package was bumped a major version
   - throws `TypeError` if `arguments.length < 2`
   - performs a translate operation on the current `transform` stack value if every parameter is finite
 
-## Other Changes By File
+### Other Changes By File
 
 - src/CanvasGradient.js
   - Added Class for `instanceof` checks
@@ -452,4 +461,3 @@ For all these reasons, the `jest-canvas-mock` package was bumped a major version
     - This function cannot normally be constructed
     - mocked to accept a `text` parameter
     - sets `width` property to `text.length`
-
diff --git a/README.md b/README.md
index 9cb9c93..630a778 100644
--- a/README.md
+++ b/README.md
@@ -144,16 +144,6 @@ const calls = ctx.__getDrawCalls();
 expect(calls).toMatchSnapshot();
 ```
 
-In some cases it may be useful to clear the events or draw calls that have already been logged.
-
-```ts
-// Clear events
-ctx.__clearEvents();
-
-// Clear draw calls
-ctx.__clearDrawCalls();
-```
-
 ## Override default mock return value
 
 You can override the default mock return value in your test to suit your need. For example, to override return value of `toDataURL`:
diff --git a/src/classes/CanvasRenderingContext2D.js b/src/classes/CanvasRenderingContext2D.js
index 2d331c1..32e6b07 100644
--- a/src/classes/CanvasRenderingContext2D.js
+++ b/src/classes/CanvasRenderingContext2D.js
@@ -42,13 +42,6 @@ export default class CanvasRenderingContext2D {
     return this._drawCalls.slice();
   }
 
-  /**
-   * Clear the list of draw calls
-   */
-  __clearDrawCalls() {
-    this._drawCalls = []
-  }
-
   /**
    * Every time a function call results in something that would have modified the state of the context,
    * an event is added to this array. This goes for every property set, and draw call.
@@ -58,13 +51,6 @@ export default class CanvasRenderingContext2D {
     return this._events.slice();
   }
 
-  /**
-   * Clear the list of events
-   */
-  __clearEvents() {
-    this._events = [];
-  }
-
   /**
    * This array keeps track of the current path, so that fill and stroke operations can store the
    * path.
@@ -74,18 +60,6 @@ export default class CanvasRenderingContext2D {
     return this._path.slice();
   }
 
-  /**
-   * Clear the path and reset it to a single beginPath event.
-   */
-  __clearPath() {
-    const event = createCanvasEvent(
-      'beginPath',
-      getTransformSlice(this),
-      { },
-    );
-    this._path = [event];
-  }
-
   _directionStack = ['inherit'];
   _fillStyleStack = ['#000'];
   _filterStack = ['none'];
@@ -185,9 +159,13 @@ export default class CanvasRenderingContext2D {
   }
 
   beginPath() {
-    this.__clearPath();
-    // push the generated beginPath to the event list
-    this._events.push(this._path[0]);
+    const event = createCanvasEvent(
+      'beginPath',
+      getTransformSlice(this),
+      { },
+    );
+    this._path = [event];
+    this._events.push(event);
   }
 
   bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y) {
@@ -1100,7 +1078,7 @@ export default class CanvasRenderingContext2D {
   }
 
   save() {
-    this._transformStack.push(this._transformStack[this._stackIndex]);
+    this._transformStack.push(this._transformStack[this._stackIndex].slice());
     this._directionStack.push(this._directionStack[this._stackIndex]);
     this._fillStyleStack.push(this._fillStyleStack[this._stackIndex]);
     this._filterStack.push(this._filterStack[this._stackIndex]);
@@ -1113,7 +1091,7 @@ export default class CanvasRenderingContext2D {
     this._lineDashStack.push(this._lineDashStack[this._stackIndex]);
     this._lineDashOffsetStack.push(this._lineDashOffsetStack[this._stackIndex]);
     this._lineJoinStack.push(this._lineJoinStack[this._stackIndex]);
-    this._lineWidthStack.push(this._lineWidthStack[this.stackIndex]);
+    this._lineWidthStack.push(this._lineWidthStack[this._stackIndex]);
     this._miterLimitStack.push(this._miterLimitStack[this._stackIndex]);
     this._shadowBlurStack.push(this._shadowBlurStack[this._stackIndex]);
     this._shadowColorStack.push(this._shadowColorStack[this._stackIndex]);
diff --git a/types/index.d.ts b/types/index.d.ts
index 1acca41..3646ad8 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -29,18 +29,6 @@ declare global {
      */
     __getEvents(): CanvasRenderingContext2DEvent[];
 
-    /**
-     * Clear all the events associated with this CanvasRenderingContext2D object.
-     *
-     * This method cannot be used in a production environment, only with `jest` using
-     * `jest-canvas-mock` and should only be used for testing.
-     *
-     * @example
-     * ctx.__clearEvents());
-     * expect(ctx.__getEvents()).toBe([]);
-     */
-    __clearEvents(): void;
-
     /**
      * Get all the successful draw calls associated with this CanvasRenderingContext2D object.
      *
@@ -52,18 +40,6 @@ declare global {
      */
     __getDrawCalls(): CanvasRenderingContext2DEvent[];
 
-    /**
-     * Clear all the successful draw calls associated with this CanvasRenderingContext2D object.
-     *
-     * This method cannot be used in a production environment, only with `jest` using
-     * `jest-canvas-mock` and should only be used for testing.
-     *
-     * @example
-     * ctx.__clearDrawCalls());
-     * expect(ctx.__getDrawCalls()).toBe([]);
-     */
-    __clearDrawCalls(): void;
-
     /**
      * Get the current path associated with this CanvasRenderingContext2D object.
      *
@@ -74,13 +50,5 @@ declare global {
      * expect(ctx.__getPath()).toMatchSnapshot();
      */
     __getPath(): CanvasRenderingContext2DEvent[];
-
-    /**
-     * Clears the current path associated with this CanvasRenderingContext2D object.
-     *
-     * This method cannot be used in a production environment, only with `jest` using
-     * `jest-canvas-mock` and should be only used for testing.
-     */
-    __clearPath(): void;
   }
 }


Test patch:
diff --git a/__tests__/classes/CanvasRenderingContext2D.__clearDrawCalls.js b/__tests__/classes/CanvasRenderingContext2D.__clearDrawCalls.js
deleted file mode 100644
index fa25184..0000000
--- a/__tests__/classes/CanvasRenderingContext2D.__clearDrawCalls.js
+++ /dev/null
@@ -1,24 +0,0 @@
-let ctx;
-beforeEach(() => {
-  // get a new context each test
-  ctx = document.createElement('canvas')
-    .getContext('2d');
-});
-
-afterEach(() => {
-  const drawCalls = ctx.__getDrawCalls();
-  expect(drawCalls).toMatchSnapshot();
-});
-
-describe('__clearDrawCalls', () => {
-  it("should clear the list of draw calls", () => {
-    ctx.fillRect(1, 2, 3, 4);
-    ctx.__clearDrawCalls();
-  });
-
-  it("should not prevent additional draw calls from being collected", () => {
-    ctx.fillRect(1, 2, 3, 4);
-    ctx.__clearDrawCalls();
-    ctx.fillRect(1, 2, 3, 4);
-  });
-});
diff --git a/__tests__/classes/CanvasRenderingContext2D.__clearEvents.js b/__tests__/classes/CanvasRenderingContext2D.__clearEvents.js
deleted file mode 100644
index 6af3841..0000000
--- a/__tests__/classes/CanvasRenderingContext2D.__clearEvents.js
+++ /dev/null
@@ -1,24 +0,0 @@
-let ctx;
-beforeEach(() => {
-  // get a new context each test
-  ctx = document.createElement('canvas')
-    .getContext('2d');
-});
-
-afterEach(() => {
-  const events = ctx.__getEvents();
-  expect(events).toMatchSnapshot();
-});
-
-describe('__clearEvents', () => {
-  it("should clear the list of events", () => {
-    ctx.fillRect(1, 2, 3, 4);
-    ctx.__clearEvents();
-  });
-
-  it("should not prevent additional events from being collected", () => {
-    ctx.fillRect(1, 2, 3, 4);
-    ctx.__clearEvents();
-    ctx.fillRect(1, 2, 3, 4);
-  });
-});
diff --git a/__tests__/classes/CanvasRenderingContext2D.__clearPath.js b/__tests__/classes/CanvasRenderingContext2D.__clearPath.js
deleted file mode 100644
index c63ac0e..0000000
--- a/__tests__/classes/CanvasRenderingContext2D.__clearPath.js
+++ /dev/null
@@ -1,24 +0,0 @@
-let ctx;
-beforeEach(() => {
-  // get a new context each test
-  ctx = document.createElement('canvas')
-    .getContext('2d');
-});
-
-afterEach(() => {
-  const events = ctx.__getPath();
-  expect(events).toMatchSnapshot();
-});
-
-describe('__clearEvents', () => {
-  it("should clear the list of events", () => {
-    ctx.arc(1, 2, 3, 4, 5);
-    ctx.__clearPath();
-  });
-
-  it("should not prevent additional events from being collected", () => {
-    ctx.arc(1, 2, 3, 4, 5);
-    ctx.__clearPath();
-    ctx.arc(1, 2, 3, 4, 5);
-  });
-});
diff --git a/__tests__/classes/CanvasRenderingContext2D.lineWidth.js b/__tests__/classes/CanvasRenderingContext2D.lineWidth.js
index 9bc0555..bed3f61 100644
--- a/__tests__/classes/CanvasRenderingContext2D.lineWidth.js
+++ b/__tests__/classes/CanvasRenderingContext2D.lineWidth.js
@@ -39,6 +39,10 @@ describe('lineWidth', () => {
     ctx.save();
     ctx.lineWidth = 10;
     expect(ctx.lineWidth).toBe(10);
+    ctx.save();
+    expect(ctx.lineWidth).toBe(10);
+    ctx.restore();
+    expect(ctx.lineWidth).toBe(10);
     ctx.restore();
     expect(ctx.lineWidth).toBe(2);
   });
diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearDrawCalls.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearDrawCalls.js.snap
deleted file mode 100644
index 81c3392..0000000
--- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearDrawCalls.js.snap
+++ /dev/null
@@ -1,25 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`__clearDrawCalls should clear the list of draw calls 1`] = `Array []`;
-
-exports[`__clearDrawCalls should not prevent additional draw calls from being collected 1`] = `
-Array [
-  Object {
-    "props": Object {
-      "height": 4,
-      "width": 3,
-      "x": 1,
-      "y": 2,
-    },
-    "transform": Array [
-      1,
-      0,
-      0,
-      1,
-      0,
-      0,
-    ],
-    "type": "fillRect",
-  },
-]
-`;
diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearEvents.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearEvents.js.snap
deleted file mode 100644
index b68b457..0000000
--- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearEvents.js.snap
+++ /dev/null
@@ -1,25 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`__clearEvents should clear the list of events 1`] = `Array []`;
-
-exports[`__clearEvents should not prevent additional events from being collected 1`] = `
-Array [
-  Object {
-    "props": Object {
-      "height": 4,
-      "width": 3,
-      "x": 1,
-      "y": 2,
-    },
-    "transform": Array [
-      1,
-      0,
-      0,
-      1,
-      0,
-      0,
-    ],
-    "type": "fillRect",
-  },
-]
-`;
diff --git a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearPath.js.snap b/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearPath.js.snap
deleted file mode 100644
index 00e067f..0000000
--- a/__tests__/classes/__snapshots__/CanvasRenderingContext2D.__clearPath.js.snap
+++ /dev/null
@@ -1,54 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`__clearEvents should clear the list of events 1`] = `
-Array [
-  Object {
-    "props": Object {},
-    "transform": Array [
-      1,
-      0,
-      0,
-      1,
-      0,
-      0,
-    ],
-    "type": "beginPath",
-  },
-]
-`;
-
-exports[`__clearEvents should not prevent additional events from being collected 1`] = `
-Array [
-  Object {
-    "props": Object {},
-    "transform": Array [
-      1,
-      0,
-      0,
-      1,
-      0,
-      0,
-    ],
-    "type": "beginPath",
-  },
-  Object {
-    "props": Object {
-      "anticlockwise": false,
-      "endAngle": 5,
-      "radius": 3,
-      "startAngle": 4,
-      "x": 1,
-      "y": 2,
-    },
-    "transform": Array [
-      1,
-      0,
-      0,
-      1,
-      0,
-      0,
-    ],
-    "type": "arc",
-  },
-]
-`;