openpencil/tests/engine/text/style-runs.test.ts
Danila Poyarkov 9e4d7bee5d chore(lint): fix unused test code
- Remove stale imports and unused locals from split engine and e2e tests
- Drop the targeted no-unused-vars test allowances
- Keep check and affected test suites warning-free
2026-05-06 02:53:19 +03:00

158 lines
5.4 KiB
TypeScript

import { describe, expect, test } from 'bun:test'
import {
adjustRunsForDelete,
adjustRunsForInsert,
applyStyleToRange,
getStyleAt,
removeStyleFromRange,
selectionHasStyle,
toggleBoldInRange,
toggleDecorationInRange,
toggleItalicInRange,
type StyleRun
} from '@open-pencil/core'
describe('getStyleAt', () => {
test('returns style within run', () => {
const runs: StyleRun[] = [{ start: 2, length: 3, style: { fontWeight: 700 } }]
expect(getStyleAt(runs, 3)).toEqual({ fontWeight: 700 })
})
test('returns empty object outside runs', () => {
const runs: StyleRun[] = [{ start: 5, length: 2, style: { fontWeight: 700 } }]
expect(getStyleAt(runs, 0)).toEqual({})
})
})
describe('applyStyleToRange', () => {
test('applies bold to range', () => {
const runs = applyStyleToRange([], 2, 5, { fontWeight: 700 }, 10)
expect(runs).toHaveLength(1)
expect(runs[0].start).toBe(2)
expect(runs[0].length).toBe(3)
expect(runs[0].style.fontWeight).toBe(700)
})
test('merges with existing style', () => {
const existing: StyleRun[] = [{ start: 0, length: 5, style: { fontWeight: 700 } }]
const runs = applyStyleToRange(existing, 2, 4, { italic: true }, 10)
const style = getStyleAt(runs, 3)
expect(style.fontWeight).toBe(700)
expect(style.italic).toBe(true)
})
})
describe('removeStyleFromRange', () => {
test('removes keys from range', () => {
const existing: StyleRun[] = [{ start: 0, length: 5, style: { fontWeight: 700, italic: true } }]
const runs = removeStyleFromRange(existing, 0, 5, ['fontWeight'], 10)
const style = getStyleAt(runs, 2)
expect(style.fontWeight).toBeUndefined()
expect(style.italic).toBe(true)
})
})
describe('selectionHasStyle', () => {
test('all chars have style', () => {
const runs: StyleRun[] = [{ start: 0, length: 5, style: { fontWeight: 700 } }]
expect(selectionHasStyle(runs, 0, 5, 'fontWeight', 700)).toBe(true)
})
test('some chars missing', () => {
const runs: StyleRun[] = [{ start: 0, length: 3, style: { fontWeight: 700 } }]
expect(selectionHasStyle(runs, 0, 5, 'fontWeight', 700)).toBe(false)
})
})
describe('adjustRunsForInsert', () => {
test('insert before run shifts start', () => {
const runs: StyleRun[] = [{ start: 5, length: 3, style: { fontWeight: 700 } }]
const adjusted = adjustRunsForInsert(runs, 2, 4)
expect(adjusted[0].start).toBe(9)
expect(adjusted[0].length).toBe(3)
})
test('insert inside run extends length', () => {
const runs: StyleRun[] = [{ start: 2, length: 6, style: { fontWeight: 700 } }]
const adjusted = adjustRunsForInsert(runs, 4, 3)
expect(adjusted[0].start).toBe(2)
expect(adjusted[0].length).toBe(9)
})
test('insert after run leaves it unchanged', () => {
const runs: StyleRun[] = [{ start: 0, length: 3, style: { fontWeight: 700 } }]
const adjusted = adjustRunsForInsert(runs, 10, 5)
expect(adjusted[0]).toEqual({ start: 0, length: 3, style: { fontWeight: 700 } })
})
})
describe('adjustRunsForDelete', () => {
test('delete before run shifts start', () => {
const runs: StyleRun[] = [{ start: 10, length: 5, style: { fontWeight: 700 } }]
const adjusted = adjustRunsForDelete(runs, 2, 3)
expect(adjusted[0].start).toBe(7)
expect(adjusted[0].length).toBe(5)
})
test('delete inside run shrinks length', () => {
const runs: StyleRun[] = [{ start: 0, length: 10, style: { fontWeight: 700 } }]
const adjusted = adjustRunsForDelete(runs, 3, 4)
expect(adjusted[0].length).toBe(6)
})
test('delete entire run removes it', () => {
const runs: StyleRun[] = [{ start: 2, length: 3, style: { fontWeight: 700 } }]
const adjusted = adjustRunsForDelete(runs, 2, 3)
expect(adjusted).toHaveLength(0)
})
test('delete after run leaves it unchanged', () => {
const runs: StyleRun[] = [{ start: 0, length: 3, style: { fontWeight: 700 } }]
const adjusted = adjustRunsForDelete(runs, 5, 2)
expect(adjusted[0]).toEqual({ start: 0, length: 3, style: { fontWeight: 700 } })
})
})
describe('toggleBoldInRange', () => {
test('non-bold to bold', () => {
const { runs, newWeight } = toggleBoldInRange([], 0, 5, 400, 10)
expect(newWeight).toBe(700)
expect(runs).toHaveLength(1)
expect(runs[0].style.fontWeight).toBe(700)
})
test('bold to non-bold', () => {
const existing: StyleRun[] = [{ start: 0, length: 5, style: { fontWeight: 700 } }]
const { newWeight } = toggleBoldInRange(existing, 0, 5, 400, 10)
expect(newWeight).toBe(400)
})
})
describe('toggleItalicInRange', () => {
test('toggle on', () => {
const { runs, newItalic } = toggleItalicInRange([], 0, 5, false, 10)
expect(newItalic).toBe(true)
expect(runs[0].style.italic).toBe(true)
})
test('toggle off', () => {
const existing: StyleRun[] = [{ start: 0, length: 5, style: { italic: true } }]
const { newItalic } = toggleItalicInRange(existing, 0, 5, false, 10)
expect(newItalic).toBe(false)
})
})
describe('toggleDecorationInRange', () => {
test('add underline', () => {
const { newDeco } = toggleDecorationInRange([], 0, 5, 'UNDERLINE', 'NONE', 10)
expect(newDeco).toBe('UNDERLINE')
})
test('remove underline', () => {
const existing: StyleRun[] = [{ start: 0, length: 5, style: { textDecoration: 'UNDERLINE' } }]
const { newDeco } = toggleDecorationInRange(existing, 0, 5, 'UNDERLINE', 'NONE', 10)
expect(newDeco).toBe('NONE')
})
})