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:
committed by
brooklyn!
parent
071842a869
commit
6fa88c19ac
@@ -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
|
||||
}
|
||||
)
|
||||
})
|
||||
@@ -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...']])
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user