test(update): isolate current-install command deps

- load a fresh update-command module instance per test via query-string import

- prevent Bun mock.module leakage from command-router tests from masking handleUpdateCommand in CI
This commit is contained in:
Tam Nhu Tran
2026-04-13 15:09:35 -04:00
parent 3103f3f293
commit 394d7d94fc
@@ -1,5 +1,5 @@
import { beforeEach, describe, expect, it } from 'bun:test';
import { handleUpdateCommand, type UpdateCommandDeps } from '../../../src/commands/update-command';
import type { UpdateCommandDeps } from '../../../src/commands/update-command';
import type { UpdateResult } from '../../../src/utils/update-checker';
let logLines: string[] = [];
@@ -99,6 +99,13 @@ function createDeps(overrides: Partial<UpdateCommandDeps> = {}): UpdateCommandDe
};
}
async function loadHandleUpdateCommand() {
const mod = await import(
`../../../src/commands/update-command?test=${Date.now()}-${Math.random()}`
);
return mod.handleUpdateCommand;
}
beforeEach(() => {
logLines = [];
spawnCalls = [];
@@ -118,6 +125,7 @@ beforeEach(() => {
describe('update-command current install handling', () => {
it('updates through the current install manager and prefix', async () => {
const handleUpdateCommand = await loadHandleUpdateCommand();
await handleUpdateCommand({ beta: true }, createDeps());
const installCall = spawnCalls.find((call) => call.args.includes('install'));
@@ -129,6 +137,7 @@ describe('update-command current install handling', () => {
});
it('fails when another manager updated elsewhere but the current binary stayed stale', async () => {
const handleUpdateCommand = await loadHandleUpdateCommand();
scenario = {
beforeState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
afterState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
@@ -144,6 +153,7 @@ describe('update-command current install handling', () => {
});
it('keeps force mode under exact target-version verification', async () => {
const handleUpdateCommand = await loadHandleUpdateCommand();
scenario = {
beforeState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
afterState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
@@ -156,6 +166,7 @@ describe('update-command current install handling', () => {
});
it('warns but succeeds when target resolution says no update and the current install stays unchanged', async () => {
const handleUpdateCommand = await loadHandleUpdateCommand();
scenario = {
beforeState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
afterState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
@@ -169,6 +180,7 @@ describe('update-command current install handling', () => {
});
it('warns but succeeds when target version resolution fails and the current install stays unchanged', async () => {
const handleUpdateCommand = await loadHandleUpdateCommand();
scenario = {
beforeState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
afterState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
@@ -182,6 +194,7 @@ describe('update-command current install handling', () => {
});
it('uses the injected version in the no-update message', async () => {
const handleUpdateCommand = await loadHandleUpdateCommand();
updateCheckResult = { status: 'no_update' };
await handleUpdateCommand(
@@ -196,6 +209,7 @@ describe('update-command current install handling', () => {
});
it('accepts a newer installed version when the dist-tag moves during update', async () => {
const handleUpdateCommand = await loadHandleUpdateCommand();
scenario = {
beforeState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
afterState: { version: '7.67.1-dev.0', packageJsonMtimeMs: 200, scriptMtimeMs: 200 },
@@ -208,6 +222,7 @@ describe('update-command current install handling', () => {
});
it('accepts force reinstall when the version stays the same but the current install files change', async () => {
const handleUpdateCommand = await loadHandleUpdateCommand();
scenario = {
beforeState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 100, scriptMtimeMs: 100 },
afterState: { version: '7.67.0-dev.5', packageJsonMtimeMs: 200, scriptMtimeMs: 200 },
@@ -229,6 +244,7 @@ describe('update-command current install handling', () => {
])(
'routes updates through the current %s install and env',
async (manager, expectedArg, envKey, envValue) => {
const handleUpdateCommand = await loadHandleUpdateCommand();
currentInstallOverride = {
...installDescriptor(),
manager: manager as 'bun' | 'yarn' | 'pnpm',