diff --git a/apps/desktop/electron/updater/checkout-source.test.ts b/apps/desktop/electron/updater/checkout-source.test.ts index e7e0bc23b4..3d273b3e5b 100644 --- a/apps/desktop/electron/updater/checkout-source.test.ts +++ b/apps/desktop/electron/updater/checkout-source.test.ts @@ -8,6 +8,7 @@ import { promisify } from 'node:util' import { expect, it, vi } from 'vitest' +import { markerPath } from '../update-marker' import * as updaterProcess from '../updater-process' import { type CheckoutStrategyDeps, createCheckoutStrategy } from './checkout' @@ -366,6 +367,7 @@ urllib.request.build_opener = local_build isMac: process.platform === 'darwin', defaultUpdateBranch: 'main', updateHandoffDwellMs: 0, + handoffClaimTimeoutMs: 2000, resolveUpdateRoot: (): string => root, readSourceUpdate: (install: string, opts: { force?: boolean }): Promise => readSourceUpdate({ @@ -395,6 +397,9 @@ urllib.request.build_opener = local_build vi.spyOn(updaterProcess, 'spawnUpdaterProcess').mockImplementation( (command: string, args: string[], options: SpawnOptions): updaterProcess.UpdaterChild => { spawned.push({ command, args, options }) + // C2: a hand-off has started only once the script takes the Desktop's + // bridge marker in its own (live, foreign) name — do that here. + fs.writeFileSync(markerPath(home), `${process.ppid}\n${Math.floor(Date.now() / 1000)}\n`) return { unref: (): void => {} } } @@ -426,6 +431,8 @@ urllib.request.build_opener = local_build fs.writeFileSync(script, '') expect(await strategy.apply()).toMatchObject({ ok: true, handedOff: true }) const handoff: (typeof spawned)[number] | undefined = spawned.pop() + // The update ran and released its claim; the next apply starts clean. + fs.rmSync(markerPath(home), { force: true }) expect(handoff?.args).toContain(script) expect(handoff?.args).toContain(channel) expect(handoff?.args).toContain(process.platform === 'win32' ? '-Channel' : '--channel') @@ -468,6 +475,7 @@ urllib.request.build_opener = local_build expect(spawned.pop()?.args).toEqual( expect.arrayContaining([process.platform === 'win32' ? '-Branch' : '--branch', 'feature/gui']) ) + fs.rmSync(markerPath(home), { force: true }) fs.rmSync(scriptDirectory, { recursive: true, force: true }) expect(await strategy.apply()).toMatchObject({ manual: true, command: 'hermes update --branch feature/gui' }) // apply() forces a fresh check; under the R2 protocol that re-resolution