Browse Source

Adds react tests, build tsconfigs

main
Steve Ruiz 3 years ago
parent
commit
b8f410b752
82 changed files with 588 additions and 165 deletions
  1. 9
    3
      package.json
  2. 2
    2
      packages/core/package.json
  3. 1
    1
      packages/core/scripts/build.js
  4. 11
    0
      packages/core/src/components/binding/binding.test.tsx
  5. 1
    0
      packages/core/src/components/binding/binding.tsx
  6. 16
    0
      packages/core/src/components/bounds/bounds.test.tsx
  7. 9
    0
      packages/core/src/components/brush/brush.test.tsx
  8. 17
    0
      packages/core/src/components/canvas/canvas.test.tsx
  9. 4
    4
      packages/core/src/components/canvas/canvas.tsx
  10. 1
    0
      packages/core/src/components/canvas/index.ts
  11. 9
    0
      packages/core/src/components/defs/defs.test.tsx
  12. 0
    0
      packages/core/src/components/defs/defs.tsx
  13. 1
    0
      packages/core/src/components/defs/index.ts
  14. 9
    0
      packages/core/src/components/error-fallback/error-fallback.test.tsx
  15. 1
    2
      packages/core/src/components/error-fallback/error-fallback.tsx
  16. 1
    0
      packages/core/src/components/error-fallback/index.ts
  17. 9
    0
      packages/core/src/components/handles/handles.test.tsx
  18. 1
    0
      packages/core/src/components/page/index.ts
  19. 17
    0
      packages/core/src/components/page/page.test.tsx
  20. 5
    5
      packages/core/src/components/page/page.tsx
  21. 1
    0
      packages/core/src/components/renderer/index.tsx
  22. 17
    0
      packages/core/src/components/renderer/renderer.test.tsx
  23. 3
    3
      packages/core/src/components/renderer/renderer.tsx
  24. 1
    0
      packages/core/src/components/shape-indicator/index.ts
  25. 9
    0
      packages/core/src/components/shape-indicator/shape-indicator.test.tsx
  26. 0
    0
      packages/core/src/components/shape-indicator/shape-indicator.tsx
  27. 17
    0
      packages/core/src/components/shape/shape.test.tsx
  28. 0
    7
      packages/core/src/shapes/example.spec.tsx
  29. 7
    0
      packages/core/src/test-utils/box.spec.tsx
  30. 20
    15
      packages/core/src/test-utils/box.tsx
  31. 20
    0
      packages/core/src/test-utils/context-wrapper.tsx
  32. 5
    0
      packages/core/src/test-utils/index.ts
  33. 19
    0
      packages/core/src/test-utils/mockDocument.ts
  34. 6
    0
      packages/core/src/test-utils/mockUtils.tsx
  35. 7
    0
      packages/core/src/test-utils/renderWithContext.tsx
  36. 11
    0
      packages/core/src/test-utils/renderWithSvg.tsx
  37. 22
    0
      packages/core/tsconfig.build.json
  38. 1
    1
      packages/core/tsconfig.json
  39. 2
    2
      packages/tldraw/package.json
  40. 1
    1
      packages/tldraw/scripts/dev.js
  41. 13
    0
      packages/tldraw/src/components/context-menu/context-menu.test.tsx
  42. 2
    3
      packages/tldraw/src/components/style-panel/quick-color-select.tsx
  43. 2
    3
      packages/tldraw/src/components/style-panel/quick-dash-select.tsx
  44. 1
    3
      packages/tldraw/src/components/style-panel/quick-fill-select.tsx
  45. 1
    3
      packages/tldraw/src/components/style-panel/quick-size-select.tsx
  46. 2
    0
      packages/tldraw/src/components/style-panel/shapes-functions.tsx
  47. 9
    0
      packages/tldraw/src/components/style-panel/style-panel.test.tsx
  48. 1
    0
      packages/tldraw/src/components/tldraw/index.ts
  49. 9
    0
      packages/tldraw/src/components/tldraw/tldraw.test.tsx
  50. 4
    4
      packages/tldraw/src/components/tldraw/tldraw.tsx
  51. 9
    0
      packages/tldraw/src/components/tools-panel/tools-panel.test.tsx
  52. 1
    1
      packages/tldraw/src/state/command/align/align.command.spec.ts
  53. 1
    1
      packages/tldraw/src/state/command/create/create.command.spec.ts
  54. 1
    1
      packages/tldraw/src/state/command/delete/delete.command.spec.ts
  55. 1
    1
      packages/tldraw/src/state/command/distribute/distribute.command.spec.ts
  56. 1
    1
      packages/tldraw/src/state/command/duplicate/duplicate.command.spec.ts
  57. 1
    1
      packages/tldraw/src/state/command/flip/flip.command.spec.ts
  58. 1
    1
      packages/tldraw/src/state/command/move/move.command.spec.ts
  59. 1
    1
      packages/tldraw/src/state/command/rotate/rotate.command.spec.ts
  60. 1
    1
      packages/tldraw/src/state/command/stretch/stretch.command.spec.ts
  61. 1
    1
      packages/tldraw/src/state/command/style/style.command.spec.ts
  62. 1
    1
      packages/tldraw/src/state/command/toggle-decoration/toggle-decoration.command.spec.ts
  63. 1
    1
      packages/tldraw/src/state/command/toggle/toggle.command.spec.ts
  64. 1
    1
      packages/tldraw/src/state/command/translate/translate.command.spec.ts
  65. 1
    1
      packages/tldraw/src/state/session/sessions/arrow/arrow.session.spec.ts
  66. 1
    1
      packages/tldraw/src/state/session/sessions/brush/brush.session.spec.ts
  67. 1
    1
      packages/tldraw/src/state/session/sessions/draw/draw.session.spec.ts
  68. 1
    1
      packages/tldraw/src/state/session/sessions/handle/handle.session.spec.ts
  69. 1
    1
      packages/tldraw/src/state/session/sessions/rotate/rotate.session.spec.ts
  70. 1
    1
      packages/tldraw/src/state/session/sessions/text/text.session.spec.ts
  71. 1
    1
      packages/tldraw/src/state/session/sessions/transform-single/transform-single.session.spec.ts
  72. 1
    1
      packages/tldraw/src/state/session/sessions/transform/transform.session.spec.ts
  73. 1
    1
      packages/tldraw/src/state/session/sessions/translate/translate.session.spec.ts
  74. 1
    1
      packages/tldraw/src/state/tlstate.spec.ts
  75. 3
    0
      packages/tldraw/src/test-utils/index.ts
  76. 66
    0
      packages/tldraw/src/test-utils/mock-document.tsx
  77. 30
    0
      packages/tldraw/src/test-utils/renderWithContext.tsx
  78. 1
    67
      packages/tldraw/src/test-utils/state-utils.tsx
  79. 21
    0
      packages/tldraw/tsconfig.build.json
  80. 1
    1
      packages/tldraw/tsconfig.json
  81. 1
    0
      setupTests.ts
  82. 96
    12
      yarn.lock

+ 9
- 3
package.json View File

@@ -28,18 +28,20 @@
28 28
     "@babel/plugin-syntax-import-meta": "^7.10.4",
29 29
     "@babel/preset-react": "^7.14.5",
30 30
     "@babel/preset-typescript": "^7.15.0",
31
+    "@testing-library/jest-dom": "^5.14.1",
32
+    "@testing-library/react": "^12.0.0",
31 33
     "@types/jest": "^26.0.24",
32 34
     "@types/node": "^15.0.1",
33
-    "@types/react-dom": "^17.0.9",
34 35
     "@types/react": "^17.0.16",
36
+    "@types/react-dom": "^17.0.9",
35 37
     "@typescript-eslint/eslint-plugin": "^4.19.0",
36 38
     "@typescript-eslint/parser": "^4.19.0",
37 39
     "babel-jest": "^27.0.6",
38 40
     "esbuild": "^0.11.11",
39 41
     "jest": "^27.0.6",
40 42
     "lerna": "^3.15.0",
41
-    "react-dom": "^17.0.2",
42 43
     "react": "^17.0.2",
44
+    "react-dom": "^17.0.2",
43 45
     "ts-jest": "^27.0.4",
44 46
     "tslib": "^2.3.0",
45 47
     "typescript": "^4.3.5"
@@ -53,6 +55,9 @@
53 55
   },
54 56
   "jest": {
55 57
     "preset": "ts-jest",
58
+    "setupFilesAfterEnv": [
59
+      "<rootDir>/setupTests.ts"
60
+    ],
56 61
     "transform": {
57 62
       "^.+\\.(tsx|jsx|ts|js)?$": "ts-jest"
58 63
     },
@@ -84,7 +89,8 @@
84 89
     "testEnvironment": "jsdom",
85 90
     "modulePathIgnorePatterns": [
86 91
       "<rootDir>/packages/core/build/",
87
-      "<rootDir>/packages/tldraw/build/"
92
+      "<rootDir>/packages/tldraw/build/",
93
+      "<rootDir>/packages/tldraw/test-utils/"
88 94
     ],
89 95
     "moduleNameMapper": {
90 96
       "@tldraw/core": "<rootDir>/packages/core/src",

+ 2
- 2
packages/core/package.json View File

@@ -15,7 +15,7 @@
15 15
   "types": "./dist/types/index.d.ts",
16 16
   "scripts": {
17 17
     "start": "node scripts/dev & tsc --watch --incremental --emitDeclarationOnly --declarationMap --outDir dist/types",
18
-    "build": "yarn clean && node scripts/build && tsc --emitDeclarationOnly --outDir dist/types",
18
+    "build": "yarn clean && node scripts/build && tsc --project tsconfig.build.json  --emitDeclarationOnly --outDir dist/types",
19 19
     "lint": "eslint src/ --ext .ts,.tsx",
20 20
     "clean": "rm -rf dist",
21 21
     "ts-node": "ts-node",
@@ -49,4 +49,4 @@
49 49
     "react-use-gesture": "^9.1.3"
50 50
   },
51 51
   "gitHead": "a7dac0f83ad998e205c2aab58182cb4ba4e099a6"
52
-}
52
+}

+ 1
- 1
packages/core/scripts/build.js View File

@@ -15,7 +15,7 @@ async function main() {
15 15
       target: 'es6',
16 16
       jsxFactory: 'React.createElement',
17 17
       jsxFragment: 'React.Fragment',
18
-      tsconfig: './tsconfig.json',
18
+      tsconfig: './tsconfig.build.json',
19 19
       external: ['react', 'react-dom'],
20 20
     })
21 21
 

+ 11
- 0
packages/core/src/components/binding/binding.test.tsx View File

@@ -0,0 +1,11 @@
1
+import * as React from 'react'
2
+import { renderWithSvg } from '+test-utils'
3
+import { Binding } from './binding'
4
+
5
+jest.spyOn(console, 'error').mockImplementation(() => void null)
6
+
7
+describe('binding', () => {
8
+  test('mounts component', () => {
9
+    renderWithSvg(<Binding point={[0, 0]} type={'anchor'} />)
10
+  })
11
+})

+ 1
- 0
packages/core/src/components/binding/binding.tsx View File

@@ -1,3 +1,4 @@
1
+import * as React from 'react'
1 2
 import type { TLBinding } from '+types'
2 3
 
3 4
 interface BindingProps {

+ 16
- 0
packages/core/src/components/bounds/bounds.test.tsx View File

@@ -0,0 +1,16 @@
1
+import * as React from 'react'
2
+import { renderWithSvg } from '+test-utils'
3
+import { Bounds } from './bounds'
4
+
5
+describe('bounds', () => {
6
+  test('mounts component', () => {
7
+    renderWithSvg(
8
+      <Bounds
9
+        zoom={1}
10
+        bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
11
+        rotation={0}
12
+        isLocked={false}
13
+      />
14
+    )
15
+  })
16
+})

+ 9
- 0
packages/core/src/components/brush/brush.test.tsx View File

@@ -0,0 +1,9 @@
1
+import * as React from 'react'
2
+import { renderWithSvg } from '+test-utils'
3
+import { Brush } from './brush'
4
+
5
+describe('brush', () => {
6
+  test('mounts component', () => {
7
+    renderWithSvg(<Brush />)
8
+  })
9
+})

+ 17
- 0
packages/core/src/components/canvas/canvas.test.tsx View File

@@ -0,0 +1,17 @@
1
+import * as React from 'react'
2
+import { mockDocument, renderWithContext } from '+test-utils'
3
+import { Canvas } from './canvas'
4
+
5
+describe('page', () => {
6
+  test('mounts component', () => {
7
+    renderWithContext(
8
+      <Canvas
9
+        page={mockDocument.page}
10
+        pageState={mockDocument.pageState}
11
+        hideBounds={false}
12
+        hideIndicators={false}
13
+        hideHandles={false}
14
+      />
15
+    )
16
+  })
17
+})

packages/core/src/components/canvas.tsx → packages/core/src/components/canvas/canvas.tsx View File

@@ -8,10 +8,10 @@ import {
8 8
   useCameraCss,
9 9
 } from '+hooks'
10 10
 import type { TLBinding, TLPage, TLPageState, TLShape } from '+types'
11
-import { ErrorFallback } from './error-fallback'
12
-import { Brush } from './brush'
13
-import { Defs } from './defs'
14
-import { Page } from './page'
11
+import { ErrorFallback } from '+components/error-fallback'
12
+import { Brush } from '+components/brush'
13
+import { Defs } from '+components/defs'
14
+import { Page } from '+components/page'
15 15
 
16 16
 function resetError() {
17 17
   void null

+ 1
- 0
packages/core/src/components/canvas/index.ts View File

@@ -0,0 +1 @@
1
+export * from './canvas'

+ 9
- 0
packages/core/src/components/defs/defs.test.tsx View File

@@ -0,0 +1,9 @@
1
+import * as React from 'react'
2
+import { renderWithSvg } from '+test-utils'
3
+import { Defs } from './defs'
4
+
5
+describe('defs', () => {
6
+  test('mounts component', () => {
7
+    renderWithSvg(<Defs zoom={1} />)
8
+  })
9
+})

packages/core/src/components/defs.tsx → packages/core/src/components/defs/defs.tsx View File


+ 1
- 0
packages/core/src/components/defs/index.ts View File

@@ -0,0 +1 @@
1
+export * from './defs'

+ 9
- 0
packages/core/src/components/error-fallback/error-fallback.test.tsx View File

@@ -0,0 +1,9 @@
1
+import * as React from 'react'
2
+import { renderWithContext } from '+test-utils'
3
+import { ErrorFallback } from './error-fallback'
4
+
5
+describe('error fallback', () => {
6
+  test('mounts component', () => {
7
+    renderWithContext(<ErrorFallback error={new Error()} resetErrorBoundary={() => void null} />)
8
+  })
9
+})

packages/core/src/components/error-fallback.tsx → packages/core/src/components/error-fallback/error-fallback.tsx View File

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import { useTLContext } from '../hooks'
2
+import { useTLContext } from '+hooks'
3 3
 
4 4
 interface ErrorFallbackProps {
5 5
   error: Error
@@ -11,7 +11,6 @@ export const ErrorFallback = React.memo(({ error, resetErrorBoundary }: ErrorFal
11 11
 
12 12
   React.useEffect(() => {
13 13
     callbacks.onError?.(error)
14
-    console.error(error)
15 14
   }, [error, resetErrorBoundary, callbacks])
16 15
 
17 16
   return null

+ 1
- 0
packages/core/src/components/error-fallback/index.ts View File

@@ -0,0 +1 @@
1
+export * from './error-fallback'

+ 9
- 0
packages/core/src/components/handles/handles.test.tsx View File

@@ -0,0 +1,9 @@
1
+import * as React from 'react'
2
+import { mockUtils, renderWithContext } from '+test-utils'
3
+import { Handles } from './handles'
4
+
5
+describe('handles', () => {
6
+  test('mounts component', () => {
7
+    renderWithContext(<Handles zoom={1} shape={mockUtils.box.create({})} />)
8
+  })
9
+})

+ 1
- 0
packages/core/src/components/page/index.ts View File

@@ -0,0 +1 @@
1
+export * from './page'

+ 17
- 0
packages/core/src/components/page/page.test.tsx View File

@@ -0,0 +1,17 @@
1
+import * as React from 'react'
2
+import { mockDocument, renderWithContext } from '+test-utils'
3
+import { Page } from './page'
4
+
5
+describe('page', () => {
6
+  test('mounts component', () => {
7
+    renderWithContext(
8
+      <Page
9
+        page={mockDocument.page}
10
+        pageState={mockDocument.pageState}
11
+        hideBounds={false}
12
+        hideIndicators={false}
13
+        hideHandles={false}
14
+      />
15
+    )
16
+  })
17
+})

packages/core/src/components/page.tsx → packages/core/src/components/page/page.tsx View File

@@ -1,11 +1,11 @@
1 1
 import * as React from 'react'
2 2
 import type { TLBinding, TLPage, TLPageState, TLShape } from '+types'
3 3
 import { useSelection, useShapeTree, useHandles, useRenderOnResize, useTLContext } from '+hooks'
4
-import { Bounds } from './bounds'
5
-import { BoundsBg } from './bounds/bounds-bg'
6
-import { Handles } from './handles'
7
-import { ShapeIndicator } from './shape-indicator'
8
-import { ShapeNode } from './shape'
4
+import { Bounds } from '+components/bounds'
5
+import { BoundsBg } from '+components/bounds/bounds-bg'
6
+import { Handles } from '+components/handles'
7
+import { ShapeNode } from '+components/shape'
8
+import { ShapeIndicator } from '+components/shape-indicator'
9 9
 
10 10
 interface PageProps<T extends TLShape> {
11 11
   page: TLPage<T, TLBinding>

+ 1
- 0
packages/core/src/components/renderer/index.tsx View File

@@ -0,0 +1 @@
1
+export * from './renderer'

+ 17
- 0
packages/core/src/components/renderer/renderer.test.tsx View File

@@ -0,0 +1,17 @@
1
+import * as React from 'react'
2
+import { mockDocument } from '+test-utils/mockDocument'
3
+import { mockUtils } from '+test-utils/mockUtils'
4
+import { render } from '@testing-library/react'
5
+import { Renderer } from './renderer'
6
+
7
+describe('context menu', () => {
8
+  test('mounts component', () => {
9
+    render(
10
+      <Renderer
11
+        shapeUtils={mockUtils}
12
+        page={mockDocument.page}
13
+        pageState={mockDocument.pageState}
14
+      />
15
+    )
16
+  })
17
+})

packages/core/src/components/renderer.tsx → packages/core/src/components/renderer/renderer.tsx View File

@@ -9,9 +9,9 @@ import type {
9 9
   TLTheme,
10 10
   TLBounds,
11 11
   TLBinding,
12
-} from '../types'
13
-import { Canvas } from '../components/canvas'
14
-import { useTLTheme, TLContext } from '../hooks'
12
+} from '../../types'
13
+import { Canvas } from '../canvas'
14
+import { useTLTheme, TLContext } from '../../hooks'
15 15
 
16 16
 export interface RendererProps<T extends TLShape>
17 17
   extends Partial<TLSettings>,

+ 1
- 0
packages/core/src/components/shape-indicator/index.ts View File

@@ -0,0 +1 @@
1
+export * from './shape-indicator'

+ 9
- 0
packages/core/src/components/shape-indicator/shape-indicator.test.tsx View File

@@ -0,0 +1,9 @@
1
+import * as React from 'react'
2
+import { mockUtils, renderWithSvg } from '+test-utils'
3
+import { ShapeIndicator } from './shape-indicator'
4
+
5
+describe('shape indicator', () => {
6
+  test('mounts component', () => {
7
+    renderWithSvg(<ShapeIndicator shape={mockUtils.box.create({})} variant={'selected'} />)
8
+  })
9
+})

packages/core/src/components/shape-indicator.tsx → packages/core/src/components/shape-indicator/shape-indicator.tsx View File


+ 17
- 0
packages/core/src/components/shape/shape.test.tsx View File

@@ -0,0 +1,17 @@
1
+import * as React from 'react'
2
+import { mockUtils, renderWithSvg } from '+test-utils'
3
+import { Shape } from './shape'
4
+
5
+describe('handles', () => {
6
+  test('mounts component', () => {
7
+    renderWithSvg(
8
+      <Shape
9
+        shape={mockUtils.box.create({})}
10
+        isEditing={false}
11
+        isBinding={false}
12
+        isDarkMode={false}
13
+        isCurrentParent={false}
14
+      />
15
+    )
16
+  })
17
+})

+ 0
- 7
packages/core/src/shapes/example.spec.tsx View File

@@ -1,7 +0,0 @@
1
-import { ExampleShape } from './example-shape'
2
-
3
-describe('example shape', () => {
4
-  it('should create an instance', () => {
5
-    expect(new ExampleShape()).toBeTruthy()
6
-  })
7
-})

+ 7
- 0
packages/core/src/test-utils/box.spec.tsx View File

@@ -0,0 +1,7 @@
1
+import { Box } from './box'
2
+
3
+describe('example shape', () => {
4
+  it('should create an instance', () => {
5
+    expect(new Box()).toBeTruthy()
6
+  })
7
+})

packages/core/src/shapes/example-shape.tsx → packages/core/src/test-utils/box.tsx View File

@@ -3,36 +3,41 @@ import * as React from 'react'
3 3
 import { TLShapeUtil, TLShape, TLBounds, TLRenderInfo, TLTransformInfo } from '+types'
4 4
 import Utils, { Intersect } from '+utils'
5 5
 
6
-export class ExampleShape extends TLShapeUtil<TLShape> {
7
-  type = 'shape-type'
6
+export interface BoxShape extends TLShape {
7
+  size: number[]
8
+}
9
+
10
+export class Box extends TLShapeUtil<BoxShape> {
11
+  type = 'box'
8 12
 
9 13
   defaultProps = {
10
-    id: 'example',
11
-    type: 'shape-type',
14
+    id: 'example1',
15
+    type: 'box',
12 16
     parentId: 'page',
13 17
     childIndex: 0,
14 18
     name: 'Example Shape',
15 19
     point: [0, 0],
20
+    size: [100, 100],
16 21
     rotation: 0,
17 22
   }
18 23
 
19
-  create(props: Partial<TLShape>) {
24
+  create(props: Partial<BoxShape>) {
20 25
     return { ...this.defaultProps, ...props }
21 26
   }
22 27
 
23
-  render(shape: TLShape, info: TLRenderInfo): JSX.Element {
28
+  render(shape: BoxShape, info: TLRenderInfo): JSX.Element {
24 29
     return <rect width={100} height={100} fill="none" stroke="black" />
25 30
   }
26 31
 
27
-  renderIndicator(shape: TLShape) {
32
+  renderIndicator(shape: BoxShape) {
28 33
     return <rect width={100} height={100} />
29 34
   }
30 35
 
31
-  shouldRender(prev: TLShape, next: TLShape): boolean {
36
+  shouldRender(prev: BoxShape, next: BoxShape): boolean {
32 37
     return true
33 38
   }
34 39
 
35
-  getBounds(shape: TLShape): TLBounds {
40
+  getBounds(shape: BoxShape): TLBounds {
36 41
     return Utils.getFromCache(this.boundsCache, shape, () => ({
37 42
       minX: 0,
38 43
       minY: 0,
@@ -43,19 +48,19 @@ export class ExampleShape extends TLShapeUtil<TLShape> {
43 48
     }))
44 49
   }
45 50
 
46
-  getRotatedBounds(shape: TLShape) {
51
+  getRotatedBounds(shape: BoxShape) {
47 52
     return Utils.getBoundsFromPoints(Utils.getRotatedCorners(this.getBounds(shape), shape.rotation))
48 53
   }
49 54
 
50
-  getCenter(shape: TLShape): number[] {
55
+  getCenter(shape: BoxShape): number[] {
51 56
     return Utils.getBoundsCenter(this.getBounds(shape))
52 57
   }
53 58
 
54
-  hitTest(shape: TLShape, point: number[]) {
59
+  hitTest(shape: BoxShape, point: number[]) {
55 60
     return Utils.pointInBounds(point, this.getBounds(shape))
56 61
   }
57 62
 
58
-  hitTestBounds(shape: TLShape, bounds: TLBounds) {
63
+  hitTestBounds(shape: BoxShape, bounds: TLBounds) {
59 64
     const rotatedCorners = Utils.getRotatedCorners(this.getBounds(shape), shape.rotation)
60 65
 
61 66
     return (
@@ -64,11 +69,11 @@ export class ExampleShape extends TLShapeUtil<TLShape> {
64 69
     )
65 70
   }
66 71
 
67
-  transform(shape: TLShape, bounds: TLBounds, _info: TLTransformInfo<TLShape>): TLShape {
72
+  transform(shape: BoxShape, bounds: TLBounds, _info: TLTransformInfo<BoxShape>): BoxShape {
68 73
     return { ...shape, point: [bounds.minX, bounds.minY] }
69 74
   }
70 75
 
71
-  transformSingle(shape: TLShape, bounds: TLBounds, info: TLTransformInfo<TLShape>): TLShape {
76
+  transformSingle(shape: BoxShape, bounds: TLBounds, info: TLTransformInfo<BoxShape>): BoxShape {
72 77
     return this.transform(shape, bounds, info)
73 78
   }
74 79
 }

+ 20
- 0
packages/core/src/test-utils/context-wrapper.tsx View File

@@ -0,0 +1,20 @@
1
+import * as React from 'react'
2
+import type { TLPageState, TLBounds } from '../types'
3
+import { mockDocument } from './mockDocument'
4
+import { mockUtils } from './mockUtils'
5
+import { useTLTheme, TLContext } from '../hooks'
6
+
7
+export const ContextWrapper: React.FC = ({ children }) => {
8
+  useTLTheme()
9
+  const rScreenBounds = React.useRef<TLBounds>(null)
10
+  const rPageState = React.useRef<TLPageState>(mockDocument.pageState)
11
+
12
+  const [context] = React.useState(() => ({
13
+    callbacks: {},
14
+    shapeUtils: mockUtils,
15
+    rScreenBounds,
16
+    rPageState,
17
+  }))
18
+
19
+  return <TLContext.Provider value={context}>{children}</TLContext.Provider>
20
+}

+ 5
- 0
packages/core/src/test-utils/index.ts View File

@@ -0,0 +1,5 @@
1
+export * from './box'
2
+export * from './mockDocument'
3
+export * from './mockUtils'
4
+export * from './renderWithContext'
5
+export * from './renderWithSvg'

+ 19
- 0
packages/core/src/test-utils/mockDocument.ts View File

@@ -0,0 +1,19 @@
1
+import type { TLBinding, TLPage, TLPageState } from '+types'
2
+import type { BoxShape } from './box'
3
+
4
+export const mockDocument: { page: TLPage<BoxShape, TLBinding>; pageState: TLPageState } = {
5
+  page: {
6
+    id: 'page1',
7
+    shapes: {},
8
+    bindings: {},
9
+  },
10
+  pageState: {
11
+    id: 'page1',
12
+    selectedIds: [],
13
+    currentParentId: 'page1',
14
+    camera: {
15
+      point: [0, 0],
16
+      zoom: 1,
17
+    },
18
+  },
19
+}

+ 6
- 0
packages/core/src/test-utils/mockUtils.tsx View File

@@ -0,0 +1,6 @@
1
+import type { TLShapeUtils } from '+types'
2
+import { Box, BoxShape } from './box'
3
+
4
+export const mockUtils: TLShapeUtils<BoxShape> = {
5
+  box: new Box(),
6
+}

+ 7
- 0
packages/core/src/test-utils/renderWithContext.tsx View File

@@ -0,0 +1,7 @@
1
+import * as React from 'react'
2
+import { render } from '@testing-library/react'
3
+import { ContextWrapper } from './context-wrapper'
4
+
5
+export const renderWithContext = (children: JSX.Element) => {
6
+  return render(<ContextWrapper>{children}</ContextWrapper>)
7
+}

+ 11
- 0
packages/core/src/test-utils/renderWithSvg.tsx View File

@@ -0,0 +1,11 @@
1
+import * as React from 'react'
2
+import { render } from '@testing-library/react'
3
+import { ContextWrapper } from './context-wrapper'
4
+
5
+export const renderWithSvg = (children: JSX.Element) => {
6
+  return render(
7
+    <ContextWrapper>
8
+      <svg>{children}</svg>
9
+    </ContextWrapper>
10
+  )
11
+}

+ 22
- 0
packages/core/tsconfig.build.json View File

@@ -0,0 +1,22 @@
1
+{
2
+  "extends": "../../tsconfig.base.json",
3
+  "include": ["src"],
4
+  "exclude": [
5
+    "node_modules",
6
+    "**/*.test.tsx",
7
+    "**/*.test.ts",
8
+    "**/*.spec.tsx",
9
+    "**/*.spec.ts",
10
+    "src/test-utils",
11
+    "dist"
12
+  ],
13
+  "compilerOptions": {
14
+    "declaration": true,
15
+    "rootDir": "src",
16
+    "outDir": "./dist/types",
17
+    "baseUrl": "src",
18
+    "paths": {
19
+      "+*": ["./*"]
20
+    }
21
+  }
22
+}

+ 1
- 1
packages/core/tsconfig.json View File

@@ -1,7 +1,7 @@
1 1
 {
2 2
   "extends": "../../tsconfig.base.json",
3 3
   "include": ["src"],
4
-  "exclude": ["node_modules", "**/*.test.ts", "**/*.spec.ts", "dist"],
4
+  "exclude": ["node_modules", "dist"],
5 5
   "compilerOptions": {
6 6
     "rootDir": "src",
7 7
     "outDir": "./dist/types",

+ 2
- 2
packages/tldraw/package.json View File

@@ -16,7 +16,7 @@
16 16
   "typings": "./dist/types/index.d.ts",
17 17
   "scripts": {
18 18
     "start": "node scripts/dev & tsc --watch --incremental --emitDeclarationOnly --declarationMap --outDir dist/types",
19
-    "build": "yarn clean && node scripts/build && tsc --emitDeclarationOnly --outDir dist/types",
19
+    "build": "yarn clean && node scripts/build && tsc --project tsconfig.build.json --emitDeclarationOnly --outDir dist/types",
20 20
     "lint": "eslint src/ --ext .ts,.tsx",
21 21
     "clean": "rm -rf dist",
22 22
     "ts-node": "ts-node",
@@ -59,4 +59,4 @@
59 59
     "zustand": "^3.5.7"
60 60
   },
61 61
   "gitHead": "4a7439ddf81b615ee49fddbe00802699975f9375"
62
-}
62
+}

+ 1
- 1
packages/tldraw/scripts/dev.js View File

@@ -14,7 +14,7 @@ async function main() {
14 14
     target: 'esnext',
15 15
     jsxFactory: 'React.createElement',
16 16
     jsxFragment: 'React.Fragment',
17
-    tsconfig: './tsconfig.json',
17
+    tsconfig: './tsconfig.build.json',
18 18
     external: ['react', 'react-dom'],
19 19
     watch: {
20 20
       onRebuild(error) {

+ 13
- 0
packages/tldraw/src/components/context-menu/context-menu.test.tsx View File

@@ -0,0 +1,13 @@
1
+import * as React from 'react'
2
+import { ContextMenu } from './context-menu'
3
+import { renderWithContext } from '~test-utils'
4
+
5
+describe('context menu', () => {
6
+  test('mounts component', () => {
7
+    renderWithContext(
8
+      <ContextMenu>
9
+        <div>Hello</div>
10
+      </ContextMenu>
11
+    )
12
+  })
13
+})

+ 2
- 3
packages/tldraw/src/components/style-panel/quick-color-select.tsx View File

@@ -11,12 +11,11 @@ const selectColor = (data: Data) => data.appState.selectedStyle.color
11 11
 export const QuickColorSelect = React.memo((): JSX.Element => {
12 12
   const { theme } = useTheme()
13 13
   const { tlstate, useSelector } = useTLDrawContext()
14
+
14 15
   const color = useSelector(selectColor)
15 16
 
16 17
   const handleColorChange = React.useCallback(
17
-    (color) => {
18
-      tlstate.style({ color: color as ColorStyle })
19
-    },
18
+    (color) => tlstate.style({ color: color as ColorStyle }),
20 19
     [tlstate]
21 20
   )
22 21
 

+ 2
- 3
packages/tldraw/src/components/style-panel/quick-dash-select.tsx View File

@@ -23,12 +23,11 @@ const selectDash = (data: Data) => data.appState.selectedStyle.dash
23 23
 
24 24
 export const QuickDashSelect = React.memo((): JSX.Element => {
25 25
   const { tlstate, useSelector } = useTLDrawContext()
26
+
26 27
   const dash = useSelector(selectDash)
27 28
 
28 29
   const changeDashStyle = React.useCallback(
29
-    (dash) => {
30
-      tlstate.style({ dash: dash as DashStyle })
31
-    },
30
+    (dash) => tlstate.style({ dash: dash as DashStyle }),
32 31
     [tlstate]
33 32
   )
34 33
 

+ 1
- 3
packages/tldraw/src/components/style-panel/quick-fill-select.tsx View File

@@ -13,9 +13,7 @@ export const QuickFillSelect = React.memo((): JSX.Element => {
13 13
   const isFilled = useSelector(isFilledSelector)
14 14
 
15 15
   const handleIsFilledChange = React.useCallback(
16
-    (isFilled: boolean) => {
17
-      tlstate.style({ isFilled })
18
-    },
16
+    (isFilled: boolean) => tlstate.style({ isFilled }),
19 17
     [tlstate]
20 18
   )
21 19
 

+ 1
- 3
packages/tldraw/src/components/style-panel/quick-size-select.tsx View File

@@ -20,9 +20,7 @@ export const QuickSizeSelect = React.memo((): JSX.Element => {
20 20
   const size = useSelector(selectSize)
21 21
 
22 22
   const changeSizeStyle = React.useCallback(
23
-    (size: string) => {
24
-      tlstate.style({ size: size as SizeStyle })
25
-    },
23
+    (size: string) => tlstate.style({ size: size as SizeStyle }),
26 24
     [tlstate]
27 25
   )
28 26
 

+ 2
- 0
packages/tldraw/src/components/style-panel/shapes-functions.tsx View File

@@ -42,6 +42,8 @@ const hasSelectionSelector = (s: Data) => s.pageState.selectedIds.length > 0
42 42
 const hasMultipleSelectionSelector = (s: Data) => s.pageState.selectedIds.length > 1
43 43
 
44 44
 export const ShapesFunctions = React.memo(() => {
45
+  const ok = useTLDrawContext()
46
+  console.log(ok)
45 47
   const { tlstate, useSelector } = useTLDrawContext()
46 48
 
47 49
   const isAllLocked = useSelector(isAllLockedSelector)

+ 9
- 0
packages/tldraw/src/components/style-panel/style-panel.test.tsx View File

@@ -0,0 +1,9 @@
1
+import * as React from 'react'
2
+import { renderWithContext } from '~test-utils'
3
+import { StylePanel } from './style-panel'
4
+
5
+describe('style panel', () => {
6
+  test('mounts component', () => {
7
+    renderWithContext(<StylePanel />)
8
+  })
9
+})

+ 1
- 0
packages/tldraw/src/components/tldraw/index.ts View File

@@ -0,0 +1 @@
1
+export * from './tldraw'

+ 9
- 0
packages/tldraw/src/components/tldraw/tldraw.test.tsx View File

@@ -0,0 +1,9 @@
1
+import * as React from 'react'
2
+import { render } from '@testing-library/react'
3
+import { TLDraw } from './tldraw'
4
+
5
+describe('tldraw', () => {
6
+  test('mounts component', () => {
7
+    render(<TLDraw />)
8
+  })
9
+})

packages/tldraw/src/components/tldraw.tsx → packages/tldraw/src/components/tldraw/tldraw.tsx View File

@@ -5,10 +5,10 @@ import styled from '~styles'
5 5
 import type { Data, TLDrawDocument } from '~types'
6 6
 import { TLDrawState } from '~state'
7 7
 import { useKeyboardShortcuts, TLDrawContext } from '~hooks'
8
-import { tldrawShapeUtils } from '../shape'
9
-import { ContextMenu } from './context-menu'
10
-import { StylePanel } from './style-panel'
11
-import { ToolsPanel } from './tools-panel'
8
+import { tldrawShapeUtils } from '~shape'
9
+import { ContextMenu } from '~components/context-menu'
10
+import { StylePanel } from '~components/style-panel'
11
+import { ToolsPanel } from '~components/tools-panel'
12 12
 
13 13
 export interface TLDrawProps {
14 14
   document?: TLDrawDocument

+ 9
- 0
packages/tldraw/src/components/tools-panel/tools-panel.test.tsx View File

@@ -0,0 +1,9 @@
1
+import * as React from 'react'
2
+import { ToolsPanel } from './tools-panel'
3
+import { renderWithContext } from '~test-utils'
4
+
5
+describe('tools panel', () => {
6
+  test('mounts component', () => {
7
+    renderWithContext(<ToolsPanel />)
8
+  })
9
+})

+ 1
- 1
packages/tldraw/src/state/command/align/align.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { AlignType } from '~types'
4 4
 
5 5
 describe('Align command', () => {

+ 1
- 1
packages/tldraw/src/state/command/create/create.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 
4 4
 describe('Create command', () => {
5 5
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/command/delete/delete.command.spec.ts View File

@@ -1,6 +1,6 @@
1 1
 import { TLDR } from '~state/tldr'
2 2
 import { TLDrawState } from '~state'
3
-import { mockDocument } from '~state/test-helpers'
3
+import { mockDocument } from '~test-utils'
4 4
 import type { TLDrawShape } from '~types'
5 5
 
6 6
 describe('Delete command', () => {

+ 1
- 1
packages/tldraw/src/state/command/distribute/distribute.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { DistributeType } from '~types'
4 4
 
5 5
 describe('Distribute command', () => {

+ 1
- 1
packages/tldraw/src/state/command/duplicate/duplicate.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 
4 4
 describe('Duplicate command', () => {
5 5
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/command/flip/flip.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import type { RectangleShape } from '~types'
4 4
 
5 5
 describe('Stretch command', () => {

+ 1
- 1
packages/tldraw/src/state/command/move/move.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { Utils } from '@tldraw/core'
4 4
 import type { Data } from '~types'
5 5
 

+ 1
- 1
packages/tldraw/src/state/command/rotate/rotate.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 
4 4
 describe('Rotate command', () => {
5 5
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/command/stretch/stretch.command.spec.ts View File

@@ -1,6 +1,6 @@
1 1
 import { StretchType, RectangleShape } from '~types'
2 2
 import { TLDrawState } from '~state'
3
-import { mockDocument } from '~state/test-helpers'
3
+import { mockDocument } from '~test-utils'
4 4
 
5 5
 describe('Stretch command', () => {
6 6
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/command/style/style.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { SizeStyle } from '~types'
4 4
 
5 5
 describe('Style command', () => {

+ 1
- 1
packages/tldraw/src/state/command/toggle-decoration/toggle-decoration.command.spec.ts View File

@@ -1,6 +1,6 @@
1 1
 import { TLDR } from '~state/tldr'
2 2
 import { TLDrawState } from '~state'
3
-import { mockDocument } from '~state/test-helpers'
3
+import { mockDocument } from '~test-utils'
4 4
 import { ArrowShape, Decoration, TLDrawShape } from '~types'
5 5
 
6 6
 describe('Handle command', () => {

+ 1
- 1
packages/tldraw/src/state/command/toggle/toggle.command.spec.ts View File

@@ -1,6 +1,6 @@
1 1
 import type { RectangleShape } from '~types'
2 2
 import { TLDrawState } from '~state'
3
-import { mockDocument } from '~state/test-helpers'
3
+import { mockDocument } from '~test-utils'
4 4
 
5 5
 describe('Toggle command', () => {
6 6
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/command/translate/translate.command.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 
4 4
 describe('Translate command', () => {
5 5
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/session/sessions/arrow/arrow.session.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { TLDR } from '~state/tldr'
4 4
 import type { ArrowShape, TLDrawShape } from '~types'
5 5
 

+ 1
- 1
packages/tldraw/src/state/session/sessions/brush/brush.session.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 
4 4
 describe('Brush session', () => {
5 5
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/session/sessions/draw/draw.session.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { ColorStyle, DashStyle, SizeStyle, TLDrawShapeType } from '~types'
4 4
 
5 5
 describe('Transform session', () => {

+ 1
- 1
packages/tldraw/src/state/session/sessions/handle/handle.session.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { TLDR } from '~state/tldr'
4 4
 import type { TLDrawShape } from '~types'
5 5
 

+ 1
- 1
packages/tldraw/src/state/session/sessions/rotate/rotate.session.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 
4 4
 describe('Brush session', () => {
5 5
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/session/sessions/text/text.session.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { TLDR } from '~state/tldr'
4 4
 import { TextShape, TLDrawShape, TLDrawShapeType } from '~types'
5 5
 

+ 1
- 1
packages/tldraw/src/state/session/sessions/transform-single/transform-single.session.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { TLBoundsCorner } from '@tldraw/core'
4 4
 
5 5
 describe('Transform single session', () => {

+ 1
- 1
packages/tldraw/src/state/session/sessions/transform/transform.session.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from '~state'
2
-import { mockDocument } from '~state/test-helpers'
2
+import { mockDocument } from '~test-utils'
3 3
 import { TLBoundsCorner, Utils } from '@tldraw/core'
4 4
 import { TLDR } from '~state/tldr'
5 5
 

+ 1
- 1
packages/tldraw/src/state/session/sessions/translate/translate.session.spec.ts View File

@@ -1,6 +1,6 @@
1 1
 import { TLDR } from '~state/tldr'
2 2
 import { TLDrawState } from '~state'
3
-import { mockDocument } from '~state/test-helpers'
3
+import { mockDocument } from '~test-utils'
4 4
 import type { TLDrawShape } from '~types'
5 5
 
6 6
 describe('Brush session', () => {

+ 1
- 1
packages/tldraw/src/state/tlstate.spec.ts View File

@@ -1,5 +1,5 @@
1 1
 import { TLDrawState } from './tlstate'
2
-import { mockDocument, TLStateUtils } from './test-helpers'
2
+import { mockDocument, TLStateUtils } from '~test-utils'
3 3
 
4 4
 describe('TLDrawState', () => {
5 5
   const tlstate = new TLDrawState()

+ 3
- 0
packages/tldraw/src/test-utils/index.ts View File

@@ -0,0 +1,3 @@
1
+export * from './mock-document'
2
+export * from './renderWithContext'
3
+export * from './state-utils'

+ 66
- 0
packages/tldraw/src/test-utils/mock-document.tsx View File

@@ -0,0 +1,66 @@
1
+import { TLDrawDocument, ColorStyle, DashStyle, SizeStyle, TLDrawShapeType } from '~types'
2
+
3
+export const mockDocument: TLDrawDocument = {
4
+  id: 'doc',
5
+  pages: {
6
+    page1: {
7
+      id: 'page1',
8
+      shapes: {
9
+        rect1: {
10
+          id: 'rect1',
11
+          parentId: 'page1',
12
+          name: 'Rectangle',
13
+          childIndex: 1,
14
+          type: TLDrawShapeType.Rectangle,
15
+          point: [0, 0],
16
+          size: [100, 100],
17
+          style: {
18
+            dash: DashStyle.Draw,
19
+            size: SizeStyle.Medium,
20
+            color: ColorStyle.Blue,
21
+          },
22
+        },
23
+        rect2: {
24
+          id: 'rect2',
25
+          parentId: 'page1',
26
+          name: 'Rectangle',
27
+          childIndex: 2,
28
+          type: TLDrawShapeType.Rectangle,
29
+          point: [100, 100],
30
+          size: [100, 100],
31
+          style: {
32
+            dash: DashStyle.Draw,
33
+            size: SizeStyle.Medium,
34
+            color: ColorStyle.Blue,
35
+          },
36
+        },
37
+        rect3: {
38
+          id: 'rect3',
39
+          parentId: 'page1',
40
+          name: 'Rectangle',
41
+          childIndex: 3,
42
+          type: TLDrawShapeType.Rectangle,
43
+          point: [20, 20],
44
+          size: [100, 100],
45
+          style: {
46
+            dash: DashStyle.Draw,
47
+            size: SizeStyle.Medium,
48
+            color: ColorStyle.Blue,
49
+          },
50
+        },
51
+      },
52
+      bindings: {},
53
+    },
54
+  },
55
+  pageStates: {
56
+    page1: {
57
+      id: 'page1',
58
+      selectedIds: [],
59
+      currentParentId: 'page1',
60
+      camera: {
61
+        point: [0, 0],
62
+        zoom: 1,
63
+      },
64
+    },
65
+  },
66
+}

+ 30
- 0
packages/tldraw/src/test-utils/renderWithContext.tsx View File

@@ -0,0 +1,30 @@
1
+import * as React from 'react'
2
+import { IdProvider } from '@radix-ui/react-id'
3
+import { TLDrawState } from '~state'
4
+import { useKeyboardShortcuts, TLDrawContext } from '~hooks'
5
+import { mockDocument } from './mock-document'
6
+import { render } from '@testing-library/react'
7
+
8
+export const Wrapper: React.FC = ({ children }) => {
9
+  const [tlstate] = React.useState(() => new TLDrawState())
10
+  const [context] = React.useState(() => {
11
+    return { tlstate, useSelector: tlstate.store }
12
+  })
13
+
14
+  useKeyboardShortcuts(tlstate)
15
+
16
+  React.useEffect(() => {
17
+    if (!document) return
18
+    tlstate.loadDocument(mockDocument)
19
+  }, [document, tlstate])
20
+
21
+  return (
22
+    <TLDrawContext.Provider value={context}>
23
+      <IdProvider>{children}</IdProvider>
24
+    </TLDrawContext.Provider>
25
+  )
26
+}
27
+
28
+export const renderWithContext = (children: JSX.Element) => {
29
+  return render(<Wrapper>{children}</Wrapper>)
30
+}

packages/tldraw/src/state/test-helpers.ts → packages/tldraw/src/test-utils/state-utils.tsx View File

@@ -1,6 +1,5 @@
1 1
 import { inputs, TLBoundsEdge, TLBoundsCorner } from '@tldraw/core'
2
-import { TLDrawDocument, ColorStyle, DashStyle, SizeStyle, TLDrawShapeType } from '~types'
3
-import type { TLDrawState } from './tlstate'
2
+import type { TLDrawState } from '~state'
4 3
 
5 4
 interface PointerOptions {
6 5
   id?: number
@@ -99,68 +98,3 @@ export class TLStateUtils {
99 98
     } as PointerEvent
100 99
   }
101 100
 }
102
-
103
-export const mockDocument: TLDrawDocument = {
104
-  id: 'doc',
105
-  pages: {
106
-    page1: {
107
-      id: 'page1',
108
-      shapes: {
109
-        rect1: {
110
-          id: 'rect1',
111
-          parentId: 'page1',
112
-          name: 'Rectangle',
113
-          childIndex: 1,
114
-          type: TLDrawShapeType.Rectangle,
115
-          point: [0, 0],
116
-          size: [100, 100],
117
-          style: {
118
-            dash: DashStyle.Draw,
119
-            size: SizeStyle.Medium,
120
-            color: ColorStyle.Blue,
121
-          },
122
-        },
123
-        rect2: {
124
-          id: 'rect2',
125
-          parentId: 'page1',
126
-          name: 'Rectangle',
127
-          childIndex: 2,
128
-          type: TLDrawShapeType.Rectangle,
129
-          point: [100, 100],
130
-          size: [100, 100],
131
-          style: {
132
-            dash: DashStyle.Draw,
133
-            size: SizeStyle.Medium,
134
-            color: ColorStyle.Blue,
135
-          },
136
-        },
137
-        rect3: {
138
-          id: 'rect3',
139
-          parentId: 'page1',
140
-          name: 'Rectangle',
141
-          childIndex: 3,
142
-          type: TLDrawShapeType.Rectangle,
143
-          point: [20, 20],
144
-          size: [100, 100],
145
-          style: {
146
-            dash: DashStyle.Draw,
147
-            size: SizeStyle.Medium,
148
-            color: ColorStyle.Blue,
149
-          },
150
-        },
151
-      },
152
-      bindings: {},
153
-    },
154
-  },
155
-  pageStates: {
156
-    page1: {
157
-      id: 'page1',
158
-      selectedIds: [],
159
-      currentParentId: 'page1',
160
-      camera: {
161
-        point: [0, 0],
162
-        zoom: 1,
163
-      },
164
-    },
165
-  },
166
-}

+ 21
- 0
packages/tldraw/tsconfig.build.json View File

@@ -0,0 +1,21 @@
1
+{
2
+  "extends": "../../tsconfig.base.json",
3
+  "include": ["src"],
4
+  "exclude": [
5
+    "node_modules",
6
+    "**/*.test.tsx",
7
+    "**/*.test.ts",
8
+    "**/*.spec.tsx",
9
+    "**/*.spec.ts",
10
+    "src/test-utils",
11
+    "dist"
12
+  ],
13
+  "compilerOptions": {
14
+    "rootDir": "src",
15
+    "outDir": "./dist/types",
16
+    "baseUrl": "src",
17
+    "paths": {
18
+      "~*": ["./*"]
19
+    }
20
+  }
21
+}

+ 1
- 1
packages/tldraw/tsconfig.json View File

@@ -1,7 +1,7 @@
1 1
 {
2 2
   "extends": "../../tsconfig.base.json",
3 3
   "include": ["src"],
4
-  "exclude": ["node_modules", "**/*.test.ts", "dist"],
4
+  "exclude": ["node_modules", "dist"],
5 5
   "compilerOptions": {
6 6
     "rootDir": "src",
7 7
     "outDir": "./dist/types",

+ 1
- 0
setupTests.ts View File

@@ -0,0 +1 @@
1
+import '@testing-library/jest-dom/extend-expect'

+ 96
- 12
yarn.lock View File

@@ -9,7 +9,7 @@
9 9
   dependencies:
10 10
     "@babel/highlight" "^7.10.4"
11 11
 
12
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5":
12
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5":
13 13
   version "7.14.5"
14 14
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
15 15
   integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
@@ -376,7 +376,7 @@
376 376
   dependencies:
377 377
     regenerator-runtime "^0.13.4"
378 378
 
379
-"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10":
379
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.9.2":
380 380
   version "7.15.3"
381 381
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
382 382
   integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
@@ -2011,11 +2011,53 @@
2011 2011
   resolved "https://registry.yarnpkg.com/@stitches/react/-/react-0.2.5.tgz#ad15b4e59ac2a0679542ba002d41253244be7dab"
2012 2012
   integrity sha512-RDVn89kW0R/M4q4TdYvsJ7nckFndzRWGGFJnEHbIH9flOpahtNdPsrxVSsZSjFpxeVqCoOxKujlQjiyRrec1VA==
2013 2013
 
2014
+"@testing-library/dom@^8.0.0":
2015
+  version "8.1.0"
2016
+  resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.1.0.tgz#f8358b1883844ea569ba76b7e94582168df5370d"
2017
+  integrity sha512-kmW9alndr19qd6DABzQ978zKQ+J65gU2Rzkl8hriIetPnwpesRaK4//jEQyYh8fEALmGhomD/LBQqt+o+DL95Q==
2018
+  dependencies:
2019
+    "@babel/code-frame" "^7.10.4"
2020
+    "@babel/runtime" "^7.12.5"
2021
+    "@types/aria-query" "^4.2.0"
2022
+    aria-query "^4.2.2"
2023
+    chalk "^4.1.0"
2024
+    dom-accessibility-api "^0.5.6"
2025
+    lz-string "^1.4.4"
2026
+    pretty-format "^27.0.2"
2027
+
2028
+"@testing-library/jest-dom@^5.14.1":
2029
+  version "5.14.1"
2030
+  resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.14.1.tgz#8501e16f1e55a55d675fe73eecee32cdaddb9766"
2031
+  integrity sha512-dfB7HVIgTNCxH22M1+KU6viG5of2ldoA5ly8Ar8xkezKHKXjRvznCdbMbqjYGgO2xjRbwnR+rR8MLUIqF3kKbQ==
2032
+  dependencies:
2033
+    "@babel/runtime" "^7.9.2"
2034
+    "@types/testing-library__jest-dom" "^5.9.1"
2035
+    aria-query "^4.2.2"
2036
+    chalk "^3.0.0"
2037
+    css "^3.0.0"
2038
+    css.escape "^1.5.1"
2039
+    dom-accessibility-api "^0.5.6"
2040
+    lodash "^4.17.15"
2041
+    redent "^3.0.0"
2042
+
2043
+"@testing-library/react@^12.0.0":
2044
+  version "12.0.0"
2045
+  resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.0.0.tgz#9aeb2264521522ab9b68f519eaf15136148f164a"
2046
+  integrity sha512-sh3jhFgEshFyJ/0IxGltRhwZv2kFKfJ3fN1vTZ6hhMXzz9ZbbcTgmDYM4e+zJv+oiVKKEWZPyqPAh4MQBI65gA==
2047
+  dependencies:
2048
+    "@babel/runtime" "^7.12.5"
2049
+    "@testing-library/dom" "^8.0.0"
2050
+
2014 2051
 "@tootallnate/once@1":
2015 2052
   version "1.1.2"
2016 2053
   resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
2017 2054
   integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
2018 2055
 
2056
+"@types/aria-query@^4.2.0":
2057
+  version "4.2.2"
2058
+  resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
2059
+  integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==
2060
+
2019 2061
 "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14":
2020 2062
   version "7.1.15"
2021 2063
   resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.15.tgz#2ccfb1ad55a02c83f8e0ad327cbc332f55eb1024"
@@ -2083,6 +2125,14 @@
2083 2125
   dependencies:
2084 2126
     "@types/istanbul-lib-report" "*"
2085 2127
 
2128
+"@types/jest@*", "@types/jest@^27.0.1":
2129
+  version "27.0.1"
2130
+  resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.0.1.tgz#fafcc997da0135865311bb1215ba16dba6bdf4ca"
2131
+  integrity sha512-HTLpVXHrY69556ozYkcq47TtQJXpcWAWfkoqz+ZGz2JnmZhzlRjprCIyFnetSy8gpDWwTTGBcRVv1J1I1vBrHw==
2132
+  dependencies:
2133
+    jest-diff "^27.0.0"
2134
+    pretty-format "^27.0.0"
2135
+
2086 2136
 "@types/jest@^26.0.23", "@types/jest@^26.0.24":
2087 2137
   version "26.0.24"
2088 2138
   resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a"
@@ -2091,14 +2141,6 @@
2091 2141
     jest-diff "^26.0.0"
2092 2142
     pretty-format "^26.0.0"
2093 2143
 
2094
-"@types/jest@^27.0.1":
2095
-  version "27.0.1"
2096
-  resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.0.1.tgz#fafcc997da0135865311bb1215ba16dba6bdf4ca"
2097
-  integrity sha512-HTLpVXHrY69556ozYkcq47TtQJXpcWAWfkoqz+ZGz2JnmZhzlRjprCIyFnetSy8gpDWwTTGBcRVv1J1I1vBrHw==
2098
-  dependencies:
2099
-    jest-diff "^27.0.0"
2100
-    pretty-format "^27.0.0"
2101
-
2102 2144
 "@types/json-schema@^7.0.7":
2103 2145
   version "7.0.9"
2104 2146
   resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
@@ -2170,6 +2212,13 @@
2170 2212
   resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
2171 2213
   integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
2172 2214
 
2215
+"@types/testing-library__jest-dom@^5.9.1":
2216
+  version "5.14.1"
2217
+  resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.1.tgz#014162a5cee6571819d48e999980694e2f657c3c"
2218
+  integrity sha512-Gk9vaXfbzc5zCXI9eYE9BI5BNHEp4D3FWjgqBE/ePGYElLAP+KvxBcsdkwfIVvezs605oiyd/VrpiHe3Oeg+Aw==
2219
+  dependencies:
2220
+    "@types/jest" "*"
2221
+
2173 2222
 "@types/yargs-parser@*":
2174 2223
   version "20.2.1"
2175 2224
   resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129"
@@ -3139,6 +3188,14 @@ chalk@4.0.0:
3139 3188
     ansi-styles "^4.1.0"
3140 3189
     supports-color "^7.1.0"
3141 3190
 
3191
+chalk@^3.0.0:
3192
+  version "3.0.0"
3193
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
3194
+  integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
3195
+  dependencies:
3196
+    ansi-styles "^4.1.0"
3197
+    supports-color "^7.1.0"
3198
+
3142 3199
 chalk@^4.0.0, chalk@^4.1.0:
3143 3200
   version "4.1.2"
3144 3201
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -3624,11 +3681,20 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0:
3624 3681
     randombytes "^2.0.0"
3625 3682
     randomfill "^1.0.3"
3626 3683
 
3627
-css.escape@1.5.1:
3684
+css.escape@1.5.1, css.escape@^1.5.1:
3628 3685
   version "1.5.1"
3629 3686
   resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
3630 3687
   integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=
3631 3688
 
3689
+css@^3.0.0:
3690
+  version "3.0.0"
3691
+  resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d"
3692
+  integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==
3693
+  dependencies:
3694
+    inherits "^2.0.4"
3695
+    source-map "^0.6.1"
3696
+    source-map-resolve "^0.6.0"
3697
+
3632 3698
 cssnano-preset-simple@^3.0.0:
3633 3699
   version "3.0.0"
3634 3700
   resolved "https://registry.yarnpkg.com/cssnano-preset-simple/-/cssnano-preset-simple-3.0.0.tgz#e95d0012699ca2c741306e9a3b8eeb495a348dbe"
@@ -3930,6 +3996,11 @@ doctrine@^3.0.0:
3930 3996
   dependencies:
3931 3997
     esutils "^2.0.2"
3932 3998
 
3999
+dom-accessibility-api@^0.5.6:
4000
+  version "0.5.7"
4001
+  resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.7.tgz#8c2aa6325968f2933160a0b7dbb380893ddf3e7d"
4002
+  integrity sha512-ml3lJIq9YjUfM9TUnEPvEYWFSwivwIGBPKpewX7tii7fwCazA8yCioGdqQcNsItPpfFvSJ3VIdMQPj60LJhcQA==
4003
+
3933 4004
 domain-browser@4.19.0:
3934 4005
   version "4.19.0"
3935 4006
   resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.19.0.tgz#1093e17c0a17dbd521182fe90d49ac1370054af1"
@@ -6676,6 +6747,11 @@ lunr@^2.3.9:
6676 6747
   resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1"
6677 6748
   integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==
6678 6749
 
6750
+lz-string@^1.4.4:
6751
+  version "1.4.4"
6752
+  resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
6753
+  integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=
6754
+
6679 6755
 macos-release@^2.2.0:
6680 6756
   version "2.5.0"
6681 6757
   resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.0.tgz#067c2c88b5f3fb3c56a375b2ec93826220fa1ff2"
@@ -7950,7 +8026,7 @@ pretty-format@^26.0.0, pretty-format@^26.6.2:
7950 8026
     ansi-styles "^4.0.0"
7951 8027
     react-is "^17.0.1"
7952 8028
 
7953
-pretty-format@^27.0.0, pretty-format@^27.0.6:
8029
+pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.0.6:
7954 8030
   version "27.0.6"
7955 8031
   resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f"
7956 8032
   integrity sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==
@@ -8868,6 +8944,14 @@ source-map-resolve@^0.5.0:
8868 8944
     source-map-url "^0.4.0"
8869 8945
     urix "^0.1.0"
8870 8946
 
8947
+source-map-resolve@^0.6.0:
8948
+  version "0.6.0"
8949
+  resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2"
8950
+  integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==
8951
+  dependencies:
8952
+    atob "^2.1.2"
8953
+    decode-uri-component "^0.2.0"
8954
+
8871 8955
 source-map-support@^0.5.17, source-map-support@^0.5.6:
8872 8956
   version "0.5.19"
8873 8957
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"

Loading…
Cancel
Save