145 lines
4.1 KiB
JavaScript
145 lines
4.1 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import {
|
|
mkdirSync,
|
|
mkdtempSync,
|
|
existsSync,
|
|
rmSync,
|
|
utimesSync,
|
|
writeFileSync,
|
|
} from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import path from 'node:path';
|
|
import { pathToFileURL } from 'node:url';
|
|
import { build } from 'esbuild';
|
|
import { test } from 'vitest';
|
|
|
|
async function loadHelper() {
|
|
const tempDir = mkdtempSync(path.join(tmpdir(), 'pinme-install-helper-'));
|
|
const outfile = path.join(tempDir, 'installProjectDependencies.cjs');
|
|
|
|
await build({
|
|
entryPoints: [path.resolve('bin/utils/installProjectDependencies.ts')],
|
|
outfile,
|
|
bundle: true,
|
|
platform: 'node',
|
|
format: 'cjs',
|
|
target: 'node18',
|
|
});
|
|
|
|
return import(pathToFileURL(outfile).href);
|
|
}
|
|
|
|
function makeProject() {
|
|
return mkdtempSync(path.join(tmpdir(), 'pinme-install-project-'));
|
|
}
|
|
|
|
test('readBackgroundInstallStatus treats fresh log-only markers as running', async () => {
|
|
const {
|
|
INSTALL_LOG_FILE,
|
|
readBackgroundInstallStatus,
|
|
} = await loadHelper();
|
|
const projectDir = makeProject();
|
|
|
|
try {
|
|
writeFileSync(path.join(projectDir, INSTALL_LOG_FILE), 'starting npm ci\n');
|
|
|
|
assert.deepEqual(readBackgroundInstallStatus(projectDir), {
|
|
status: 'running',
|
|
exitCode: null,
|
|
logPath: path.join(projectDir, INSTALL_LOG_FILE),
|
|
});
|
|
} finally {
|
|
rmSync(projectDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('readBackgroundInstallStatus detects stale log-only markers as interrupted', async () => {
|
|
const {
|
|
INSTALL_LOG_FILE,
|
|
readBackgroundInstallStatus,
|
|
} = await loadHelper();
|
|
const projectDir = makeProject();
|
|
const logPath = path.join(projectDir, INSTALL_LOG_FILE);
|
|
|
|
try {
|
|
mkdirSync(projectDir, { recursive: true });
|
|
writeFileSync(logPath, 'starting npm ci\n');
|
|
const staleTime = new Date(Date.now() - 2 * 60 * 1000);
|
|
utimesSync(logPath, staleTime, staleTime);
|
|
|
|
assert.deepEqual(readBackgroundInstallStatus(projectDir), {
|
|
status: 'interrupted',
|
|
exitCode: null,
|
|
logPath,
|
|
});
|
|
} finally {
|
|
rmSync(projectDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('readBackgroundInstallStatus detects dead background install pid as interrupted', async () => {
|
|
const {
|
|
INSTALL_LOG_FILE,
|
|
INSTALL_PID_FILE,
|
|
readBackgroundInstallStatus,
|
|
} = await loadHelper();
|
|
const projectDir = makeProject();
|
|
const logPath = path.join(projectDir, INSTALL_LOG_FILE);
|
|
|
|
try {
|
|
writeFileSync(logPath, 'starting npm ci\n');
|
|
writeFileSync(path.join(projectDir, INSTALL_PID_FILE), '999999999');
|
|
|
|
assert.deepEqual(readBackgroundInstallStatus(projectDir), {
|
|
status: 'interrupted',
|
|
exitCode: null,
|
|
logPath,
|
|
});
|
|
} finally {
|
|
rmSync(projectDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('stopBackgroundInstall clears a dead background install pid marker', async () => {
|
|
const {
|
|
INSTALL_LOG_FILE,
|
|
INSTALL_PID_FILE,
|
|
stopBackgroundInstall,
|
|
} = await loadHelper();
|
|
const projectDir = makeProject();
|
|
const logPath = path.join(projectDir, INSTALL_LOG_FILE);
|
|
const pidPath = path.join(projectDir, INSTALL_PID_FILE);
|
|
|
|
try {
|
|
writeFileSync(logPath, 'starting npm ci\n');
|
|
writeFileSync(pidPath, '999999999');
|
|
|
|
assert.equal(await stopBackgroundInstall(projectDir), false);
|
|
assert.equal(readFileExists(pidPath), false);
|
|
} finally {
|
|
rmSync(projectDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('buildBackgroundInstallCommand captures Windows npm exit code after command finishes', async () => {
|
|
const {
|
|
buildBackgroundInstallCommand,
|
|
} = await loadHelper();
|
|
|
|
const command = buildBackgroundInstallCommand(
|
|
'ci',
|
|
'C:\\Users\\Pin Me\\project\\.pinme-install.log',
|
|
'C:\\Users\\Pin Me\\project\\.pinme-install.exitcode',
|
|
'win32',
|
|
);
|
|
|
|
assert.deepEqual(command.shellArgs.slice(0, 4), ['/d', '/s', '/v:on', '/c']);
|
|
assert.match(command.shellArgs[4], /echo !errorlevel! >/);
|
|
assert.doesNotMatch(command.shellArgs[4], /%errorlevel%/);
|
|
assert.match(command.shellArgs[4], /"C:\\Users\\Pin Me\\project\\.pinme-install.log"/);
|
|
});
|
|
|
|
function readFileExists(filePath) {
|
|
return existsSync(filePath);
|
|
}
|