takt/src/__tests__/runtime-environment.test.ts

114 lines
3.8 KiB
TypeScript

import { mkdtempSync, existsSync, readFileSync, rmSync, writeFileSync, chmodSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { afterEach, describe, expect, it } from 'vitest';
import { prepareRuntimeEnvironment, resolveRuntimeConfig } from '../core/runtime/runtime-environment.js';
describe('prepareRuntimeEnvironment', () => {
const tempDirs: string[] = [];
const systemTmpDir = tmpdir();
const envKeys = [
'TMPDIR',
'XDG_CACHE_HOME',
'XDG_CONFIG_HOME',
'XDG_STATE_HOME',
'CI',
'JAVA_TOOL_OPTIONS',
'GRADLE_USER_HOME',
'npm_config_cache',
] as const;
const originalEnv = Object.fromEntries(envKeys.map((key) => [key, process.env[key]]));
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
rmSync(dir, { recursive: true, force: true });
}
for (const key of envKeys) {
const value = originalEnv[key];
if (value === undefined) {
delete process.env[key];
} else {
process.env[key] = value;
}
}
});
it('should return undefined when runtime.prepare is not set', () => {
const cwd = mkdtempSync(join(systemTmpDir, 'takt-runtime-env-'));
tempDirs.push(cwd);
const result = prepareRuntimeEnvironment(cwd, undefined);
expect(result).toBeUndefined();
});
it('should create .runtime files and inject tool-specific env', () => {
const cwd = mkdtempSync(join(systemTmpDir, 'takt-runtime-env-'));
tempDirs.push(cwd);
const result = prepareRuntimeEnvironment(cwd, {
prepare: ['gradle', 'node'],
});
expect(result).toBeDefined();
expect(result?.prepare).toEqual(['gradle', 'node']);
const runtimeRoot = join(cwd, '.runtime');
expect(existsSync(runtimeRoot)).toBe(true);
expect(existsSync(join(runtimeRoot, 'tmp'))).toBe(true);
expect(existsSync(join(runtimeRoot, 'cache'))).toBe(true);
expect(existsSync(join(runtimeRoot, 'config'))).toBe(true);
expect(existsSync(join(runtimeRoot, 'state'))).toBe(true);
expect(existsSync(join(runtimeRoot, 'gradle'))).toBe(true);
expect(existsSync(join(runtimeRoot, 'npm'))).toBe(true);
const envFile = join(runtimeRoot, 'env.sh');
expect(existsSync(envFile)).toBe(true);
const envContent = readFileSync(envFile, 'utf-8');
expect(envContent).toContain('export TMPDIR=');
expect(envContent).toContain('export GRADLE_USER_HOME=');
expect(envContent).toContain('export npm_config_cache=');
});
it('should execute custom prepare script path and merge exported env', () => {
const cwd = mkdtempSync(join(systemTmpDir, 'takt-runtime-env-'));
tempDirs.push(cwd);
const scriptPath = join(cwd, 'prepare-custom.sh');
writeFileSync(scriptPath, [
'#!/usr/bin/env bash',
'set -euo pipefail',
'runtime_root="${TAKT_RUNTIME_ROOT:?}"',
'custom_dir="$runtime_root/custom-cache"',
'mkdir -p "$custom_dir"',
'echo "CUSTOM_CACHE_DIR=$custom_dir"',
].join('\n'), 'utf-8');
chmodSync(scriptPath, 0o755);
const result = prepareRuntimeEnvironment(cwd, {
prepare: [scriptPath],
});
expect(result).toBeDefined();
expect(result?.injectedEnv.CUSTOM_CACHE_DIR).toBe(join(cwd, '.runtime', 'custom-cache'));
expect(existsSync(join(cwd, '.runtime', 'custom-cache'))).toBe(true);
});
});
describe('resolveRuntimeConfig', () => {
it('should use piece runtime when both global and piece are defined', () => {
const resolved = resolveRuntimeConfig(
{ prepare: ['gradle', 'node'] },
{ prepare: ['node', 'pnpm'] },
);
expect(resolved).toEqual({ prepare: ['node', 'pnpm'] });
});
it('should fallback to global runtime when piece runtime is missing', () => {
const resolved = resolveRuntimeConfig(
{ prepare: ['gradle', 'node', 'gradle'] },
undefined,
);
expect(resolved).toEqual({ prepare: ['gradle', 'node'] });
});
});