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>
90 lines
2.9 KiB
TypeScript
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
|
|
})
|
|
})
|