package-manager.test.js
1 'use strict' 2 /* eslint-disable @typescript-eslint/no-require-imports */ 3 4 const test = require('node:test') 5 const assert = require('node:assert/strict') 6 const fs = require('node:fs') 7 const os = require('node:os') 8 const path = require('node:path') 9 10 const { 11 INSTALL_METADATA_FILE, 12 LOCKFILE_NAMES, 13 dependenciesChanged, 14 detectPackageManager, 15 detectPackageManagerFromUserAgent, 16 getGlobalUpdateSpec, 17 getInstallCommand, 18 getRunScriptCommand, 19 } = require('./package-manager.js') 20 21 test('detectPackageManagerFromUserAgent parses supported package managers', () => { 22 assert.equal(detectPackageManagerFromUserAgent('pnpm/10.6.1 npm/? node/v22.6.0 darwin arm64'), 'pnpm') 23 assert.equal(detectPackageManagerFromUserAgent('yarn/4.7.0 npm/? node/v22.6.0 darwin arm64'), 'yarn') 24 assert.equal(detectPackageManagerFromUserAgent('bun/1.2.10 npm/? node/v22.6.0 darwin arm64'), 'bun') 25 assert.equal(detectPackageManagerFromUserAgent('npm/10.9.2 node/v22.6.0 darwin arm64'), 'npm') 26 }) 27 28 test('detectPackageManager prefers the lockfile present in the workspace', () => { 29 const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'swarmclaw-pm-')) 30 31 fs.writeFileSync(path.join(tmpDir, 'pnpm-lock.yaml'), 'lock', 'utf8') 32 assert.equal(detectPackageManager(tmpDir), 'pnpm') 33 34 fs.writeFileSync(path.join(tmpDir, 'bun.lockb'), 'lock', 'utf8') 35 assert.equal(detectPackageManager(tmpDir), 'bun') 36 37 fs.rmSync(tmpDir, { recursive: true, force: true }) 38 }) 39 40 test('detectPackageManager falls back to npm when no lockfile exists', () => { 41 const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'swarmclaw-pm-empty-')) 42 assert.equal(detectPackageManager(tmpDir), 'npm') 43 fs.rmSync(tmpDir, { recursive: true, force: true }) 44 }) 45 46 test('detectPackageManager uses install metadata when present', () => { 47 const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'swarmclaw-pm-meta-')) 48 fs.writeFileSync( 49 path.join(tmpDir, INSTALL_METADATA_FILE), 50 JSON.stringify({ packageManager: 'yarn' }), 51 'utf8', 52 ) 53 assert.equal(detectPackageManager(tmpDir), 'yarn') 54 fs.rmSync(tmpDir, { recursive: true, force: true }) 55 }) 56 57 test('dependenciesChanged recognizes package.json and all supported lockfiles', () => { 58 assert.equal(dependenciesChanged('package.json\nsrc/app.ts'), true) 59 for (const lockfile of LOCKFILE_NAMES) { 60 assert.equal(dependenciesChanged(`${lockfile}\nREADME.md`), true) 61 } 62 assert.equal(dependenciesChanged('README.md\nsrc/index.ts'), false) 63 }) 64 65 test('getInstallCommand returns manager-specific install arguments', () => { 66 assert.deepEqual(getInstallCommand('npm', true), { command: 'npm', args: ['install', '--omit=dev'] }) 67 assert.deepEqual(getInstallCommand('pnpm', false), { command: 'pnpm', args: ['install'] }) 68 assert.deepEqual(getInstallCommand('yarn', true), { command: 'yarn', args: ['install', '--production=true'] }) 69 assert.deepEqual(getInstallCommand('bun', true), { command: 'bun', args: ['install', '--production'] }) 70 }) 71 72 test('getRunScriptCommand returns manager-specific script launchers', () => { 73 assert.deepEqual(getRunScriptCommand('npm', 'build'), { command: 'npm', args: ['run', 'build'] }) 74 assert.deepEqual(getRunScriptCommand('pnpm', 'start'), { command: 'pnpm', args: ['start'] }) 75 assert.deepEqual(getRunScriptCommand('yarn', 'dev'), { command: 'yarn', args: ['dev'] }) 76 assert.deepEqual(getRunScriptCommand('bun', 'start'), { command: 'bun', args: ['run', 'start'] }) 77 }) 78 79 test('getGlobalUpdateSpec returns manager-specific update commands', () => { 80 assert.deepEqual(getGlobalUpdateSpec('npm', '@swarmclawai/swarmclaw'), { 81 command: 'npm', 82 args: ['update', '-g', '@swarmclawai/swarmclaw'], 83 display: 'npm update -g @swarmclawai/swarmclaw', 84 }) 85 assert.deepEqual(getGlobalUpdateSpec('pnpm', '@swarmclawai/swarmclaw'), { 86 command: 'pnpm', 87 args: ['add', '-g', '@swarmclawai/swarmclaw@latest'], 88 display: 'pnpm add -g @swarmclawai/swarmclaw@latest', 89 }) 90 })