Files
opsxshell/test/utils/safeTerminalFit.test.ts
T
Logan.LiandCursor 08696896f9 feat: harden local shell, SFTP, and desktop session reliability
Finder-launched terminals now inherit a login PATH so tools like ollama resolve, destructive SFTP/editor actions require confirmation, and terminal search plus window dragging work again. SSH forwards and RDP sessions keep listeners and survive reconnect without FastPath crashes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-16 16:08:11 +08:00

90 lines
2.9 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import type { FitAddon } from '@xterm/addon-fit'
import type { Terminal } from '@xterm/xterm'
import {
isTerminalDisposed,
markTerminalDisposed,
safeTerminalDispose,
safeTerminalFit,
safeTerminalWrite,
} from '../../src/utils/safeTerminalFit'
describe('safeTerminalFit', () => {
it('returns false without an addon', () => {
expect(safeTerminalFit(null)).toBe(false)
})
it('skips fit when terminal element is detached', () => {
const fit = vi.fn()
const term = {
element: { isConnected: false, parentElement: { clientWidth: 100, clientHeight: 40 } },
} as unknown as Terminal
expect(safeTerminalFit({ fit } as unknown as FitAddon, term)).toBe(false)
expect(fit).not.toHaveBeenCalled()
})
it('skips fit when host has zero size', () => {
const fit = vi.fn()
const term = {
element: { isConnected: true, parentElement: { clientWidth: 0, clientHeight: 0 } },
} as unknown as Terminal
expect(safeTerminalFit({ fit } as unknown as FitAddon, term)).toBe(false)
expect(fit).not.toHaveBeenCalled()
})
it('swallows renderer dimension races', () => {
const fit = vi.fn(() => {
throw new TypeError("undefined is not an object (evaluating 'this._renderer.value.dimensions')")
})
const term = {
element: { isConnected: true, parentElement: { clientWidth: 80, clientHeight: 40 } },
} as unknown as Terminal
expect(safeTerminalFit({ fit } as unknown as FitAddon, term)).toBe(false)
expect(fit).toHaveBeenCalledOnce()
})
it('returns true on successful fit', () => {
const fit = vi.fn()
const term = {
element: { isConnected: true, parentElement: { clientWidth: 80, clientHeight: 40 } },
} as unknown as Terminal
expect(safeTerminalFit({ fit } as unknown as FitAddon, term)).toBe(true)
})
it('blocks write after mark disposed', () => {
const write = vi.fn()
const term = { write } as unknown as Terminal
markTerminalDisposed(term)
expect(isTerminalDisposed(term)).toBe(true)
safeTerminalWrite(term, 'x')
expect(write).not.toHaveBeenCalled()
})
it('marks disposed and removes element before dispose', () => {
const raf: FrameRequestCallback[] = []
const original = globalThis.requestAnimationFrame
globalThis.requestAnimationFrame = ((cb: FrameRequestCallback) => {
raf.push(cb)
return raf.length
}) as typeof requestAnimationFrame
const dispose = vi.fn()
const remove = vi.fn()
const term = {
dispose,
element: { remove },
} as unknown as Terminal
safeTerminalDispose(term)
expect(isTerminalDisposed(term)).toBe(true)
expect(remove).toHaveBeenCalledOnce()
expect(dispose).not.toHaveBeenCalled()
// Drain double-rAF queue used by safeTerminalDispose.
while (raf.length) {
const next = raf.shift()!
next(0)
}
expect(dispose).toHaveBeenCalledOnce()
globalThis.requestAnimationFrame = original
})
})