fix(desktop): lint missing-profile error and move its tests to a sibling file

Keeps remote-lifecycle.test.ts under its code-health line cap and clears
the curly/no-useless-escape errors from check:lint.
This commit is contained in:
Brooklyn Nicholson
2026-10-07 13:20:50 -05:00
committed by brooklyn!
parent 071842a869
commit 6fa88c19ac
3 changed files with 67 additions and 20 deletions

View File

@@ -0,0 +1,53 @@
import assert from 'node:assert/strict'
import { test } from 'vitest'
import { scrapeReadyPort, spawnLogPath } from './remote-lifecycle'
const OWNERSHIP_ID = '0123456789abcdef0123456789abcdef'
const SPAWN_NONCE = '0123456789abcdef'
function logSsh(log: string) {
return {
async exec(cmd: string) {
return cmd.startsWith('cat ') ? log : ''
}
}
}
test('scrapeReadyPort explains a missing remote profile', async () => {
const ssh = logSsh("Error: Profile 'operator' does not exist. Create it with: hermes profile create operator\n")
await assert.rejects(
() =>
scrapeReadyPort(ssh, spawnLogPath(OWNERSHIP_ID, SPAWN_NONCE), {
timeoutMs: 1000,
isAlive: async () => false
}),
(err: any) => {
assert.equal(err.kind, 'remote-profile-missing')
assert.equal(err.profile, 'operator')
assert.match(err.message, /remote Hermes profile 'operator' does not exist/)
assert.match(err.message, /hermes profile create operator/)
return true
}
)
})
test('scrapeReadyPort keeps the generic spawn failure for other exits', async () => {
const ssh = logSsh('Traceback (most recent call last):\nRuntimeError: boom\n')
await assert.rejects(
() =>
scrapeReadyPort(ssh, spawnLogPath(OWNERSHIP_ID, SPAWN_NONCE), {
timeoutMs: 1000,
isAlive: async () => false
}),
(err: any) => {
assert.equal(err.kind, 'spawn-failed')
return true
}
)
})

View File

@@ -1088,23 +1088,6 @@ test('scrapeReadyPort reads only the named spawn log', async () => {
assert.ok(ssh.calls.every(call => !call.includes('desktop-ssh.log')))
})
test('scrapeReadyPort explains a missing remote profile', async () => {
const ssh = fakeSsh([[/cat/, "Error: Profile 'operator' does not exist. Create it with: hermes profile create operator\n"]])
await assert.rejects(
() => scrapeReadyPort(ssh, spawnLogPath(OWNERSHIP_ID, SPAWN_NONCE), {
timeoutMs: 1000,
isAlive: async () => false
}),
(err: any) => {
assert.equal(err.kind, 'remote-profile-missing')
assert.match(err.message, /remote Hermes profile 'operator' does not exist/)
assert.match(err.message, /hermes profile create operator/)
return true
}
)
})
test('scrapeReadyPort times out and reports a dead spawn', async () => {
// never emits a READY line
const ssh = fakeSsh([[/cat .*\.log/, 'still starting...']])

View File

@@ -1218,18 +1218,25 @@ async function remoteSupportsSshOwnership(ssh, hermesPath) {
}
function remoteProfileMissingError(output) {
const match = String(output || '').match(/Error: Profile ['\"]([^'\"]+)['\"] does not exist\.?(?: Create it with: ([^\n]+))?/i)
const match = String(output || '').match(
/Error: Profile ['"]([^'"]+)['"] does not exist\.?(?: Create it with: ([^\n]+))?/i
)
if (!match) return null
if (!match) {
return null
}
const profile = match[1]
const createCommand = match[2]?.trim()
const err: any = new Error(
`The remote Hermes profile '${profile}' does not exist. ` +
`Select an existing remote profile${createCommand ? ` or create it with: ${createCommand}` : '.'}`
)
err.kind = 'remote-profile-missing'
err.profile = profile
return err
}
@@ -1250,7 +1257,11 @@ async function scrapeReadyPort(ssh, logPath, { timeoutMs = resolveReadyTimeoutMs
if (isAlive && !(await isAlive())) {
const cause = remoteProfileMissingError(tail)
if (cause) throw cause
if (cause) {
throw cause
}
const err: any = new Error('Remote dashboard process exited before announcing its port.')
err.kind = 'spawn-failed'
throw err