import { beforeEach, describe, expect, it } from 'vitest' import i18n from '../../src/i18n' import { translateErrorMessage, translateIpcError } from '../../src/i18n/format' describe('translateErrorMessage — SFTP real-device phrases', () => { beforeEach(async () => { await i18n.changeLanguage('zh-CN') }) it.each([ ['Permission denied', 'errors:sftp.permissionDenied'], ['权限不足,无法访问', 'errors:sftp.permissionDenied'], ['SFTP 会话不存在: sftp-1', 'errors:sftp.sessionGone'], ['SSH 连接不存在', 'errors:sftp.sessionGone'], ['SFTP 正在传输文件,请稍后再试', 'errors:sftp.busy'], ['transfer is in progress', 'errors:sftp.busy'], ['Unable to startup channel', 'errors:sftp.channelFailed'], ['MaxSessions limit', 'errors:sftp.channelFailed'], ['文件过大(3.2 MB),编辑上限约 2MB', 'errors:sftp.editTooLarge'], ['该文件像是二进制内容,无法用文本编辑器打开', 'errors:sftp.editBinary'], ['远程文件不是有效 UTF-8 文本', 'errors:sftp.editNotUtf8'], ['传输已取消', 'errors:sftp.transferCancelled'], ['No space left on device', 'errors:sftp.diskFull'], ['ENOSPC', 'errors:sftp.diskFull'], [ '建立远程端口转发失败: [Session(-32)] Unable to complete request for forward-listen', 'errors:forward.remoteDenied', ], [ '建立远程端口转发失败: 远端拒绝监听端口 8080(常见原因:AllowTcpForwarding 未开或仅为 local、PermitListen 未包含该端口、端口已被占用)。可用命令行核对:ssh -R 8080:127.0.0.1:<本地端口> user@host', 'errors:forward.remoteDenied', ], [ '建立远程端口转发失败: 远端拒绝监听特权端口 80(需 root 或改用 ≥1024;另请确认 AllowTcpForwarding / PermitListen,且端口未被占用)。可用命令行核对:ssh -R 80:127.0.0.1:<本地端口> user@host', 'errors:forward.remoteDeniedPrivileged', ], ['closed by user', 'errors:connection.unexpectedDropped'], ['connection closed', 'errors:connection.unexpectedDropped'], ['keepalive failed', 'errors:connection.keepaliveFailed'], ['shell.idleTimeout', 'errors:connection.idleKicked'], ['shell.exited', 'errors:connection.shellExited'], ['命令已终止', 'ai:step.terminated'], ['command cancelled', 'ai:step.terminated'], ])('maps %s', (raw, key) => { expect(translateErrorMessage(raw)).toBe(i18n.t(key)) }) it('falls back to raw text when unmatched', () => { expect(translateErrorMessage('weird native blip 0xdead')).toBe('weird native blip 0xdead') }) }) describe('translateIpcError', () => { beforeEach(async () => { await i18n.changeLanguage('zh-CN') }) it('maps a stable errorCode before the raw phrase', () => { expect(translateIpcError('ignored', 'native.taskJoin')).toBe(i18n.t('errors:native.taskJoin')) expect(translateIpcError('native.invalidBase64')).toBe(i18n.t('errors:native.invalidBase64')) }) it('falls back to phrase matching when the code is unknown', () => { expect(translateIpcError('Permission denied', 'not.a.real.code')).toBe(i18n.t('errors:sftp.permissionDenied')) }) })