Taha/more constraints tests (#3863)

This PR adds a test each for 'contain' behaviour and mixed x and y
values.

1. Contain behaviour test: Lots of complicated maths that I put together
from hunting around in the editor code. I wasn't really sure how to
calculate the final state of the camera, so the test just checks that
the camera changes at all.
2. Mixed values test: different values for bounds and padding are tested
implicitly elsewhere in the file. This checks that different values can
be set for behaviour and origin.


### Change Type

<!--  Please select a 'Scope' label ️ -->

- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [x] `internal` — Does not affect user-facing stuff

<!--  Please select a 'Type' label ️ -->

- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [x] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know


### Test Plan


### Release Notes

- Adds more tests for the camera constraints API
This commit is contained in:
Taha 2024-06-04 08:59:14 +01:00 committed by GitHub
parent 19d051c188
commit 23cf8729bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -863,9 +863,49 @@ describe('Padding', () => {
}) })
describe('Contain behavior', () => { describe('Contain behavior', () => {
it.todo( it('Locks axis until the bounds are smaller than the padded viewport, then allows "inside" panning', () => {
'Locks axis until the bounds are bigger than the padded viewport, then allows "inside" panning' const boundsW = 1600
) const boundsH = 900
const padding = 100
editor.setCameraOptions({
...DEFAULT_CAMERA_OPTIONS,
constraints: {
...DEFAULT_CONSTRAINTS,
bounds: { x: 0, y: 0, w: boundsW, h: boundsH },
behavior: 'contain',
origin: { x: 0.5, y: 0.5 },
padding: { x: padding, y: padding },
initialZoom: 'fit-max',
baseZoom: 'fit-max',
},
})
editor.setCamera(editor.getCamera(), { reset: true })
const baseZoom = 700 / 900
const x = padding / baseZoom - boundsW + (boundsW - padding * 2) / baseZoom - padding
const y = padding / baseZoom - boundsH + (boundsH - padding * 2) / baseZoom
expect(editor.getCamera()).toCloselyMatchObject({ x, y, z: baseZoom }, 5)
// We should not be able to pan
editor.pan(new Vec(-10000, -10000))
expect(editor.getCamera()).toCloselyMatchObject({ x, y, z: baseZoom }, 5)
// But we can zoom
editor.zoomOut()
const newZoom = 0.5 * baseZoom
const newX =
padding / newZoom - boundsW + (boundsW - padding * 2) / newZoom - boundsW / 2 - padding * 2
const newY = padding / newZoom - boundsH + (boundsH - padding * 2) / newZoom - boundsH / 2
const newCamera = { x: newX, y: newY, z: newZoom }
expect(editor.getCamera()).toCloselyMatchObject(newCamera, 5)
// Panning is still locked
editor.pan(new Vec(-10000, -10000))
expect(editor.getCamera()).toCloselyMatchObject(newCamera, 5)
// Zooming to within bounds will allow us to pan
editor.zoomIn().zoomIn()
const camera = editor.getCamera()
editor.pan(new Vec(-10000, -10000))
expect(editor.getCamera()).not.toMatchObject(camera)
})
}) })
describe('Inside behavior', () => { describe('Inside behavior', () => {
@ -886,12 +926,12 @@ describe('Inside behavior', () => {
expect(editor.getCamera()).toMatchObject({ x: 0, y: 0, z: 1 }) expect(editor.getCamera()).toMatchObject({ x: 0, y: 0, z: 1 })
// panning far outside of the bounds // panning far outside of the bounds
editor.pan(new Vec(-10000, -10000)) editor.pan(new Vec(-10000, -10000))
jest.advanceTimersByTime(300)
// should be clamped to the bounds + padding // should be clamped to the bounds + padding
expect(editor.getCamera()).toMatchObject({ x: -100, y: -100, z: 1 }) expect(editor.getCamera()).toMatchObject({ x: -100, y: -100, z: 1 })
// panning to the opposite direction, far outside of the bounds // panning to the opposite direction, far outside of the bounds
editor.pan(new Vec(10000, 10000)) editor.pan(new Vec(10000, 10000))
jest.advanceTimersByTime(300)
// should be clamped to the bounds + padding // should be clamped to the bounds + padding
expect(editor.getCamera()).toMatchObject({ x: 100, y: 100, z: 1 }) expect(editor.getCamera()).toMatchObject({ x: 100, y: 100, z: 1 })
}) })
@ -915,19 +955,59 @@ describe('Outside behavior', () => {
expect(editor.getCamera()).toMatchObject({ x: 0, y: 0, z: 1 }) expect(editor.getCamera()).toMatchObject({ x: 0, y: 0, z: 1 })
// panning far outside of the bounds // panning far outside of the bounds
editor.pan(new Vec(-10000, -10000)) editor.pan(new Vec(-10000, -10000))
jest.advanceTimersByTime(300)
// should be clamped so that the far edge of the bounds is adjacent to the viewport + padding // should be clamped so that the far edge of the bounds is adjacent to the viewport + padding
expect(editor.getCamera()).toMatchObject({ x: -bounds.w + 100, y: -bounds.h + 100, z: 1 }) expect(editor.getCamera()).toMatchObject({ x: -bounds.w + 100, y: -bounds.h + 100, z: 1 })
// panning to the opposite direction, far outside of the bounds // panning to the opposite direction, far outside of the bounds
editor.pan(new Vec(10000, 10000)) editor.pan(new Vec(10000, 10000))
jest.advanceTimersByTime(300)
// should be clamped so that the far edge of the bounds is adjacent to the viewport + padding // should be clamped so that the far edge of the bounds is adjacent to the viewport + padding
expect(editor.getCamera()).toMatchObject({ x: bounds.w - 100, y: bounds.h - 100, z: 1 }) expect(editor.getCamera()).toMatchObject({ x: bounds.w - 100, y: bounds.h - 100, z: 1 })
}) })
}) })
describe('Allows mixed values for x and y', () => { describe('Allows mixed values for x and y', () => {
it.todo('Allows different values to be set for x and y axes') it('Allows different values to be set for x and y behaviour', () => {
editor.setCameraOptions({
...DEFAULT_CAMERA_OPTIONS,
constraints: {
...DEFAULT_CONSTRAINTS,
behavior: { x: 'inside', y: 'outside' },
initialZoom: 'fit-x',
baseZoom: 'fit-x',
},
})
editor.setCamera(editor.getCamera(), { reset: true })
const camera = editor.getCamera()
editor.pan(new Vec(-100, 0))
// no change when panning on x axis because it's set to inside
expect(editor.getCamera()).toMatchObject(camera)
editor.pan(new Vec(0, -100))
// change when panning on y axis because it's set to outside
expect(editor.getCamera()).toMatchObject({ ...camera, y: camera.y - 100 / camera.z })
editor.pan(new Vec(0, -1000000))
// clamped to the bounds
expect(editor.getCamera()).toMatchObject({ ...camera, y: -800 })
})
it('Allows different values to be set for x and y origin', () => {
editor.setCameraOptions({
...DEFAULT_CAMERA_OPTIONS,
constraints: {
...DEFAULT_CONSTRAINTS,
behavior: 'contain',
origin: { x: 0, y: 1 },
initialZoom: 'default',
},
})
editor.setCamera(editor.getCamera(), { reset: true })
const camera = editor.getCamera()
editor.zoomOut()
// zooms out and keeps the bounds in the bottom left of the viewport, so no change on x axis
expect(editor.getCamera()).toMatchObject({ x: 0, y: camera.y + 900, z: 0.5 })
})
}) })
test('it animated towards the constrained viewport rather than the given viewport', () => { test('it animated towards the constrained viewport rather than the given viewport', () => {