diff --git a/.eslintrc b/.eslintrc index 2a1689f41..c15ae363a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,8 +1,16 @@ { "root": true, "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint"], - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + "plugins": ["@typescript-eslint", "jest"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:jest/recommended" + ], + "rules": { + "jest/no-export": "warn", + "jest/no-identical-title": "warn" + }, "overrides": [ { // enable the rule specifically for TypeScript files diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bee851e7b..32fffae98 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,6 +24,10 @@ jobs: - name: Build Packages run: yarn build:packages --cache-dir=".turbo" + # lint + - name: Lint + run: yarn lint + # run unit tests - name: Jest Annotations & Coverage run: yarn test:ci diff --git a/package.json b/package.json index 1f67fee35..5e5a64003 100644 --- a/package.json +++ b/package.json @@ -44,17 +44,18 @@ "@swc-node/jest": "^1.4.3", "@testing-library/jest-dom": "^5.16.2", "@testing-library/react": "^12.1.2", + "@tldraw/lfg": "latest", "@types/jest": "^27.4.0", "@types/node": "^17.0.14", "@types/vscode": "^1.63.2", - "@typescript-eslint/eslint-plugin": "^5.10.2", - "@typescript-eslint/parser": "^5.10.2", + "@typescript-eslint/eslint-plugin": "^5.17.0", + "@typescript-eslint/parser": "^5.17.0", "eslint": "^8.8.0", + "eslint-plugin-jest": "^26.6.0", "fake-indexeddb": "^3.1.7", "husky": "^7.0.4", "init-package-json": "^2.0.5", "jest": "^27.4.7", - "@tldraw/lfg": "latest", "lint-staged": "^12.3.3", "mobx": "^6.3.8", "prettier": "^2.5.1", diff --git a/packages/tldraw/src/state/TldrawApp.spec.ts b/packages/tldraw/src/state/TldrawApp.spec.ts index d94a82a26..2b7ca9782 100644 --- a/packages/tldraw/src/state/TldrawApp.spec.ts +++ b/packages/tldraw/src/state/TldrawApp.spec.ts @@ -110,7 +110,7 @@ describe('TldrawTestApp', () => { expect(app.bindings.length).toBe(2) }) - it.only('removes bindings from copied shape handles', () => { + it('removes bindings from copied shape handles', () => { const app = new TldrawTestApp() app @@ -326,12 +326,12 @@ describe('TldrawTestApp', () => { }) }) - describe('Copies to JSON', () => { + test('Copies to JSON', () => { const app = new TldrawTestApp().loadDocument(mockDocument).selectAll() expect(app.copyJson()).toMatchSnapshot('copied json') }) - describe('Mutates bound shapes', () => { + test('Mutates bound shapes', () => { const app = new TldrawTestApp() .createShapes( { @@ -687,7 +687,7 @@ describe('TldrawTestApp', () => { expect(app.bindings).toMatchObject(Object.values(bindings)) }) - it('It should update the page shapes after the settings have been updated', async () => { + it('should update the page shapes after the settings have been updated', async () => { const shapes = deepCopy(mockDocument.pages.page1.shapes) const bindings = deepCopy(mockDocument.pages.page1.bindings) const app = new TldrawTestApp('multiplayer', { diff --git a/packages/tldraw/src/state/TldrawApp.ts b/packages/tldraw/src/state/TldrawApp.ts index 2ba8dac02..0c8e12c0d 100644 --- a/packages/tldraw/src/state/TldrawApp.ts +++ b/packages/tldraw/src/state/TldrawApp.ts @@ -1273,7 +1273,7 @@ export class TldrawApp extends StateManager { updateDocument = (document: TDDocument, reason = 'updated_document'): this => { const prevState = this.state - let nextState = { ...prevState, document: { ...prevState.document } } + const nextState = { ...prevState, document: { ...prevState.document } } if (!document.pages[this.currentPageId]) { nextState.appState = { diff --git a/packages/tldraw/src/state/__snapshots__/TldrawApp.spec.ts.snap b/packages/tldraw/src/state/__snapshots__/TldrawApp.spec.ts.snap index e32d45f52..c89f46dbb 100644 --- a/packages/tldraw/src/state/__snapshots__/TldrawApp.spec.ts.snap +++ b/packages/tldraw/src/state/__snapshots__/TldrawApp.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` 1`] = ` +exports[`TldrawTestApp Copies to JSON: copied json 1`] = ` TldrawTestApp { "_idbId": undefined, "_snapshot": Object { @@ -818,3 +818,156 @@ TldrawTestApp { "zoomToSelection": [Function], } `; + +exports[`TldrawTestApp Exposes undo/redo stack: history 1`] = ` +Array [ + Object { + "after": Object { + "document": Object { + "pageStates": Object { + "page1": Object { + "selectedIds": Array [ + "rect1", + ], + }, + }, + "pages": Object { + "page1": Object { + "bindings": Object {}, + "shapes": Object { + "rect1": Object { + "childIndex": 1, + "id": "rect1", + "label": "", + "labelPoint": Array [ + 0.5, + 0.5, + ], + "name": "Rectangle", + "parentId": "page1", + "point": Array [ + 0, + 0, + ], + "rotation": 0, + "size": Array [ + 100, + 200, + ], + "style": Object { + "color": "black", + "dash": "draw", + "isFilled": false, + "scale": 1, + "size": "small", + }, + "type": "rectangle", + }, + }, + }, + }, + }, + }, + "before": Object { + "document": Object { + "pageStates": Object { + "page1": Object { + "selectedIds": Array [], + }, + }, + "pages": Object { + "page1": Object { + "bindings": Object {}, + "shapes": Object { + "rect1": undefined, + }, + }, + }, + }, + }, + "id": "create", + }, + Object { + "after": Object { + "document": Object { + "pageStates": Object { + "page1": Object { + "selectedIds": Array [ + "rect2", + ], + }, + }, + "pages": Object { + "page1": Object { + "bindings": Object {}, + "shapes": Object { + "rect2": Object { + "childIndex": 1, + "id": "rect2", + "label": "", + "labelPoint": Array [ + 0.5, + 0.5, + ], + "name": "Rectangle", + "parentId": "page1", + "point": Array [ + 0, + 0, + ], + "rotation": 0, + "size": Array [ + 100, + 200, + ], + "style": Object { + "color": "black", + "dash": "draw", + "isFilled": false, + "scale": 1, + "size": "small", + }, + "type": "rectangle", + }, + }, + }, + }, + }, + }, + "before": Object { + "document": Object { + "pageStates": Object { + "page1": Object { + "selectedIds": Array [ + "rect1", + ], + }, + }, + "pages": Object { + "page1": Object { + "bindings": Object {}, + "shapes": Object { + "rect2": undefined, + }, + }, + }, + }, + }, + "id": "create", + }, +] +`; + +exports[`TldrawTestApp Selection When selecting all selects all: selected all 1`] = ` +Array [ + "rect1", + "rect2", + "rect3", +] +`; + +exports[`TldrawTestApp When copying to SVG Copies grouped shapes.: copied svg with group 1`] = `""`; + +exports[`TldrawTestApp When copying to SVG Copies shapes.: copied svg 1`] = `""`; + +exports[`TldrawTestApp When copying to SVG Respects child index: copied svg with reordered elements 1`] = `""`; diff --git a/packages/tldraw/src/state/sessions/RotateSession/RotateSession.spec.ts b/packages/tldraw/src/state/sessions/RotateSession/RotateSession.spec.ts index 187e46a8c..6cc3a46bf 100644 --- a/packages/tldraw/src/state/sessions/RotateSession/RotateSession.spec.ts +++ b/packages/tldraw/src/state/sessions/RotateSession/RotateSession.spec.ts @@ -128,7 +128,7 @@ describe('Rotate session', () => { ) ) - expect(app.getShape('rect1').rotation) + expect(app.getShape('rect1').rotation).not.toBeUndefined() expect(centerBefore).toStrictEqual(centerAfterA) expect(centerAfterA).toStrictEqual(centerAfterB) }) @@ -156,7 +156,7 @@ describe('Rotate session', () => { ) ) - expect(app.getShape('rect1').rotation) + expect(app.getShape('rect1').rotation).not.toBeUndefined() expect(centerBefore).toStrictEqual(centerAfterA) app.selectAll().nudge([10, 10]) diff --git a/packages/tldraw/src/test/documents/old-doc-2.ts b/packages/tldraw/src/test/documents/old-doc-2.ts index 2f8decd62..5fad34e19 100644 --- a/packages/tldraw/src/test/documents/old-doc-2.ts +++ b/packages/tldraw/src/test/documents/old-doc-2.ts @@ -15607,19 +15607,19 @@ export default { [3.88, 268.53, 0.5], [0.97, 276.6, 0.5], [0, 281.48, 0.5], - [-5.684341886080802e-14, 284.41, 0.5], - [-5.684341886080802e-14, 284.66, 0.5], - [-5.684341886080802e-14, 284.93, 0.5], - [-5.684341886080802e-14, 285.47, 0.5], - [-5.684341886080802e-14, 285.72, 0.5], - [-5.684341886080802e-14, 285.49, 0.5], - [-5.684341886080802e-14, 285.24, 0.5], - [-5.684341886080802e-14, 284.99, 0.5], - [-5.684341886080802e-14, 284.71000000000004, 0.5], - [-5.684341886080802e-14, 284.46000000000004, 0.5], - [-5.684341886080802e-14, 283.91, 0.5], - [-5.684341886080802e-14, 283.66, 0.5], - [-5.684341886080802e-14, 283.39, 0.5], + [-5.684341886080802, 284.41, 0.5], + [-5.684341886080802, 284.66, 0.5], + [-5.684341886080802, 284.93, 0.5], + [-5.684341886080802, 285.47, 0.5], + [-5.684341886080802, 285.72, 0.5], + [-5.684341886080802, 285.49, 0.5], + [-5.684341886080802, 285.24, 0.5], + [-5.684341886080802, 284.99, 0.5], + [-5.684341886080802, 284.71000000000004, 0.5], + [-5.684341886080802, 284.46000000000004, 0.5], + [-5.684341886080802, 283.91, 0.5], + [-5.684341886080802, 283.66, 0.5], + [-5.684341886080802, 283.39, 0.5], [0.2399999999998954, 282.86, 0.5], [0.5099999999999341, 282.58, 0.5], [1.0599999999999454, 282.03000000000003, 0.5], diff --git a/yarn.lock b/yarn.lock index 5a02371b3..231dca6db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3575,6 +3575,21 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/eslint-plugin@^5.17.0": + version "5.31.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz#cae1967b1e569e6171bbc6bec2afa4e0c8efccfe" + integrity sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ== + dependencies: + "@typescript-eslint/scope-manager" "5.31.0" + "@typescript-eslint/type-utils" "5.31.0" + "@typescript-eslint/utils" "5.31.0" + debug "^4.3.4" + functional-red-black-tree "^1.0.1" + ignore "^5.2.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.10.2": version "5.11.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.11.0.tgz#b4fcaf65513f9b34bdcbffdda055724a5efb7e04" @@ -3585,6 +3600,16 @@ "@typescript-eslint/typescript-estree" "5.11.0" debug "^4.3.2" +"@typescript-eslint/parser@^5.17.0": + version "5.31.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.31.0.tgz#7f42d7dcc68a0a6d80a0f3d9a65063aee7bb8d2c" + integrity sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw== + dependencies: + "@typescript-eslint/scope-manager" "5.31.0" + "@typescript-eslint/types" "5.31.0" + "@typescript-eslint/typescript-estree" "5.31.0" + debug "^4.3.4" + "@typescript-eslint/scope-manager@5.11.0": version "5.11.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.11.0.tgz#f5aef83ff253f457ecbee5f46f762298f0101e4b" @@ -3593,6 +3618,14 @@ "@typescript-eslint/types" "5.11.0" "@typescript-eslint/visitor-keys" "5.11.0" +"@typescript-eslint/scope-manager@5.31.0": + version "5.31.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz#f47a794ba84d9b818ab7f8f44fff55a61016c606" + integrity sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg== + dependencies: + "@typescript-eslint/types" "5.31.0" + "@typescript-eslint/visitor-keys" "5.31.0" + "@typescript-eslint/type-utils@5.11.0": version "5.11.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.11.0.tgz#58be0ba73d1f6ef8983d79f7f0bc2209b253fefe" @@ -3602,6 +3635,15 @@ debug "^4.3.2" tsutils "^3.21.0" +"@typescript-eslint/type-utils@5.31.0": + version "5.31.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.31.0.tgz#70a0b7201360b5adbddb0c36080495aa08f6f3d9" + integrity sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w== + dependencies: + "@typescript-eslint/utils" "5.31.0" + debug "^4.3.4" + tsutils "^3.21.0" + "@typescript-eslint/types@4.33.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" @@ -3612,6 +3654,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.11.0.tgz#ba345818a2540fdf2755c804dc2158517ab61188" integrity sha512-cxgBFGSRCoBEhvSVLkKw39+kMzUKHlJGVwwMbPcTZX3qEhuXhrjwaZXWMxVfxDgyMm+b5Q5b29Llo2yow8Y7xQ== +"@typescript-eslint/types@5.31.0": + version "5.31.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.31.0.tgz#7aa389122b64b18e473c1672fb3b8310e5f07a9a" + integrity sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g== + "@typescript-eslint/typescript-estree@5.11.0": version "5.11.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.11.0.tgz#53f9e09b88368191e52020af77c312a4777ffa43" @@ -3625,6 +3672,19 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.31.0": + version "5.31.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz#eb92970c9d6e3946690d50c346fb9b1d745ee882" + integrity sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw== + dependencies: + "@typescript-eslint/types" "5.31.0" + "@typescript-eslint/visitor-keys" "5.31.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/typescript-estree@^4.16.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" @@ -3650,6 +3710,18 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" +"@typescript-eslint/utils@5.31.0", "@typescript-eslint/utils@^5.10.0": + version "5.31.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.31.0.tgz#e146fa00dca948bfe547d665b2138a2dc1b79acd" + integrity sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.31.0" + "@typescript-eslint/types" "5.31.0" + "@typescript-eslint/typescript-estree" "5.31.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + "@typescript-eslint/visitor-keys@4.33.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" @@ -3666,6 +3738,14 @@ "@typescript-eslint/types" "5.11.0" eslint-visitor-keys "^3.0.0" +"@typescript-eslint/visitor-keys@5.31.0": + version "5.31.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz#b0eca264df01ce85dceb76aebff3784629258f54" + integrity sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg== + dependencies: + "@typescript-eslint/types" "5.31.0" + eslint-visitor-keys "^3.3.0" + "@ungap/promise-all-settled@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" @@ -5206,6 +5286,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -6319,6 +6406,13 @@ eslint-plugin-import@^2.25.2: resolve "^1.20.0" tsconfig-paths "^3.12.0" +eslint-plugin-jest@^26.6.0: + version "26.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.6.0.tgz#546804fa42da75d7d58d4d3b278d5186abd3f6c0" + integrity sha512-f8n46/97ZFdU4KqeQYqO8AEVGIhHWvkpgNBWHH3jrM28/y8llnbf3IjfIKv6p2pZIMinK1PCqbbROxs9Eud02Q== + dependencies: + "@typescript-eslint/utils" "^5.10.0" + eslint-plugin-jsx-a11y@^6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8" @@ -7059,7 +7153,7 @@ globby@^10.0.1: merge2 "^1.2.3" slash "^3.0.0" -globby@^11.0.0, globby@^11.0.3, globby@^11.0.4: +globby@^11.0.0, globby@^11.0.3, globby@^11.0.4, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -10587,6 +10681,13 @@ semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: dependencies: lru-cache "^6.0.0" +semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + serialize-error@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18"