- Enforce explicit-any and TypeScript suppression bans in tests - Remove remaining broad any casts from engine and e2e coverage - Split markdown ambient declarations from typed browser globals
208 lines
6 KiB
TypeScript
208 lines
6 KiB
TypeScript
import { describe, test, expect } from 'bun:test'
|
|
|
|
import { TextEditor, type SceneNode } from '@open-pencil/core'
|
|
|
|
import type { CanvasKit } from 'canvaskit-wasm'
|
|
|
|
const mockCk = {} as CanvasKit
|
|
|
|
function createEditor(text = 'Hello World') {
|
|
const editor = new TextEditor(mockCk)
|
|
const node = { id: 'test-node', text } as SceneNode
|
|
editor.start(node)
|
|
return { editor, node }
|
|
}
|
|
|
|
describe('TextEditor', () => {
|
|
test('start initializes state', () => {
|
|
const { editor } = createEditor()
|
|
expect(editor.isActive).toBe(true)
|
|
expect(editor.nodeId).toBe('test-node')
|
|
expect(editor.state?.text).toBe('Hello World')
|
|
expect(editor.state?.cursor).toBe(11)
|
|
})
|
|
|
|
test('stop returns result and clears state', () => {
|
|
const { editor } = createEditor()
|
|
const result = editor.stop()
|
|
expect(result?.nodeId).toBe('test-node')
|
|
expect(result?.text).toBe('Hello World')
|
|
expect(editor.isActive).toBe(false)
|
|
expect(editor.nodeId).toBeNull()
|
|
})
|
|
|
|
test('stop on inactive returns null', () => {
|
|
const editor = new TextEditor(mockCk)
|
|
expect(editor.stop()).toBeNull()
|
|
})
|
|
|
|
test('insert at end', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.insert('!', node)
|
|
expect(editor.state?.text).toBe('Hello World!')
|
|
expect(editor.state?.cursor).toBe(12)
|
|
})
|
|
|
|
test('insert at cursor position', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.state!.cursor = 5
|
|
editor.insert(' Beautiful', node)
|
|
expect(editor.state?.text).toBe('Hello Beautiful World')
|
|
})
|
|
|
|
test('insert replaces selection', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.state!.selectionAnchor = 0
|
|
editor.state!.cursor = 5
|
|
editor.insert('Goodbye', node)
|
|
expect(editor.state?.text).toBe('Goodbye World')
|
|
expect(editor.state?.cursor).toBe(7)
|
|
expect(editor.state?.selectionAnchor).toBeNull()
|
|
})
|
|
|
|
test('backspace deletes char before cursor', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.backspace(node)
|
|
expect(editor.state?.text).toBe('Hello Worl')
|
|
expect(editor.state?.cursor).toBe(10)
|
|
})
|
|
|
|
test('backspace at start does nothing', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.state!.cursor = 0
|
|
editor.backspace(node)
|
|
expect(editor.state?.text).toBe('Hello World')
|
|
})
|
|
|
|
test('backspace deletes selection', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.state!.selectionAnchor = 6
|
|
editor.state!.cursor = 11
|
|
editor.backspace(node)
|
|
expect(editor.state?.text).toBe('Hello ')
|
|
expect(editor.state?.cursor).toBe(6)
|
|
})
|
|
|
|
test('delete removes char after cursor', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.state!.cursor = 0
|
|
editor.delete(node)
|
|
expect(editor.state?.text).toBe('ello World')
|
|
expect(editor.state?.cursor).toBe(0)
|
|
})
|
|
|
|
test('delete at end does nothing', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.delete(node)
|
|
expect(editor.state?.text).toBe('Hello World')
|
|
})
|
|
|
|
test('delete removes selection', () => {
|
|
const { editor, node } = createEditor()
|
|
editor.state!.selectionAnchor = 0
|
|
editor.state!.cursor = 5
|
|
editor.delete(node)
|
|
expect(editor.state?.text).toBe(' World')
|
|
})
|
|
|
|
test('moveLeft', () => {
|
|
const { editor } = createEditor()
|
|
editor.moveLeft()
|
|
expect(editor.state?.cursor).toBe(10)
|
|
})
|
|
|
|
test('moveRight at end stays', () => {
|
|
const { editor } = createEditor()
|
|
editor.moveRight()
|
|
expect(editor.state?.cursor).toBe(11)
|
|
})
|
|
|
|
test('moveLeft collapses selection to start', () => {
|
|
const { editor } = createEditor()
|
|
editor.state!.selectionAnchor = 3
|
|
editor.state!.cursor = 8
|
|
editor.moveLeft()
|
|
expect(editor.state?.cursor).toBe(3)
|
|
expect(editor.state?.selectionAnchor).toBeNull()
|
|
})
|
|
|
|
test('moveRight collapses selection to end', () => {
|
|
const { editor } = createEditor()
|
|
editor.state!.selectionAnchor = 3
|
|
editor.state!.cursor = 8
|
|
editor.moveRight()
|
|
expect(editor.state?.cursor).toBe(8)
|
|
expect(editor.state?.selectionAnchor).toBeNull()
|
|
})
|
|
|
|
test('selectAll', () => {
|
|
const { editor } = createEditor()
|
|
editor.selectAll()
|
|
expect(editor.state?.selectionAnchor).toBe(0)
|
|
expect(editor.state?.cursor).toBe(11)
|
|
})
|
|
|
|
test('hasSelection', () => {
|
|
const { editor } = createEditor()
|
|
expect(editor.hasSelection()).toBe(false)
|
|
editor.state!.selectionAnchor = 0
|
|
expect(editor.hasSelection()).toBe(true)
|
|
})
|
|
|
|
test('hasSelection false when anchor equals cursor', () => {
|
|
const { editor } = createEditor()
|
|
editor.state!.selectionAnchor = editor.state!.cursor
|
|
expect(editor.hasSelection()).toBe(false)
|
|
})
|
|
|
|
test('getSelectionRange', () => {
|
|
const { editor } = createEditor()
|
|
expect(editor.getSelectionRange()).toBeNull()
|
|
editor.state!.selectionAnchor = 8
|
|
editor.state!.cursor = 3
|
|
expect(editor.getSelectionRange()).toEqual([3, 8])
|
|
})
|
|
|
|
test('getSelectedText', () => {
|
|
const { editor } = createEditor()
|
|
editor.state!.selectionAnchor = 0
|
|
editor.state!.cursor = 5
|
|
expect(editor.getSelectedText()).toBe('Hello')
|
|
})
|
|
|
|
test('selectWord', () => {
|
|
const { editor } = createEditor()
|
|
editor.selectWord(2)
|
|
expect(editor.state?.selectionAnchor).toBe(0)
|
|
expect(editor.state?.cursor).toBe(5)
|
|
})
|
|
|
|
test('selectWord on second word', () => {
|
|
const { editor } = createEditor()
|
|
editor.selectWord(8)
|
|
expect(editor.state?.selectionAnchor).toBe(6)
|
|
expect(editor.state?.cursor).toBe(11)
|
|
})
|
|
|
|
test('moveWordLeft', () => {
|
|
const { editor } = createEditor()
|
|
editor.moveWordLeft()
|
|
expect(editor.state?.cursor).toBe(6)
|
|
})
|
|
|
|
test('moveWordRight from start', () => {
|
|
const { editor } = createEditor()
|
|
editor.state!.cursor = 0
|
|
editor.moveWordRight()
|
|
expect(editor.state?.cursor).toBe(6)
|
|
})
|
|
|
|
test('moveLeft with extend creates selection', () => {
|
|
const { editor } = createEditor()
|
|
editor.state!.cursor = 5
|
|
editor.moveLeft(true)
|
|
expect(editor.state?.selectionAnchor).toBe(5)
|
|
expect(editor.state?.cursor).toBe(4)
|
|
})
|
|
})
|