76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import type { Editor } from 'tldraw'
|
|
import { installTldrawTextMeasurementGuard } from './tldrawTextMeasurementGuard'
|
|
|
|
type TextMeasure = Pick<Editor, 'textMeasure'>['textMeasure']
|
|
type MeasureElementTextNodeSpans = TextMeasure['measureElementTextNodeSpans']
|
|
|
|
function textMeasureHost(measureElementTextNodeSpans: MeasureElementTextNodeSpans) {
|
|
return {
|
|
textMeasure: {
|
|
measureElementTextNodeSpans,
|
|
},
|
|
}
|
|
}
|
|
|
|
function elementWithText(text: string): HTMLElement {
|
|
const element = document.createElement('div')
|
|
element.textContent = text
|
|
vi.spyOn(element, 'getBoundingClientRect').mockReturnValue(DOMRect.fromRect({
|
|
height: 24,
|
|
width: 88,
|
|
}))
|
|
return element
|
|
}
|
|
|
|
describe('tldraw text measurement guard', () => {
|
|
it('falls back to a whole-text span when Edge returns no range rect', () => {
|
|
const originalMeasure = vi.fn(() => {
|
|
throw new TypeError("Cannot read properties of undefined (reading 'top')")
|
|
})
|
|
const host = textMeasureHost(originalMeasure)
|
|
const cleanup = installTldrawTextMeasurementGuard(host)
|
|
|
|
expect(host.textMeasure.measureElementTextNodeSpans(elementWithText('Label'))).toEqual({
|
|
didTruncate: false,
|
|
spans: [{
|
|
box: { h: 24, w: 88, x: 0, y: 0 },
|
|
text: 'Label',
|
|
}],
|
|
})
|
|
|
|
cleanup()
|
|
expect(() => host.textMeasure.measureElementTextNodeSpans(elementWithText('Label'))).toThrow('top')
|
|
})
|
|
|
|
it('preserves first-line truncation for fallback measurements', () => {
|
|
const originalMeasure = vi.fn(() => {
|
|
throw new TypeError("Cannot read properties of undefined (reading 'top')")
|
|
})
|
|
const host = textMeasureHost(originalMeasure)
|
|
installTldrawTextMeasurementGuard(host)
|
|
|
|
expect(host.textMeasure.measureElementTextNodeSpans(
|
|
elementWithText('Title\nOverflow'),
|
|
{ shouldTruncateToFirstLine: true },
|
|
)).toEqual({
|
|
didTruncate: true,
|
|
spans: [{
|
|
box: { h: 24, w: 88, x: 0, y: 0 },
|
|
text: 'Title',
|
|
}],
|
|
})
|
|
})
|
|
|
|
it('rethrows unrelated measurement failures', () => {
|
|
const originalMeasure = vi.fn(() => {
|
|
throw new RangeError('bad measurement state')
|
|
})
|
|
const host = textMeasureHost(originalMeasure)
|
|
installTldrawTextMeasurementGuard(host)
|
|
|
|
expect(() => host.textMeasure.measureElementTextNodeSpans(elementWithText('Label')))
|
|
.toThrow('bad measurement state')
|
|
})
|
|
})
|