mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-02-15 19:03:22 +08:00
fix: add missing validation in renameAlias, add 6 tests
renameAlias was missing length (>128), reserved name, and empty string validation that setAlias enforced. This inconsistency allowed renaming aliases to reserved names like 'list' or 'delete'. Also adds tests for: - renameAlias empty string, reserved name, and length limit - validate-skills whitespace-only SKILL.md rejection - validate-rules whitespace-only file and recursive subdirectory scan
This commit is contained in:
@@ -310,15 +310,28 @@ function renameAlias(oldAlias, newAlias) {
|
||||
return { success: false, error: `Alias '${oldAlias}' not found` };
|
||||
}
|
||||
|
||||
if (data.aliases[newAlias]) {
|
||||
return { success: false, error: `Alias '${newAlias}' already exists` };
|
||||
// Validate new alias name (same rules as setAlias)
|
||||
if (!newAlias || newAlias.length === 0) {
|
||||
return { success: false, error: 'New alias name cannot be empty' };
|
||||
}
|
||||
|
||||
if (newAlias.length > 128) {
|
||||
return { success: false, error: 'New alias name cannot exceed 128 characters' };
|
||||
}
|
||||
|
||||
// Validate new alias name
|
||||
if (!/^[a-zA-Z0-9_-]+$/.test(newAlias)) {
|
||||
return { success: false, error: 'New alias name must contain only letters, numbers, dashes, and underscores' };
|
||||
}
|
||||
|
||||
const reserved = ['list', 'help', 'remove', 'delete', 'create', 'set'];
|
||||
if (reserved.includes(newAlias.toLowerCase())) {
|
||||
return { success: false, error: `'${newAlias}' is a reserved alias name` };
|
||||
}
|
||||
|
||||
if (data.aliases[newAlias]) {
|
||||
return { success: false, error: `Alias '${newAlias}' already exists` };
|
||||
}
|
||||
|
||||
const aliasData = data.aliases[oldAlias];
|
||||
delete data.aliases[oldAlias];
|
||||
|
||||
|
||||
@@ -470,6 +470,18 @@ function runTests() {
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('fails on whitespace-only SKILL.md', () => {
|
||||
const testDir = createTestDir();
|
||||
const skillDir = path.join(testDir, 'blank-skill');
|
||||
fs.mkdirSync(skillDir);
|
||||
fs.writeFileSync(path.join(skillDir, 'SKILL.md'), ' \n\t\n ');
|
||||
|
||||
const result = runValidatorWithDir('validate-skills', 'SKILLS_DIR', testDir);
|
||||
assert.strictEqual(result.code, 1, 'Should reject whitespace-only SKILL.md');
|
||||
assert.ok(result.stderr.includes('Empty file'), 'Should report empty file');
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// ==========================================
|
||||
// validate-commands.js
|
||||
// ==========================================
|
||||
@@ -673,6 +685,29 @@ function runTests() {
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('fails on whitespace-only rule file', () => {
|
||||
const testDir = createTestDir();
|
||||
fs.writeFileSync(path.join(testDir, 'blank.md'), ' \n\t\n ');
|
||||
|
||||
const result = runValidatorWithDir('validate-rules', 'RULES_DIR', testDir);
|
||||
assert.strictEqual(result.code, 1, 'Should reject whitespace-only rule file');
|
||||
assert.ok(result.stderr.includes('Empty'), 'Should report empty file');
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('validates rules in subdirectories recursively', () => {
|
||||
const testDir = createTestDir();
|
||||
const subDir = path.join(testDir, 'sub');
|
||||
fs.mkdirSync(subDir);
|
||||
fs.writeFileSync(path.join(testDir, 'top.md'), '# Top Level Rule');
|
||||
fs.writeFileSync(path.join(subDir, 'nested.md'), '# Nested Rule');
|
||||
|
||||
const result = runValidatorWithDir('validate-rules', 'RULES_DIR', testDir);
|
||||
assert.strictEqual(result.code, 0, 'Should validate nested rules');
|
||||
assert.ok(result.stdout.includes('Validated 2'), 'Should find both rules');
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
// Summary
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
|
||||
@@ -282,6 +282,30 @@ function runTests() {
|
||||
assert.strictEqual(result.success, false);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects rename to empty string', () => {
|
||||
resetAliases();
|
||||
aliases.setAlias('valid', '/path');
|
||||
const result = aliases.renameAlias('valid', '');
|
||||
assert.strictEqual(result.success, false);
|
||||
assert.ok(result.error.includes('empty'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects rename to reserved name', () => {
|
||||
resetAliases();
|
||||
aliases.setAlias('valid', '/path');
|
||||
const result = aliases.renameAlias('valid', 'list');
|
||||
assert.strictEqual(result.success, false);
|
||||
assert.ok(result.error.includes('reserved'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects rename to name exceeding 128 chars', () => {
|
||||
resetAliases();
|
||||
aliases.setAlias('valid', '/path');
|
||||
const result = aliases.renameAlias('valid', 'a'.repeat(129));
|
||||
assert.strictEqual(result.success, false);
|
||||
assert.ok(result.error.includes('128'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
// updateAliasTitle tests
|
||||
console.log('\nupdateAliasTitle:');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user