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>
127 lines
4.3 KiB
TypeScript
127 lines
4.3 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { expandSnippetVariables } from '../../src/utils/snippetVariables'
|
|
import { applyKeywordHighlights, DEFAULT_KEYWORD_HIGHLIGHT_RULES } from '../../src/utils/keywordHighlight'
|
|
import {
|
|
StreamingKeywordHighlight,
|
|
trailingIncompleteEscape,
|
|
} from '../../src/utils/streamingKeywordHighlight'
|
|
import { localShellEnterKey, normalizeTerminalInject } from '../../src/utils/platformShells'
|
|
|
|
describe('expandSnippetVariables', () => {
|
|
it('replaces known placeholders', () => {
|
|
const out = expandSnippetVariables('ssh {{username}}@{{host}}:{{port}}', {
|
|
username: 'root',
|
|
host: '10.0.0.1',
|
|
port: 22,
|
|
})
|
|
expect(out).toBe('ssh root@10.0.0.1:22')
|
|
})
|
|
|
|
it('uses default when missing', () => {
|
|
const out = expandSnippetVariables('cd {{path:/tmp}}', {})
|
|
expect(out).toBe('cd /tmp')
|
|
})
|
|
|
|
it('keeps unknown placeholders without default', () => {
|
|
const out = expandSnippetVariables('echo {{unknown}}', {})
|
|
expect(out).toBe('echo {{unknown}}')
|
|
})
|
|
})
|
|
|
|
describe('applyKeywordHighlights', () => {
|
|
it('highlights error keywords', () => {
|
|
const out = applyKeywordHighlights('FATAL error happened', DEFAULT_KEYWORD_HIGHLIGHT_RULES)
|
|
expect(out).toContain('\x1b[')
|
|
expect(out).toContain('FATAL')
|
|
})
|
|
|
|
it('returns original when disabled rules only', () => {
|
|
const rules = DEFAULT_KEYWORD_HIGHLIGHT_RULES.map((r) => ({ ...r, enabled: false }))
|
|
const text = 'no highlight'
|
|
expect(applyKeywordHighlights(text, rules)).toBe(text)
|
|
})
|
|
|
|
it('does not inject SGR inside OSC window-title sequences (SSH title leak)', () => {
|
|
const rules = [
|
|
{
|
|
id: 'ipv4',
|
|
label: 'IPv4',
|
|
pattern: '\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b',
|
|
isRegex: true,
|
|
color: '#8be9fd',
|
|
enabled: true,
|
|
},
|
|
]
|
|
const osc = '\x1b]0;ssh root@165.154.155.48\x07'
|
|
const out = applyKeywordHighlights(`${osc}Welcome to Ubuntu`, rules)
|
|
expect(out).toContain(osc)
|
|
expect(out).not.toMatch(/\x1b\]0;.*\x1b\[38/) // eslint-disable-line no-control-regex -- OSC must stay intact
|
|
expect(out).toContain('Welcome to Ubuntu')
|
|
})
|
|
|
|
it('still highlights IPs in plain text when the ipv4 rule is enabled', () => {
|
|
const rules = [
|
|
{
|
|
id: 'ipv4',
|
|
label: 'IPv4',
|
|
pattern: '\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b',
|
|
isRegex: true,
|
|
color: '#8be9fd',
|
|
enabled: true,
|
|
},
|
|
]
|
|
const out = applyKeywordHighlights('peer 10.0.0.1 online', rules)
|
|
expect(out).toContain('\x1b[38;2;')
|
|
expect(out).toContain('10.0.0.1')
|
|
expect(out).toContain('\x1b[39m')
|
|
})
|
|
|
|
it('leaves existing CSI color sequences intact', () => {
|
|
const colored = '\x1b[01;32mroot\x1b[00m@host'
|
|
const out = applyKeywordHighlights(colored, DEFAULT_KEYWORD_HIGHLIGHT_RULES)
|
|
expect(out).toContain('\x1b[01;32mroot\x1b[00m')
|
|
})
|
|
})
|
|
|
|
describe('StreamingKeywordHighlight', () => {
|
|
const ipv4Rules = [
|
|
{
|
|
id: 'ipv4',
|
|
label: 'IPv4',
|
|
pattern: '\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b',
|
|
isRegex: true,
|
|
color: '#8be9fd',
|
|
enabled: true,
|
|
},
|
|
]
|
|
|
|
it('holds incomplete OSC across chunks', () => {
|
|
expect(trailingIncompleteEscape('\x1b]0;ssh root@1.2.3.4')).toBe('\x1b]0;ssh root@1.2.3.4')
|
|
const stream = new StreamingKeywordHighlight()
|
|
expect(stream.push('\x1b]0;ssh root@1.2.3.4', ipv4Rules)).toBe('')
|
|
const done = stream.push('\x07Welcome', ipv4Rules)
|
|
expect(done).toContain('\x1b]0;ssh root@1.2.3.4\x07')
|
|
expect(done).toContain('Welcome')
|
|
expect(done).not.toMatch(/\x1b\]0;.*\x1b\[38/) // eslint-disable-line no-control-regex -- OSC must stay intact
|
|
})
|
|
|
|
it('holds incomplete CSI across chunks', () => {
|
|
const stream = new StreamingKeywordHighlight()
|
|
expect(stream.push('\x1b[38;2;139', ipv4Rules)).toBe('')
|
|
const out = stream.push(';233;253m10.0.0.1 done', ipv4Rules)
|
|
expect(out.startsWith('\x1b[38;2;139;233;253m')).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('normalizeTerminalInject', () => {
|
|
it('converts LF to CR like xterm paste', () => {
|
|
expect(normalizeTerminalInject('echo hi\n', '')).toBe('echo hi\r')
|
|
expect(normalizeTerminalInject('echo hi', '\r')).toBe('echo hi\r')
|
|
})
|
|
|
|
it('uses CR enter for unix local shells', () => {
|
|
expect(localShellEnterKey('zsh')).toBe('\r')
|
|
expect(localShellEnterKey('pwsh')).toBe('\r\n')
|
|
})
|
|
})
|