chore: alphabetize npm scripts and fix test file formatting
This commit is contained in:
parent
ea813716e2
commit
58c2e460c8
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue