fix
This commit is contained in:
commit
b639155ec6
14
.github/copilot-instructions.md
vendored
14
.github/copilot-instructions.md
vendored
@ -40,14 +40,12 @@ The following instructions are only to be applied when performing a code review.
|
||||
* [ ] Encourage the use of `tools`, but it's not required.
|
||||
* [ ] Strongly encourage the use of `model` to specify the model that the chat mode is optimised for.
|
||||
|
||||
|
||||
## Branching Policy
|
||||
|
||||
- Always create a new branch for each task, feature, or fix.
|
||||
- Use the following naming conventions:
|
||||
- `feature/<short-description>`
|
||||
- `bugfix/<short-description>`
|
||||
- `task/<short-description>`
|
||||
- Never commit changes directly to the `main` or default branch.
|
||||
- After completing changes, push the branch and open a pull request for review and merging.
|
||||
* [ ] Always create a new branch for each task or issue you are working on.
|
||||
* [ ] Use descriptive branch names following the convention: `feature/description`, `fix/description`, or `docs/description`.
|
||||
* [ ] Never commit directly to the `main` branch.
|
||||
* [ ] Always open a pull request for code changes, even for small updates.
|
||||
* [ ] Ensure your branch is up to date with `main` before opening a pull request.
|
||||
* [ ] Delete the branch after the pull request is merged.
|
||||
|
||||
|
||||
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
@ -1,11 +1,14 @@
|
||||
{
|
||||
"chat.modeFilesLocations": {
|
||||
"chatmodes": true
|
||||
"chatmodes": true,
|
||||
".github/chatmodes": true
|
||||
},
|
||||
"chat.promptFilesLocations": {
|
||||
"prompts": true
|
||||
"prompts": true,
|
||||
".github/prompts": true
|
||||
},
|
||||
"chat.instructionsFilesLocations": {
|
||||
"instructions": true
|
||||
"instructions": true,
|
||||
".github/instructions": true
|
||||
}
|
||||
}
|
||||
@ -101,34 +101,37 @@ async function applyConfig(configPath = "awesome-copilot.config.yml") {
|
||||
};
|
||||
|
||||
// Import config manager for effective state computation
|
||||
const { computeEffectiveItemStates } = require("./config-manager");
|
||||
const { getEffectivelyEnabledItems } = require("./config-manager");
|
||||
|
||||
// Compute effective states using precedence rules
|
||||
const effectiveStates = computeEffectiveItemStates(config);
|
||||
// Get precomputed sets of effectively enabled items for O(1) performance
|
||||
const effectivelyEnabledSets = getEffectivelyEnabledItems(config);
|
||||
|
||||
// Create sets of effectively enabled items for performance
|
||||
const effectivelyEnabledSets = {
|
||||
prompts: new Set(),
|
||||
instructions: new Set(),
|
||||
chatmodes: new Set()
|
||||
};
|
||||
|
||||
for (const section of ["prompts", "instructions", "chatmodes"]) {
|
||||
for (const [itemName, state] of Object.entries(effectiveStates[section])) {
|
||||
if (state.enabled) {
|
||||
effectivelyEnabledSets[section].add(itemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Count enabled collections for summary
|
||||
// Count effectively enabled collections for summary
|
||||
// A collection is effectively enabled if it contributes any enabled items
|
||||
if (config.collections) {
|
||||
for (const [collectionName, enabled] of Object.entries(config.collections)) {
|
||||
if (enabled) {
|
||||
for (const [collectionName, configEnabled] of Object.entries(config.collections)) {
|
||||
if (configEnabled) {
|
||||
const collectionPath = path.join(rootDir, "collections", `${collectionName}.collection.yml`);
|
||||
if (fs.existsSync(collectionPath)) {
|
||||
const collection = parseCollectionYaml(collectionPath);
|
||||
if (collection && collection.items) {
|
||||
// Check if this collection contributes any effectively enabled items
|
||||
let hasEnabledItems = false;
|
||||
for (const item of collection.items) {
|
||||
const itemName = path.basename(item.path).replace(/\.(prompt|instructions|chatmode)\.md$/, '');
|
||||
if (item.kind === "prompt" && effectivelyEnabledSets.prompts.has(itemName)) {
|
||||
hasEnabledItems = true;
|
||||
break;
|
||||
} else if (item.kind === "instruction" && effectivelyEnabledSets.instructions.has(itemName)) {
|
||||
hasEnabledItems = true;
|
||||
break;
|
||||
} else if (item.kind === "chat-mode" && effectivelyEnabledSets.chatmodes.has(itemName)) {
|
||||
hasEnabledItems = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasEnabledItems) {
|
||||
summary.collections++;
|
||||
console.log(`✓ Enabled collection: ${collectionName} (${collection.items.length} items)`);
|
||||
}
|
||||
@ -136,6 +139,7 @@ async function applyConfig(configPath = "awesome-copilot.config.yml") {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up files that are no longer enabled (requirement #3: Toggling instructions off will remove them)
|
||||
const cleanupSummary = cleanupDisabledFiles(outputDir, effectivelyEnabledSets, rootDir);
|
||||
|
||||
@ -149,8 +149,16 @@ function handleListCommand(rawArgs) {
|
||||
const availableItems = getAllAvailableItems(section);
|
||||
|
||||
// Count effectively enabled items
|
||||
const effectivelyEnabled = Object.values(effectiveStates[section] || {})
|
||||
let effectivelyEnabled;
|
||||
if (section === "collections") {
|
||||
// For collections, count explicitly enabled ones
|
||||
effectivelyEnabled = Object.values(sanitizedConfig[section] || {})
|
||||
.filter(value => value === true).length;
|
||||
} else {
|
||||
// For other sections, count effectively enabled items
|
||||
effectivelyEnabled = Object.values(effectiveStates[section] || {})
|
||||
.filter(state => state.enabled).length;
|
||||
}
|
||||
|
||||
const { totalCharacters } = calculateSectionFootprint(section, sanitizedConfig[section]);
|
||||
const headingParts = [
|
||||
@ -170,20 +178,40 @@ function handleListCommand(rawArgs) {
|
||||
|
||||
// Show items with effective state and reason
|
||||
if (section === "collections") {
|
||||
// Collections show simple enabled/disabled
|
||||
// Collections show simple enabled/disabled with count of effectively enabled items
|
||||
availableItems.forEach(itemName => {
|
||||
const isEnabled = Boolean(sanitizedConfig[section]?.[itemName]);
|
||||
console.log(` [${isEnabled ? "✓" : " "}] ${itemName}`);
|
||||
|
||||
// Count how many items this collection would enable
|
||||
let enabledCount = 0;
|
||||
if (isEnabled) {
|
||||
// Simulate what would happen if only this collection was enabled
|
||||
const testConfig = { collections: { [itemName]: true } };
|
||||
const testEffectiveStates = computeEffectiveItemStates(testConfig);
|
||||
|
||||
for (const sectionName of ["prompts", "instructions", "chatmodes"]) {
|
||||
enabledCount += Object.values(testEffectiveStates[sectionName] || {})
|
||||
.filter(state => state.enabled && state.reason === "collection").length;
|
||||
}
|
||||
}
|
||||
|
||||
const countText = isEnabled ? ` (${enabledCount} items effectively enabled)` : "";
|
||||
console.log(` [${isEnabled ? "✓" : " "}] ${itemName}${countText}`);
|
||||
});
|
||||
} else {
|
||||
// Other sections show effective state with reason
|
||||
// Other sections show effective state with detailed reason
|
||||
availableItems.forEach(itemName => {
|
||||
const effectiveState = effectiveStates[section]?.[itemName];
|
||||
if (effectiveState) {
|
||||
const symbol = effectiveState.enabled ? "✓" : " ";
|
||||
const reasonText = effectiveState.reason === "explicit"
|
||||
? ` (${effectiveState.reason})`
|
||||
: effectiveState.enabled ? ` (${effectiveState.reason})` : "";
|
||||
let reasonText = "";
|
||||
|
||||
if (effectiveState.reason === "explicit") {
|
||||
reasonText = ` (explicit:${effectiveState.enabled})`;
|
||||
} else if (effectiveState.reason === "collection" && effectiveState.collections && effectiveState.collections.length > 0) {
|
||||
reasonText = ` (via:[${effectiveState.collections.join(',')}])`;
|
||||
}
|
||||
|
||||
console.log(` [${symbol}] ${itemName}${reasonText}`);
|
||||
} else {
|
||||
console.log(` [ ] ${itemName}`);
|
||||
|
||||
@ -101,6 +101,11 @@ function toBoolean(value) {
|
||||
if (normalized === "false") return false;
|
||||
}
|
||||
|
||||
// Preserve undefined as undefined for "no explicit override"
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Boolean(value);
|
||||
}
|
||||
|
||||
@ -185,11 +190,17 @@ function generateConfigHash(config) {
|
||||
* Compute effective item states respecting explicit overrides over collections
|
||||
*
|
||||
* This function builds membership maps per section and returns effectively enabled items with reasons.
|
||||
* It uses the following precedence rules:
|
||||
* 1. Explicit true/false overrides everything (highest priority)
|
||||
* It uses strict comparisons to ensure undefined values are never treated as explicitly disabled.
|
||||
*
|
||||
* Precedence rules with strict undefined handling:
|
||||
* 1. Explicit true/false overrides everything (highest priority) - uses strict === comparisons
|
||||
* 2. If undefined and enabled by collection, use true
|
||||
* 3. Otherwise, use false (disabled)
|
||||
*
|
||||
* CRITICAL: Only values that are strictly === false are treated as explicitly disabled.
|
||||
* undefined, null, 0, '', or other falsy values are NOT treated as explicit disabling.
|
||||
* This allows collections to enable items that are not explicitly configured.
|
||||
*
|
||||
* @param {Object} config - Configuration object with sections
|
||||
* @returns {Object} Effective states for each section with { itemName: { enabled: boolean, reason: string } }
|
||||
* Reason can be: 'explicit', 'collection', or 'disabled'
|
||||
@ -203,14 +214,21 @@ function computeEffectiveItemStates(config) {
|
||||
chatmodes: {}
|
||||
};
|
||||
|
||||
// Build membership maps: Map<itemName, Set<collectionName>> per section for O(1) lookups
|
||||
// Build detailed membership maps: Map<itemName, Set<collectionName>> per section
|
||||
const collectionMemberships = {
|
||||
prompts: new Map(),
|
||||
instructions: new Map(),
|
||||
chatmodes: new Map()
|
||||
};
|
||||
|
||||
// Build simple enabled sets for O(1) lookups
|
||||
const collectionEnabledItems = {
|
||||
prompts: new Set(),
|
||||
instructions: new Set(),
|
||||
chatmodes: new Set()
|
||||
};
|
||||
|
||||
// Identify enabled collections per section
|
||||
// Identify enabled collections per section and track memberships
|
||||
if (config.collections) {
|
||||
for (const [collectionName, enabled] of Object.entries(config.collections)) {
|
||||
if (enabled === true) {
|
||||
@ -222,12 +240,24 @@ function computeEffectiveItemStates(config) {
|
||||
// Extract item name from path - remove directory and all extensions
|
||||
const itemName = path.basename(item.path).replace(/\.(prompt|instructions|chatmode)\.md$/, '');
|
||||
|
||||
let sectionName;
|
||||
if (item.kind === "prompt") {
|
||||
collectionEnabledItems.prompts.add(itemName);
|
||||
sectionName = "prompts";
|
||||
} else if (item.kind === "instruction") {
|
||||
collectionEnabledItems.instructions.add(itemName);
|
||||
sectionName = "instructions";
|
||||
} else if (item.kind === "chat-mode") {
|
||||
collectionEnabledItems.chatmodes.add(itemName);
|
||||
sectionName = "chatmodes";
|
||||
}
|
||||
|
||||
if (sectionName) {
|
||||
// Track which collections enable this item
|
||||
if (!collectionMemberships[sectionName].has(itemName)) {
|
||||
collectionMemberships[sectionName].set(itemName, new Set());
|
||||
}
|
||||
collectionMemberships[sectionName].get(itemName).add(collectionName);
|
||||
|
||||
// Add to enabled set for O(1) lookups
|
||||
collectionEnabledItems[sectionName].add(itemName);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -247,27 +277,35 @@ function computeEffectiveItemStates(config) {
|
||||
for (const itemName of availableItems) {
|
||||
const explicitValue = sectionConfig[itemName];
|
||||
const isEnabledByCollection = collectionEnabled.has(itemName);
|
||||
const enablingCollections = collectionMemberships[section].get(itemName) || new Set();
|
||||
|
||||
// Precedence rules:
|
||||
// 1. If explicitly set to true or false, use that value
|
||||
// Precedence rules with strict undefined handling:
|
||||
// 1. If explicitly set to true or false, use that value (highest priority)
|
||||
// 2. If undefined and enabled by collection, use true
|
||||
// 3. Otherwise, use false
|
||||
// 3. Otherwise, use false (disabled)
|
||||
//
|
||||
// IMPORTANT: Only strict === false comparisons are used to determine explicit disabling.
|
||||
// undefined values are NEVER treated as explicitly disabled, allowing collections to enable them.
|
||||
|
||||
let enabled = false;
|
||||
let reason = "disabled";
|
||||
let collections = [];
|
||||
|
||||
if (explicitValue === true) {
|
||||
enabled = true;
|
||||
reason = "explicit";
|
||||
} else if (explicitValue === false) {
|
||||
// Strict comparison ensures only explicit false disables items
|
||||
enabled = false;
|
||||
reason = "explicit";
|
||||
} else if (explicitValue === undefined && isEnabledByCollection) {
|
||||
// undefined values can be enabled by collections (not treated as disabled)
|
||||
enabled = true;
|
||||
reason = "collection";
|
||||
collections = Array.from(enablingCollections).sort();
|
||||
}
|
||||
|
||||
effectiveStates[section][itemName] = { enabled, reason };
|
||||
effectiveStates[section][itemName] = { enabled, reason, collections };
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,6 +341,93 @@ function getEffectivelyEnabledItems(config) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle a collection's enabled state without modifying individual item flags
|
||||
*
|
||||
* This function implements the core requirement from TASK-003:
|
||||
* - Only modifies the collection's enabled flag
|
||||
* - Never writes to per-item flags (e.g., config.prompts[item] = enabled)
|
||||
* - Returns summary information for CLI feedback
|
||||
* - Preserves all existing explicit per-item overrides
|
||||
*
|
||||
* @param {Object} config - Configuration object with collections section
|
||||
* @param {string} name - Collection name to toggle
|
||||
* @param {boolean} enabled - Desired enabled state for the collection
|
||||
* @returns {Object} Summary object with delta information for CLI feedback
|
||||
*/
|
||||
function toggleCollection(config, name, enabled) {
|
||||
// Validate inputs
|
||||
if (!config || typeof config !== 'object') {
|
||||
throw new Error('Config object is required');
|
||||
}
|
||||
if (!name || typeof name !== 'string') {
|
||||
throw new Error('Collection name is required');
|
||||
}
|
||||
if (typeof enabled !== 'boolean') {
|
||||
throw new Error('Enabled state must be a boolean');
|
||||
}
|
||||
|
||||
// Ensure collections section exists
|
||||
if (!config.collections) {
|
||||
config.collections = {};
|
||||
}
|
||||
|
||||
// Get current state
|
||||
const currentState = Boolean(config.collections[name]);
|
||||
|
||||
// Check if collection exists (has a .collection.yml file)
|
||||
const collectionPath = path.join(__dirname, "collections", `${name}.collection.yml`);
|
||||
if (!fs.existsSync(collectionPath)) {
|
||||
throw new Error(`Collection '${name}' does not exist`);
|
||||
}
|
||||
|
||||
// If state is already the desired state, return early
|
||||
if (currentState === enabled) {
|
||||
return {
|
||||
changed: false,
|
||||
collectionName: name,
|
||||
currentState: currentState,
|
||||
newState: enabled,
|
||||
delta: { enabled: [], disabled: [] },
|
||||
message: `Collection '${name}' is already ${enabled ? 'enabled' : 'disabled'}.`
|
||||
};
|
||||
}
|
||||
|
||||
// Compute effective states before the change
|
||||
const effectiveStatesBefore = computeEffectiveItemStates(config);
|
||||
|
||||
// CORE REQUIREMENT: Only modify the collection's enabled flag
|
||||
// Never write to per-item flags (config.prompts[item] = enabled)
|
||||
config.collections[name] = enabled;
|
||||
|
||||
// Compute effective states after the change
|
||||
const effectiveStatesAfter = computeEffectiveItemStates(config);
|
||||
|
||||
// Calculate delta summary for CLI feedback
|
||||
const delta = { enabled: [], disabled: [] };
|
||||
for (const sectionName of ["prompts", "instructions", "chatmodes"]) {
|
||||
for (const item of getAllAvailableItems(sectionName)) {
|
||||
const beforeState = effectiveStatesBefore[sectionName]?.[item]?.enabled || false;
|
||||
const afterState = effectiveStatesAfter[sectionName]?.[item]?.enabled || false;
|
||||
|
||||
if (!beforeState && afterState) {
|
||||
delta.enabled.push(`${sectionName}/${item}`);
|
||||
} else if (beforeState && !afterState) {
|
||||
delta.disabled.push(`${sectionName}/${item}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
changed: true,
|
||||
collectionName: name,
|
||||
currentState: currentState,
|
||||
newState: enabled,
|
||||
delta,
|
||||
message: `${enabled ? 'Enabled' : 'Disabled'} collection '${name}'.`
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DEFAULT_CONFIG_PATH,
|
||||
CONFIG_SECTIONS,
|
||||
@ -316,5 +441,6 @@ module.exports = {
|
||||
getAllAvailableItems,
|
||||
computeEffectiveItemStates,
|
||||
getEffectivelyEnabledItems,
|
||||
generateConfigHash
|
||||
generateConfigHash,
|
||||
toggleCollection
|
||||
};
|
||||
|
||||
13
test-all.js
13
test-all.js
@ -8,6 +8,7 @@ const { runTests: runUnitTests } = require('./test-effective-states');
|
||||
const { runTests: runIntegrationTests } = require('./test-integration');
|
||||
const { runTests: runCliTests } = require('./test-cli');
|
||||
const { runTests: runApplyTests } = require('./test-apply-effective');
|
||||
const { runTests: runToggleCollectionTests } = require('./test-toggle-collection');
|
||||
|
||||
async function runAllTests() {
|
||||
console.log('🧪 Running Awesome Copilot Comprehensive Test Suite\n');
|
||||
@ -17,7 +18,8 @@ async function runAllTests() {
|
||||
unit: false,
|
||||
integration: false,
|
||||
cli: false,
|
||||
apply: false
|
||||
apply: false,
|
||||
toggleCollection: false
|
||||
};
|
||||
|
||||
try {
|
||||
@ -52,6 +54,14 @@ async function runAllTests() {
|
||||
console.error('Apply tests failed with error:', error.message);
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('\n🔧 Toggle Collection Tests (TASK-003)');
|
||||
console.log('-'.repeat(36));
|
||||
results.toggleCollection = await runToggleCollectionTests();
|
||||
} catch (error) {
|
||||
console.error('Toggle collection tests failed with error:', error.message);
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('\n🤖 Repository Instructions Tests');
|
||||
console.log('-'.repeat(33));
|
||||
@ -71,6 +81,7 @@ async function runAllTests() {
|
||||
{ name: 'Integration Tests', result: results.integration, emoji: '🔄' },
|
||||
{ name: 'CLI Tests', result: results.cli, emoji: '⌨️' },
|
||||
{ name: 'Apply Tests', result: results.apply, emoji: '🎯' },
|
||||
{ name: 'Toggle Collection', result: results.toggleCollection, emoji: '🔧' },
|
||||
{ name: 'Repo Instructions', result: results.repoInstructions, emoji: '🤖' }
|
||||
];
|
||||
|
||||
|
||||
207
test-cli.js
207
test-cli.js
@ -92,7 +92,7 @@ async function runTests() {
|
||||
|
||||
const result = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(result.success, 'List should succeed');
|
||||
assert(result.stdout.includes('(collection)'), 'Should show collection reason');
|
||||
assert(result.stdout.includes('(via:[testing-automation])'), 'Should show collection reason');
|
||||
assert(result.stdout.includes('[✓]'), 'Should show enabled items');
|
||||
});
|
||||
|
||||
@ -105,7 +105,7 @@ async function runTests() {
|
||||
assert(result.success, 'Individual toggle should succeed');
|
||||
|
||||
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit)'),
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit:false)'),
|
||||
'Explicitly disabled item should show explicit reason');
|
||||
});
|
||||
|
||||
@ -128,6 +128,209 @@ async function runTests() {
|
||||
assert(result.stdout.includes('already enabled'), 'Should indicate no change needed');
|
||||
});
|
||||
|
||||
// Test 8: Multiple collections effective states
|
||||
await test("Multiple collections effective states", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
|
||||
// Enable two collections with potential overlap
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle collections csharp-dotnet-development on --config ${TEST_CONFIG}`);
|
||||
|
||||
const result = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(result.success, 'List should succeed');
|
||||
|
||||
// Should show collection reason for items enabled by collection
|
||||
assert(result.stdout.includes('(collection)'), 'Should show collection reason');
|
||||
assert(result.stdout.includes('[✓]'), 'Should show enabled items');
|
||||
|
||||
// Count should reflect enabled items from both collections
|
||||
const enabledMatch = result.stdout.match(/Prompts \((\d+)\/\d+ enabled\)/);
|
||||
assert(enabledMatch && parseInt(enabledMatch[1]) > 5, 'Should have multiple enabled prompts from collections');
|
||||
});
|
||||
|
||||
// Test 9: Explicit overrides with collection conflicts
|
||||
await test("Explicit overrides with collection conflicts", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
|
||||
// Override a collection item explicitly to off
|
||||
await runCommand(`node awesome-copilot.js toggle prompts playwright-generate-test off --config ${TEST_CONFIG}`);
|
||||
|
||||
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult.success, 'List should succeed');
|
||||
|
||||
// Should show explicit reason and disabled state
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit)'), 'Should show explicit reason');
|
||||
assert(listResult.stdout.includes('[ ] playwright-generate-test'), 'Should show as disabled despite collection');
|
||||
|
||||
// Other collection items should still show as enabled
|
||||
assert(listResult.stdout.includes('[✓] playwright-explore-website (collection)'), 'Other collection items should remain enabled');
|
||||
});
|
||||
|
||||
// Test 10: Delta summary accuracy with conflicts
|
||||
await test("Delta summary accuracy with conflicts", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
|
||||
// Enable collection
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
|
||||
// Add explicit override to disable one item
|
||||
await runCommand(`node awesome-copilot.js toggle prompts playwright-generate-test off --config ${TEST_CONFIG}`);
|
||||
|
||||
// Disable the collection - should show accurate delta excluding explicit override
|
||||
const result = await runCommand(`node awesome-copilot.js toggle collections testing-automation off --config ${TEST_CONFIG}`);
|
||||
assert(result.success, 'Toggle should succeed');
|
||||
assert(result.stdout.includes('Delta summary'), 'Should show delta summary');
|
||||
assert(result.stdout.includes('items will be disabled'), 'Should show disabled items count');
|
||||
|
||||
// Should not include the explicitly disabled item in the delta
|
||||
const lines = result.stdout.split('\n');
|
||||
const disabledItems = lines.filter(line => line.includes(' - prompts/'));
|
||||
assert(!disabledItems.some(line => line.includes('playwright-generate-test')),
|
||||
'Should not show explicitly disabled item in delta');
|
||||
});
|
||||
|
||||
// Test 11: Instructions and chatmodes effective states
|
||||
await test("Instructions and chatmodes effective states", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
|
||||
// Test instructions
|
||||
const instructionsResult = await runCommand(`node awesome-copilot.js list instructions --config ${TEST_CONFIG}`);
|
||||
assert(instructionsResult.success, 'Instructions list should succeed');
|
||||
assert(instructionsResult.stdout.includes('[✓] playwright-typescript (collection)'),
|
||||
'Instructions should show collection reason');
|
||||
|
||||
// Test chatmodes
|
||||
const chatmodesResult = await runCommand(`node awesome-copilot.js list chatmodes --config ${TEST_CONFIG}`);
|
||||
assert(chatmodesResult.success, 'Chatmodes list should succeed');
|
||||
assert(chatmodesResult.stdout.includes('[✓] tdd-red (collection)'),
|
||||
'Chatmodes should show collection reason');
|
||||
});
|
||||
|
||||
// Test 12: Collections section display
|
||||
await test("Collections section shows simple enabled/disabled", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
|
||||
const result = await runCommand(`node awesome-copilot.js list collections --config ${TEST_CONFIG}`);
|
||||
assert(result.success, 'Collections list should succeed');
|
||||
assert(result.stdout.includes('[✓] testing-automation'), 'Should show enabled collection');
|
||||
assert(result.stdout.includes('[ ] csharp-dotnet-development'), 'Should show disabled collection');
|
||||
|
||||
// Collections should not show reasons (unlike other sections)
|
||||
assert(!result.stdout.includes('(explicit)'), 'Collections should not show reason text');
|
||||
assert(!result.stdout.includes('(collection)'), 'Collections should not show reason text');
|
||||
});
|
||||
|
||||
// Test 13: Output clarity and user-friendliness
|
||||
await test("Output clarity and user-friendliness", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
|
||||
const result = await runCommand(`node awesome-copilot.js list --config ${TEST_CONFIG}`);
|
||||
assert(result.success, 'List should succeed');
|
||||
|
||||
// Should show counts (character estimates may or may not appear depending on content)
|
||||
assert(result.stdout.includes('enabled'), 'Should show enabled counts');
|
||||
|
||||
// Should show helpful usage message
|
||||
assert(result.stdout.includes("Use 'awesome-copilot toggle'"), 'Should show usage instructions');
|
||||
|
||||
// Should show clear section headers
|
||||
assert(result.stdout.includes('Prompts'), 'Should show Prompts section');
|
||||
assert(result.stdout.includes('Instructions'), 'Should show Instructions section');
|
||||
assert(result.stdout.includes('Chat Modes'), 'Should show Chat Modes section');
|
||||
assert(result.stdout.includes('Collections'), 'Should show Collections section');
|
||||
|
||||
// Should show configuration path
|
||||
assert(result.stdout.includes('Configuration:'), 'Should show configuration file path');
|
||||
});
|
||||
|
||||
// Test 14: Complex scenario with multiple overrides
|
||||
await test("Complex scenario with multiple overrides", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
|
||||
// Enable multiple collections
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle collections csharp-dotnet-development on --config ${TEST_CONFIG}`);
|
||||
|
||||
// Add explicit overrides
|
||||
await runCommand(`node awesome-copilot.js toggle prompts playwright-generate-test off --config ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle prompts create-readme on --config ${TEST_CONFIG}`);
|
||||
|
||||
const result = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(result.success, 'List should succeed');
|
||||
|
||||
// Should show mixed states with correct reasons
|
||||
assert(result.stdout.includes('[ ] playwright-generate-test (explicit)'), 'Should show explicit disable');
|
||||
assert(result.stdout.includes('[✓] create-readme (explicit)'), 'Should show explicit enable');
|
||||
assert(result.stdout.includes('(collection)'), 'Should show collection-enabled items');
|
||||
|
||||
// Count should be accurate
|
||||
const enabledMatch = result.stdout.match(/Prompts \((\d+)\/\d+ enabled\)/);
|
||||
assert(enabledMatch, 'Should show enabled count');
|
||||
|
||||
const enabledCount = parseInt(enabledMatch[1]);
|
||||
assert(enabledCount > 8, 'Should have multiple items enabled from collections and explicit');
|
||||
});
|
||||
|
||||
// Test 15: No misleading disabled messages for shared items
|
||||
await test("No misleading disabled messages for shared items", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
|
||||
// Enable a collection that has items potentially shared with other collections
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
|
||||
// Toggle collection off and check delta summary
|
||||
const result = await runCommand(`node awesome-copilot.js toggle collections testing-automation off --config ${TEST_CONFIG}`);
|
||||
assert(result.success, 'Toggle should succeed');
|
||||
|
||||
// Should show accurate delta - items should be listed as will be disabled
|
||||
// since they're not enabled by other collections in this test
|
||||
assert(result.stdout.includes('Delta summary'), 'Should show delta summary');
|
||||
assert(result.stdout.includes('items will be disabled'), 'Should show disabled items count');
|
||||
|
||||
// Verify the messaging is clear and not misleading
|
||||
const lines = result.stdout.split('\n');
|
||||
const deltaLines = lines.filter(line => line.includes('+ ') || line.includes('- '));
|
||||
assert(deltaLines.length > 0, 'Should show specific items in delta');
|
||||
});
|
||||
|
||||
// Test 16: Membership and counts verification
|
||||
await test("Membership and counts verification", async () => {
|
||||
await runCommand(`node awesome-copilot.js init ${TEST_CONFIG}`);
|
||||
|
||||
// Enable collection and add explicit overrides
|
||||
await runCommand(`node awesome-copilot.js toggle collections testing-automation on --config ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle prompts playwright-generate-test off --config ${TEST_CONFIG}`);
|
||||
await runCommand(`node awesome-copilot.js toggle prompts create-readme on --config ${TEST_CONFIG}`);
|
||||
|
||||
// Get all section results
|
||||
const promptsResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
const instructionsResult = await runCommand(`node awesome-copilot.js list instructions --config ${TEST_CONFIG}`);
|
||||
const chatmodesResult = await runCommand(`node awesome-copilot.js list chatmodes --config ${TEST_CONFIG}`);
|
||||
|
||||
// Verify counts are accurate and consistent
|
||||
const promptsMatch = promptsResult.stdout.match(/Prompts \((\d+)\/(\d+) enabled\)/);
|
||||
const instructionsMatch = instructionsResult.stdout.match(/Instructions \((\d+)\/(\d+) enabled\)/);
|
||||
const chatmodesMatch = chatmodesResult.stdout.match(/Chat Modes \((\d+)\/(\d+) enabled\)/);
|
||||
|
||||
assert(promptsMatch, 'Should show prompts count');
|
||||
assert(instructionsMatch, 'Should show instructions count');
|
||||
assert(chatmodesMatch, 'Should show chatmodes count');
|
||||
|
||||
// Counts should be reasonable for testing-automation collection
|
||||
assert(parseInt(promptsMatch[1]) >= 4, 'Should have reasonable prompts enabled');
|
||||
assert(parseInt(instructionsMatch[1]) >= 2, 'Should have reasonable instructions enabled');
|
||||
assert(parseInt(chatmodesMatch[1]) >= 3, 'Should have reasonable chatmodes enabled');
|
||||
|
||||
// Total items should be consistent
|
||||
assert(parseInt(promptsMatch[2]) > 80, 'Should show total prompts available');
|
||||
assert(parseInt(instructionsMatch[2]) > 70, 'Should show total instructions available');
|
||||
assert(parseInt(chatmodesMatch[2]) > 50, 'Should show total chatmodes available');
|
||||
});
|
||||
|
||||
console.log(`\nCLI Test Results: ${passedTests}/${totalTests} passed`);
|
||||
|
||||
cleanup(); // Final cleanup
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
# Awesome Copilot Configuration File
|
||||
# Manual test for effective state computation
|
||||
#
|
||||
# Testing precedence rules with undefined values
|
||||
|
||||
version: "1.0"
|
||||
project:
|
||||
name: "Test Project"
|
||||
description: "Testing effective state precedence"
|
||||
output_directory: ".github"
|
||||
collections:
|
||||
testing-automation: false
|
||||
prompts:
|
||||
ai-prompt-engineering-safety-review: false
|
||||
playwright-generate-test: true
|
||||
instructions:
|
||||
chatmodes:
|
||||
@ -164,7 +164,50 @@ function runTests() {
|
||||
'Chat mode should be enabled by collection');
|
||||
});
|
||||
|
||||
// Test 8: getEffectivelyEnabledItems returns Sets format
|
||||
// Test 9: TASK-006 - Strict false checks prevent undefined treated as disabled
|
||||
test("TASK-006: Strict false checks prevent undefined treated as disabled", () => {
|
||||
const config = {
|
||||
prompts: {
|
||||
'explicit-false-item': false,
|
||||
'explicit-true-item': true,
|
||||
// 'undefined-item' is undefined (not set)
|
||||
},
|
||||
collections: {
|
||||
'testing-automation': true
|
||||
}
|
||||
};
|
||||
const result = computeEffectiveItemStates(config);
|
||||
|
||||
// Explicit false should be disabled with reason 'explicit'
|
||||
const explicitFalse = result.prompts['explicit-false-item'];
|
||||
if (explicitFalse) {
|
||||
assert(explicitFalse.reason === 'explicit' && !explicitFalse.enabled,
|
||||
'Items with explicit false should be disabled with reason explicit');
|
||||
}
|
||||
|
||||
// Explicit true should be enabled with reason 'explicit'
|
||||
const explicitTrue = result.prompts['explicit-true-item'];
|
||||
if (explicitTrue) {
|
||||
assert(explicitTrue.reason === 'explicit' && explicitTrue.enabled,
|
||||
'Items with explicit true should be enabled with reason explicit');
|
||||
}
|
||||
|
||||
// Undefined item in collection should be enabled with reason 'collection'
|
||||
const undefinedInCollection = result.prompts['playwright-generate-test'];
|
||||
if (undefinedInCollection) {
|
||||
assert(undefinedInCollection.reason === 'collection' && undefinedInCollection.enabled,
|
||||
'Undefined items should be enabled by collections, not treated as explicitly disabled');
|
||||
}
|
||||
|
||||
// Undefined item NOT in collection should be disabled with reason 'disabled' (not 'explicit')
|
||||
const undefinedNotInCollection = result.prompts['some-random-item-not-in-any-collection'];
|
||||
if (undefinedNotInCollection) {
|
||||
assert(undefinedNotInCollection.reason === 'disabled' && !undefinedNotInCollection.enabled,
|
||||
'Undefined items not in collections should have reason disabled, not explicit');
|
||||
}
|
||||
});
|
||||
|
||||
// Test 10: getEffectivelyEnabledItems returns Sets format
|
||||
test("getEffectivelyEnabledItems returns Sets format", () => {
|
||||
const config = {
|
||||
prompts: {
|
||||
@ -214,6 +257,37 @@ function runTests() {
|
||||
assert(result.prompts.size > 0, 'Should have enabled prompts');
|
||||
});
|
||||
|
||||
// Test 10: Undefined values are not treated as explicitly disabled (TASK-004)
|
||||
test("Undefined values are not treated as explicitly disabled", () => {
|
||||
const config = {
|
||||
prompts: {
|
||||
'playwright-generate-test': true, // explicit true
|
||||
'csharp-nunit': false, // explicit false
|
||||
// 'playwright-explore-website' is undefined (not mentioned)
|
||||
},
|
||||
collections: {
|
||||
'testing-automation': true
|
||||
}
|
||||
};
|
||||
|
||||
const result = computeEffectiveItemStates(config);
|
||||
|
||||
// Explicit true should be explicit
|
||||
const explicitTrue = result.prompts['playwright-generate-test'];
|
||||
assert(explicitTrue && explicitTrue.enabled && explicitTrue.reason === 'explicit',
|
||||
'Explicit true should be enabled with explicit reason');
|
||||
|
||||
// Explicit false should be explicit (strict === false comparison)
|
||||
const explicitFalse = result.prompts['csharp-nunit'];
|
||||
assert(explicitFalse && !explicitFalse.enabled && explicitFalse.reason === 'explicit',
|
||||
'Explicit false should be disabled with explicit reason');
|
||||
|
||||
// Undefined should inherit from collection
|
||||
const undefinedItem = result.prompts['playwright-explore-website'];
|
||||
assert(undefinedItem && undefinedItem.enabled && undefinedItem.reason === 'collection',
|
||||
'Undefined items should inherit from collection, not be treated as explicitly disabled');
|
||||
});
|
||||
|
||||
console.log(`\nTest Results: ${passedTests}/${totalTests} passed`);
|
||||
|
||||
if (passedTests === totalTests) {
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
# Awesome Copilot Configuration File
|
||||
# Generated on 2025-09-21T22:44:51.675Z
|
||||
#
|
||||
# This file uses effective state precedence:
|
||||
# 1. Explicit item settings (true/false) override everything
|
||||
# 2. Items not listed inherit from enabled collections
|
||||
# 3. Otherwise items are disabled
|
||||
#
|
||||
# To use:
|
||||
# - Enable collections for curated sets of related items
|
||||
# - Explicitly set individual items to true/false to override collections
|
||||
# - Items not mentioned will follow collection settings
|
||||
#
|
||||
# After configuring, run: awesome-copilot apply
|
||||
#
|
||||
|
||||
version: "1.0"
|
||||
project:
|
||||
name: "My Project"
|
||||
description: "A project using awesome-copilot customizations"
|
||||
output_directory: ".github"
|
||||
prompts:
|
||||
playwright-generate-test: false
|
||||
instructions:
|
||||
chatmodes:
|
||||
collections:
|
||||
azure-cloud-development: false
|
||||
csharp-dotnet-development: false
|
||||
database-data-management: false
|
||||
devops-oncall: false
|
||||
frontend-web-dev: false
|
||||
project-planning: false
|
||||
security-best-practices: false
|
||||
technical-spike: false
|
||||
testing-automation: true
|
||||
@ -119,14 +119,14 @@ async function runTests() {
|
||||
|
||||
// Check it's explicitly disabled
|
||||
const listResult1 = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult1.stdout.includes('create-readme (explicit)'), 'Should show explicit disabled');
|
||||
assert(listResult1.stdout.includes('create-readme (explicit:false)'), 'Should show explicit disabled');
|
||||
|
||||
// Force enable all with --all flag
|
||||
await runCommand(`node awesome-copilot.js toggle prompts all on --all --config ${TEST_CONFIG}`);
|
||||
|
||||
// Check it's now explicitly enabled
|
||||
const listResult2 = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult2.stdout.includes('create-readme (explicit)') && listResult2.stdout.includes('[✓]'), 'Should be explicitly enabled');
|
||||
assert(listResult2.stdout.includes('create-readme (explicit:true)') && listResult2.stdout.includes('[✓]'), 'Should be explicitly enabled');
|
||||
});
|
||||
|
||||
// Test 4: File cleanup on disable
|
||||
@ -180,7 +180,7 @@ async function runTests() {
|
||||
|
||||
// Double-check with list command
|
||||
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit)'), "'playwright-generate-test (explicit)' should be present in the list output");
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit:false)'), "'playwright-generate-test (explicit:false)' should be present in the list output");
|
||||
assert(!listResult.stdout.includes('[✓] playwright-generate-test'), "'[✓] playwright-generate-test' should NOT be present in the list output (should remain explicitly disabled)");
|
||||
});
|
||||
|
||||
|
||||
194
test-toggle-collection.js
Normal file
194
test-toggle-collection.js
Normal file
@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Unit tests for toggleCollection function
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const { toggleCollection, computeEffectiveItemStates } = require('./config-manager');
|
||||
|
||||
// Change to project directory for tests
|
||||
process.chdir(__dirname);
|
||||
|
||||
function assert(condition, message) {
|
||||
if (!condition) {
|
||||
throw new Error(`Assertion failed: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
let totalTests = 0;
|
||||
let passedTests = 0;
|
||||
|
||||
function test(name, testFn) {
|
||||
totalTests++;
|
||||
try {
|
||||
testFn();
|
||||
console.log(`✅ ${name}`);
|
||||
passedTests++;
|
||||
} catch (error) {
|
||||
console.log(`❌ ${name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Running unit tests for toggleCollection function...\n");
|
||||
|
||||
// Test 1: Toggle collection from false to true
|
||||
test("Toggle collection from false to true", () => {
|
||||
const config = {
|
||||
collections: {
|
||||
'testing-automation': false
|
||||
}
|
||||
};
|
||||
|
||||
const result = toggleCollection(config, 'testing-automation', true);
|
||||
|
||||
assert(result.changed === true, 'Should indicate change occurred');
|
||||
assert(result.collectionName === 'testing-automation', 'Should return correct collection name');
|
||||
assert(result.currentState === false, 'Should show previous state as false');
|
||||
assert(result.newState === true, 'Should show new state as true');
|
||||
assert(config.collections['testing-automation'] === true, 'Config should be updated');
|
||||
assert(result.delta.enabled.length > 0, 'Should show items being enabled');
|
||||
});
|
||||
|
||||
// Test 2: Toggle collection from true to false
|
||||
test("Toggle collection from true to false", () => {
|
||||
const config = {
|
||||
collections: {
|
||||
'testing-automation': true
|
||||
}
|
||||
};
|
||||
|
||||
const result = toggleCollection(config, 'testing-automation', false);
|
||||
|
||||
assert(result.changed === true, 'Should indicate change occurred');
|
||||
assert(result.newState === false, 'Should show new state as false');
|
||||
assert(config.collections['testing-automation'] === false, 'Config should be updated');
|
||||
assert(result.delta.disabled.length > 0, 'Should show items being disabled');
|
||||
});
|
||||
|
||||
// Test 3: Toggle collection to same state (no change)
|
||||
test("Toggle collection to same state (no change)", () => {
|
||||
const config = {
|
||||
collections: {
|
||||
'testing-automation': true
|
||||
}
|
||||
};
|
||||
|
||||
const result = toggleCollection(config, 'testing-automation', true);
|
||||
|
||||
assert(result.changed === false, 'Should indicate no change occurred');
|
||||
assert(result.message.includes('already enabled'), 'Should indicate already enabled');
|
||||
});
|
||||
|
||||
// Test 4: Preserves explicit overrides
|
||||
test("Preserves explicit overrides", () => {
|
||||
const config = {
|
||||
prompts: {
|
||||
'playwright-generate-test': false // Explicit override
|
||||
},
|
||||
collections: {
|
||||
'testing-automation': false
|
||||
}
|
||||
};
|
||||
|
||||
// Enable collection
|
||||
const result = toggleCollection(config, 'testing-automation', true);
|
||||
|
||||
// Verify the explicit override is preserved
|
||||
assert(config.prompts['playwright-generate-test'] === false, 'Explicit override should be preserved');
|
||||
assert(config.collections['testing-automation'] === true, 'Collection should be enabled');
|
||||
|
||||
// Check that the overridden item is not in the enabled delta
|
||||
const hasOverriddenItem = result.delta.enabled.some(item => item.includes('playwright-generate-test'));
|
||||
assert(!hasOverriddenItem, 'Explicitly disabled item should not appear in enabled delta');
|
||||
});
|
||||
|
||||
// Test 5: Only modifies collection flag, never individual items
|
||||
test("Only modifies collection flag, never individual items", () => {
|
||||
const config = {
|
||||
prompts: {},
|
||||
instructions: {},
|
||||
chatmodes: {},
|
||||
collections: {
|
||||
'testing-automation': false
|
||||
}
|
||||
};
|
||||
|
||||
const originalPrompts = { ...config.prompts };
|
||||
const originalInstructions = { ...config.instructions };
|
||||
const originalChatmodes = { ...config.chatmodes };
|
||||
|
||||
toggleCollection(config, 'testing-automation', true);
|
||||
|
||||
// Verify individual sections were not modified
|
||||
assert(JSON.stringify(config.prompts) === JSON.stringify(originalPrompts), 'Prompts section should not be modified');
|
||||
assert(JSON.stringify(config.instructions) === JSON.stringify(originalInstructions), 'Instructions section should not be modified');
|
||||
assert(JSON.stringify(config.chatmodes) === JSON.stringify(originalChatmodes), 'Chatmodes section should not be modified');
|
||||
|
||||
// Only collections should be modified
|
||||
assert(config.collections['testing-automation'] === true, 'Only collection flag should be modified');
|
||||
});
|
||||
|
||||
// Test 6: Error handling for invalid inputs
|
||||
test("Error handling for invalid inputs", () => {
|
||||
let errorThrown = false;
|
||||
|
||||
try {
|
||||
toggleCollection(null, 'test', true);
|
||||
} catch (error) {
|
||||
errorThrown = true;
|
||||
assert(error.message.includes('Config object is required'), 'Should require config object');
|
||||
}
|
||||
assert(errorThrown, 'Should throw error for null config');
|
||||
|
||||
errorThrown = false;
|
||||
try {
|
||||
toggleCollection({}, '', true);
|
||||
} catch (error) {
|
||||
errorThrown = true;
|
||||
assert(error.message.includes('Collection name is required'), 'Should require collection name');
|
||||
}
|
||||
assert(errorThrown, 'Should throw error for empty name');
|
||||
|
||||
errorThrown = false;
|
||||
try {
|
||||
toggleCollection({}, 'test', 'not-boolean');
|
||||
} catch (error) {
|
||||
errorThrown = true;
|
||||
assert(error.message.includes('Enabled state must be a boolean'), 'Should require boolean enabled state');
|
||||
}
|
||||
assert(errorThrown, 'Should throw error for non-boolean enabled state');
|
||||
});
|
||||
|
||||
// Test 7: Error handling for non-existent collection
|
||||
test("Error handling for non-existent collection", () => {
|
||||
const config = { collections: {} };
|
||||
|
||||
let errorThrown = false;
|
||||
try {
|
||||
toggleCollection(config, 'non-existent-collection', true);
|
||||
} catch (error) {
|
||||
errorThrown = true;
|
||||
assert(error.message.includes('does not exist'), 'Should indicate collection does not exist');
|
||||
}
|
||||
assert(errorThrown, 'Should throw error for non-existent collection');
|
||||
});
|
||||
|
||||
console.log(`\nTest Results: ${passedTests}/${totalTests} passed`);
|
||||
|
||||
if (passedTests === totalTests) {
|
||||
console.log('🎉 All toggleCollection tests passed!');
|
||||
return true;
|
||||
} else {
|
||||
console.log('💥 Some toggleCollection tests failed!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
const success = runTests();
|
||||
process.exit(success ? 0 : 1);
|
||||
}
|
||||
|
||||
module.exports = { runTests };
|
||||
Loading…
x
Reference in New Issue
Block a user