From 58c2e460c8024673fa546f8ea4155136532057a3 Mon Sep 17 00:00:00 2001 From: Magal Date: Thu, 21 May 2026 11:36:19 -0300 Subject: [PATCH] chore: alphabetize npm scripts and fix test file formatting --- package.json | 2 +- test/test-inject-mcp-config.js | 104 +++++++++++++++++---------------- test/verify-installer.js | 74 +++++++++++++++-------- 3 files changed, 105 insertions(+), 75 deletions(-) diff --git a/package.json b/package.json index 7ec8d6d25..c6388580b 100644 --- a/package.json +++ b/package.json @@ -36,9 +36,9 @@ "format:fix:staged": "prettier --write", "install:bmad": "node tools/installer/bmad-cli.js install", "lint": "eslint . --ext .js,.cjs,.mjs,.yaml --max-warnings=0", - "memtrace:restart": "node _bmad/scripts/memtrace/memtrace-restart.mjs", "lint:fix": "eslint . --ext .js,.cjs,.mjs,.yaml --fix", "lint:md": "markdownlint-cli2 \"**/*.md\"", + "memtrace:restart": "node _bmad/scripts/memtrace/memtrace-restart.mjs", "prepare": "command -v husky >/dev/null 2>&1 && husky || exit 0", "quality": "npm run format:check && npm run lint && npm run lint:md && npm run docs:build && npm run test:install && npm run test:urls && npm run validate:refs && npm run validate:skills", "rebundle": "node tools/installer/bundlers/bundle-web.js rebundle", diff --git a/test/test-inject-mcp-config.js b/test/test-inject-mcp-config.js index c260d2647..4cf21aad0 100644 --- a/test/test-inject-mcp-config.js +++ b/test/test-inject-mcp-config.js @@ -43,15 +43,19 @@ function runInjector(mode, envOverrides = {}) { const scriptPath = path.resolve(__dirname, '../_bmad/scripts/memtrace/inject-mcp-config.mjs'); const command = `node "${scriptPath}" --mode ${mode}`; - exec(command, { - env: { ...process.env, ...envOverrides } - }, (error, stdout, stderr) => { - if (error) { - reject({ error, stdout, stderr }); - } else { - resolve({ stdout, stderr }); - } - }); + exec( + command, + { + env: { ...process.env, ...envOverrides }, + }, + (error, stdout, stderr) => { + if (error) { + reject({ error, stdout, stderr }); + } else { + resolve({ stdout, stderr }); + } + }, + ); }); } @@ -77,14 +81,14 @@ async function runTests() { assert( config.mcpServers !== undefined && config.mcpServers.memtrace !== undefined, - 'Test 1.1: Creates new Claude config file and injects memtrace server skeleton' + 'Test 1.1: Creates new Claude config file and injects memtrace server skeleton', ); assert( config.mcpServers.memtrace.command === 'memtrace' && config.mcpServers.memtrace.args[0] === 'mcp', - 'Test 1.1: Injected server details match expected schema format' + 'Test 1.1: Injected server details match expected schema format', ); - } catch (err) { - assert(false, 'Test 1.1 Failed with error', err.message || JSON.stringify(err)); + } catch (error) { + assert(false, 'Test 1.1 Failed with error', error.message || JSON.stringify(error)); } // Test 1.2: File exists with other servers (preserves other servers) @@ -93,9 +97,9 @@ async function runTests() { mcpServers: { otherServer: { command: 'node', - args: ['other-path/server.js'] - } - } + args: ['other-path/server.js'], + }, + }, }; await fs.writeFile(claudeTestFile, JSON.stringify(preExistingConfig, null, 2), 'utf8'); @@ -105,14 +109,14 @@ async function runTests() { assert( config.mcpServers.otherServer !== undefined && config.mcpServers.otherServer.command === 'node', - 'Test 1.2: Preserves pre-existing mcpServers in Claude config' + 'Test 1.2: Preserves pre-existing mcpServers in Claude config', ); assert( config.mcpServers.memtrace !== undefined && config.mcpServers.memtrace.command === 'memtrace', - 'Test 1.2: Correctly appends memtrace server configuration alongside existing ones' + 'Test 1.2: Correctly appends memtrace server configuration alongside existing ones', ); - } catch (err) { - assert(false, 'Test 1.2 Failed with error', err.message || JSON.stringify(err)); + } catch (error) { + assert(false, 'Test 1.2 Failed with error', error.message || JSON.stringify(error)); } // Test 1.3: File exists and memtrace key already exists (overwrites memtrace key only) @@ -121,13 +125,13 @@ async function runTests() { mcpServers: { otherServer: { command: 'node', - args: ['other-path/server.js'] + args: ['other-path/server.js'], }, memtrace: { command: 'old-command', - args: ['old-arg'] - } - } + args: ['old-arg'], + }, + }, }; await fs.writeFile(claudeTestFile, JSON.stringify(preExistingConfig, null, 2), 'utf8'); @@ -137,14 +141,14 @@ async function runTests() { assert( config.mcpServers.otherServer !== undefined && config.mcpServers.otherServer.command === 'node', - 'Test 1.3: Overwriting preserves other servers' + 'Test 1.3: Overwriting preserves other servers', ); assert( config.mcpServers.memtrace.command === 'memtrace' && config.mcpServers.memtrace.args[0] === 'mcp', - 'Test 1.3: Correctly overwrites only the memtrace key' + 'Test 1.3: Correctly overwrites only the memtrace key', ); - } catch (err) { - assert(false, 'Test 1.3 Failed with error', err.message || JSON.stringify(err)); + } catch (error) { + assert(false, 'Test 1.3 Failed with error', error.message || JSON.stringify(error)); } console.log(''); @@ -164,14 +168,14 @@ async function runTests() { assert( config.mcp !== undefined && config.mcp.memtrace !== undefined, - 'Test 2.1: Creates new OpenCode config file and injects memtrace server skeleton' + 'Test 2.1: Creates new OpenCode config file and injects memtrace server skeleton', ); assert( config.mcp.memtrace.type === 'local' && config.mcp.memtrace.command[0] === 'memtrace' && config.mcp.memtrace.command[1] === 'mcp', - 'Test 2.1: Injected server details match expected OpenCode schema format' + 'Test 2.1: Injected server details match expected OpenCode schema format', ); - } catch (err) { - assert(false, 'Test 2.1 Failed with error', err.message || JSON.stringify(err)); + } catch (error) { + assert(false, 'Test 2.1 Failed with error', error.message || JSON.stringify(error)); } // Test 2.2: File exists with other keys (preserves other keys) @@ -180,9 +184,9 @@ async function runTests() { mcp: { otherServer: { type: 'local', - command: ['other-server'] - } - } + command: ['other-server'], + }, + }, }; await fs.writeFile(opencodeTestFile, JSON.stringify(preExistingConfig, null, 2), 'utf8'); @@ -192,14 +196,14 @@ async function runTests() { assert( config.mcp.otherServer !== undefined && config.mcp.otherServer.type === 'local', - 'Test 2.2: Preserves pre-existing mcp in OpenCode config' + 'Test 2.2: Preserves pre-existing mcp in OpenCode config', ); assert( config.mcp.memtrace !== undefined && config.mcp.memtrace.type === 'local', - 'Test 2.2: Correctly appends memtrace server configuration alongside existing ones' + 'Test 2.2: Correctly appends memtrace server configuration alongside existing ones', ); - } catch (err) { - assert(false, 'Test 2.2 Failed with error', err.message || JSON.stringify(err)); + } catch (error) { + assert(false, 'Test 2.2 Failed with error', error.message || JSON.stringify(error)); } // Test 2.3: File exists and memtrace key already exists (overwrites memtrace key only) @@ -208,13 +212,13 @@ async function runTests() { mcp: { otherServer: { type: 'local', - command: ['other-server'] + command: ['other-server'], }, memtrace: { type: 'remote', - command: ['old-memtrace'] - } - } + command: ['old-memtrace'], + }, + }, }; await fs.writeFile(opencodeTestFile, JSON.stringify(preExistingConfig, null, 2), 'utf8'); @@ -224,20 +228,20 @@ async function runTests() { assert( config.mcp.otherServer !== undefined && config.mcp.otherServer.type === 'local', - 'Test 2.3: Overwriting preserves other OpenCode servers' + 'Test 2.3: Overwriting preserves other OpenCode servers', ); assert( config.mcp.memtrace.type === 'local' && config.mcp.memtrace.command[0] === 'memtrace', - 'Test 2.3: Correctly overwrites only the memtrace key in OpenCode config' + 'Test 2.3: Correctly overwrites only the memtrace key in OpenCode config', ); - } catch (err) { - assert(false, 'Test 2.3 Failed with error', err.message || JSON.stringify(err)); + } catch (error) { + assert(false, 'Test 2.3 Failed with error', error.message || JSON.stringify(error)); } // Clean up try { await fs.rm(tempDir, { recursive: true, force: true }); - } catch (err) { + } catch { // Ignore cleanup errors } @@ -252,7 +256,7 @@ async function runTests() { } } -runTests().catch(err => { - console.error('Fatal test error:', err); +runTests().catch((error) => { + console.error('Fatal test error:', error); process.exit(1); }); diff --git a/test/verify-installer.js b/test/verify-installer.js index 808b7f464..0f21ae4b8 100644 --- a/test/verify-installer.js +++ b/test/verify-installer.js @@ -58,7 +58,7 @@ async function ensureDir(filePath) { const dir = path.dirname(filePath); try { await fs.mkdir(dir, { recursive: true }); - } catch (err) {} + } catch { /* directory may already exist */ } } async function runVerification() { @@ -116,20 +116,32 @@ async function runVerification() { const possibleBash1 = path.join(gitParent, 'bin', 'bash.exe'); const possibleBash2 = path.join(gitParent, 'bin', 'sh.exe'); - if (await fs.access(possibleBash1).then(() => true).catch(() => false)) { + if ( + await fs + .access(possibleBash1) + .then(() => true) + .catch(() => false) + ) { command = `"${possibleBash1}" install-bmad-memtrace.sh`; - } else if (await fs.access(possibleBash2).then(() => true).catch(() => false)) { + } else if ( + await fs + .access(possibleBash2) + .then(() => true) + .catch(() => false) + ) { command = `"${possibleBash2}" install-bmad-memtrace.sh`; } } - } catch (e) { + } catch { // Fallback - const paths = [ - 'C:\\Program Files\\Git\\bin\\bash.exe', - 'C:\\Program Files (x86)\\Git\\bin\\bash.exe', - ]; + const paths = [String.raw`C:\Program Files\Git\bin\bash.exe`, String.raw`C:\Program Files (x86)\Git\bin\bash.exe`]; for (const p of paths) { - if (await fs.access(p).then(() => true).catch(() => false)) { + if ( + await fs + .access(p) + .then(() => true) + .catch(() => false) + ) { command = `"${p}" install-bmad-memtrace.sh`; break; } @@ -150,23 +162,38 @@ async function runVerification() { // 5. Assertions // AC 1: .memtrace-workspace exists - const anchorExists = await fs.access(path.join(tempDir, '.memtrace-workspace')).then(() => true).catch(() => false); + const anchorExists = await fs + .access(path.join(tempDir, '.memtrace-workspace')) + .then(() => true) + .catch(() => false); assert(anchorExists, 'AC 1: .memtrace-workspace anchor file successfully created in project root'); // Legacy cleanup: README.md is deleted - const readmeExists = await fs.access(dummyClonedFile).then(() => true).catch(() => false); + const readmeExists = await fs + .access(dummyClonedFile) + .then(() => true) + .catch(() => false); assert(!readmeExists, 'Legacy cleanup: Tracked clone files (README.md) successfully deleted'); // Git removal: .git is deleted - const gitExists = await fs.access(path.join(tempDir, '.git')).then(() => true).catch(() => false); + const gitExists = await fs + .access(path.join(tempDir, '.git')) + .then(() => true) + .catch(() => false); assert(!gitExists, 'Security/Standalone: .git directory completely removed'); // Staging cleanup: bmad-install is deleted - const stagingExists = await fs.access(path.join(tempDir, 'bmad-install')).then(() => true).catch(() => false); + const stagingExists = await fs + .access(path.join(tempDir, 'bmad-install')) + .then(() => true) + .catch(() => false); assert(!stagingExists, 'Runtime cleanup: bmad-install staging directory successfully removed'); // BMad preservation: _bmad directory remains - const bmadExists = await fs.access(path.join(tempDir, '_bmad')).then(() => true).catch(() => false); + const bmadExists = await fs + .access(path.join(tempDir, '_bmad')) + .then(() => true) + .catch(() => false); assert(bmadExists, 'Core preservation: _bmad directory preserved post-cleanup'); // AC 2: Claude Desktop configuration successfully injected @@ -174,7 +201,7 @@ async function runVerification() { const claudeConfig = JSON.parse(claudeContent); assert( claudeConfig.mcpServers && claudeConfig.mcpServers.memtrace && claudeConfig.mcpServers.memtrace.command === 'memtrace', - 'AC 2: Claude Desktop config correctly created and populated with memtrace MCP server' + 'AC 2: Claude Desktop config correctly created and populated with memtrace MCP server', ); // AC 3: OpenCode configuration successfully injected @@ -182,20 +209,19 @@ async function runVerification() { const opencodeConfig = JSON.parse(opencodeContent); assert( opencodeConfig.mcp && opencodeConfig.mcp.memtrace && opencodeConfig.mcp.memtrace.type === 'local', - 'AC 3: OpenCode config correctly created and populated with memtrace local definition' + 'AC 3: OpenCode config correctly created and populated with memtrace local definition', ); - - } catch (err) { - console.error('Verification failed with error:', err); - if (err.stdout) console.error('stdout:', err.stdout); - if (err.stderr) console.error('stderr:', err.stderr); + } catch (error) { + console.error('Verification failed with error:', error); + if (error.stdout) console.error('stdout:', error.stdout); + if (error.stderr) console.error('stderr:', error.stderr); failed++; } // Clean up try { await fs.rm(tempDir, { recursive: true, force: true }); - } catch (err) {} + } catch { /* cleanup errors are non-fatal */ } console.log(`\n${colors.cyan}========================================`); console.log(`Verification Summary: Passed: ${passed}, Failed: ${failed}`); @@ -208,7 +234,7 @@ async function runVerification() { } } -runVerification().catch(err => { - console.error('Fatal verification error:', err); +runVerification().catch((error) => { + console.error('Fatal verification error:', error); process.exit(1); });