pinned / client /editing /pinNotes.test.ts
igorktech's picture
Pinned demo: two recorded boards, agent off
6f91ce5 verified
Raw History Blame Contribute Delete
4.24 kB
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { react } from 'tldraw'
import { defaultPaperCardProps } from '../../shared/shapes.ts'
import { changes, watchBoard } from '../pinboard/changes.ts'
import { pinOffset } from '../widgets/notes.ts'
import { fakeEditor } from './fixtures/fakeEditor.ts'
import { cardUnder, dropNoteAt, gap, placeNote, registerPinNotes, UNPIN_GAP } from './pinNotes.ts'
import { boardToast } from './toast.ts'
// Two cards as getShapePageBounds gives them: Liu 2022's 172 × 70 card, drawn centred on a 48 px
// node at (100, 100); Tirosh 2016 sits 400 px to the right.
const liu = { id: 'shape:paper-liu', box: { x: 38, y: 89, w: 172, h: 70 } }
const tirosh = { id: 'shape:paper-tirosh', box: { x: 438, y: 89, w: 172, h: 70 } }
const cards = [liu, tirosh]
const note = (x: number, y: number) => ({ x, y, w: 160, h: 160 })
test('a point inside a card’s drawn box finds that card, even outside its node', () => {
assert.equal(cardUnder({ x: 205, y: 95 }, cards)?.id, liu.id) // right of the node, still on the card
assert.equal(cardUnder({ x: 215, y: 95 }, cards), null) // just past the card's right edge
assert.equal(cardUnder({ x: 124, y: 160 }, cards), null) // just below it
// overlapping cards: the one whose centre is nearest
const close = { id: 'shape:paper-close', box: { x: 138, y: 89, w: 172, h: 70 } }
assert.equal(cardUnder({ x: 190, y: 124 }, [liu, close])?.id, close.id)
})
test('a note whose centre is on a card pins to it; one beside it stays as it is', () => {
assert.deepEqual(placeNote(note(50, 40), null, cards), { pin: liu.id }) // centre (130, 120)
assert.deepEqual(placeNote(note(250, 40), null, cards), null)
// a pinned note dropped on another paper moves to it
assert.deepEqual(placeNote(note(450, 40), liu.id, cards), { pin: tirosh.id })
// dropped on its own paper again, it's put back beside it
assert.deepEqual(placeNote(note(50, 40), liu.id, cards), { pin: liu.id })
})
test('a pinned note comes loose only once it’s more than a card’s width from its paper', () => {
assert.equal(UNPIN_GAP, 172)
// the card's right edge is at x = 210: a gap of 172 keeps the pin, 173 doesn't
assert.deepEqual(placeNote(note(210 + 172, 100), liu.id, [liu]), null)
assert.deepEqual(placeNote(note(210 + 173, 100), liu.id, [liu]), { unpin: true })
// below and to the left count too
assert.deepEqual(placeNote(note(-400, 400), liu.id, [liu]), { unpin: true })
// a free note far from everything stays free; a paper that's gone (hidden) keeps its pin
assert.deepEqual(placeNote(note(1000, 1000), null, cards), null)
assert.deepEqual(placeNote(note(1000, 1000), 'shape:paper-gone', cards), null)
})
test('gap between boxes is 0 when they touch and diagonal past a corner', () => {
assert.equal(gap({ x: 0, y: 0, w: 10, h: 10 }, { x: 10, y: 0, w: 10, h: 10 }), 0)
assert.equal(gap({ x: 0, y: 0, w: 10, h: 10 }, { x: 13, y: 14, w: 10, h: 10 }), 5)
})
test('the toolbar’s Note dropped on a paper is pinned once, beside the card, with one toast', () => {
const props = defaultPaperCardProps('pmid:2', { authors: ['Yang Liu'], year: 2022, w: 48, h: 48 })
const { editor, shapes, bindings, writes } = fakeEditor([{ id: liu.id, type: 'paper-card', x: 100, y: 100, props }])
const toasts: string[] = []
const stop = react('board toasts', () => {
const shown = boardToast.get()
if (shown) toasts.push(shown.text)
})
const cleanups = [watchBoard(editor, 'b_drop'), registerPinNotes(editor)]
try {
dropNoteAt(editor, { x: 124, y: 124 }) // the middle of Liu 2022's node
assert.deepEqual(
writes.filter((w) => w.includes('binding')),
['create binding note-pin']
)
const [pin] = [...bindings.values()]
const { dx, dy } = pinOffset(props, 0)
assert.equal(pin.toId, liu.id)
assert.deepEqual(pin.props, { dx, dy })
const note = shapes.get(pin.fromId)!
assert.deepEqual([note.x, note.y], [100 + dx, 100 + dy])
assert.deepEqual(toasts, ['Note pinned to Liu 2022. It moves with the paper.'])
assert.deepEqual(
changes.get('b_drop').entries.map((e) => e.change),
[{ type: 'note_added', noteId: note.id, text: '', paperId: 'pmid:2' }]
)
} finally {
stop()
cleanups.forEach((cleanup) => cleanup())
}
})