chore: fix use-tag e2e test

This commit is contained in:
Ralph Khreish
2025-07-12 00:38:49 +03:00
parent e580e5d7c0
commit 3204582885
7 changed files with 187 additions and 173 deletions

View File

@@ -3,17 +3,27 @@
* Runs once before all test suites
*/
const { execSync } = require('child_process');
const { existsSync } = require('fs');
const { join } = require('path');
import { execSync } from 'child_process';
import { existsSync } from 'fs';
import { join } from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
module.exports = async () => {
console.log('\n🚀 Setting up E2E test environment...\n');
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export default async () => {
// Silent mode for cleaner output
if (!process.env.JEST_SILENT_REPORTER) {
console.log('\n🚀 Setting up E2E test environment...\n');
}
try {
// Ensure task-master is linked globally
const projectRoot = join(__dirname, '../../..');
console.log('📦 Linking task-master globally...');
if (!process.env.JEST_SILENT_REPORTER) {
console.log('📦 Linking task-master globally...');
}
execSync('npm link', {
cwd: projectRoot,
stdio: 'inherit'
@@ -26,13 +36,17 @@ module.exports = async () => {
'⚠️ Warning: .env file not found. Some tests may fail without API keys.'
);
} else {
console.log('✅ .env file found');
if (!process.env.JEST_SILENT_REPORTER) {
console.log('✅ .env file found');
}
}
// Verify task-master command is available
try {
execSync('task-master --version', { stdio: 'pipe' });
console.log('✅ task-master command is available\n');
if (!process.env.JEST_SILENT_REPORTER) {
console.log('✅ task-master command is available\n');
}
} catch (error) {
throw new Error(
'task-master command not found. Please ensure npm link succeeded.'

View File

@@ -3,8 +3,11 @@
* Runs once after all test suites
*/
module.exports = async () => {
console.log('\n🧹 Cleaning up E2E test environment...\n');
export default async () => {
// Silent mode for cleaner output
if (!process.env.JEST_SILENT_REPORTER) {
console.log('\n🧹 Cleaning up E2E test environment...\n');
}
// Any global cleanup needed
// Note: Individual test directories are cleaned up in afterEach hooks

View File

@@ -1,131 +1,169 @@
const path = require('path');
const fs = require('fs');
const {
setupTestEnvironment,
cleanupTestEnvironment,
runCommand
} = require('../../helpers/testHelpers');
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
import { mkdtempSync, existsSync, readFileSync, rmSync, writeFileSync } from 'fs';
import { join } from 'path';
import { tmpdir } from 'os';
describe('use-tag command', () => {
let testDir;
let tasksPath;
let helpers;
beforeEach(async () => {
const setup = await setupTestEnvironment();
testDir = setup.testDir;
tasksPath = setup.tasksPath;
// Create test directory
testDir = mkdtempSync(join(tmpdir(), 'task-master-use-tag-'));
// Initialize test helpers
const context = global.createTestContext('use-tag');
helpers = context.helpers;
// Copy .env file if it exists
const mainEnvPath = join(process.cwd(), '.env');
const testEnvPath = join(testDir, '.env');
if (existsSync(mainEnvPath)) {
const envContent = readFileSync(mainEnvPath, 'utf8');
writeFileSync(testEnvPath, envContent);
}
// Initialize task-master project
const initResult = await helpers.taskMaster('init', ['-y'], {
cwd: testDir
});
expect(initResult).toHaveExitCode(0);
// Create tasks file path
const tasksPath = join(testDir, '.taskmaster/tasks/tasks.json');
// Create a test project with multiple tags
const tasksData = {
tasks: [
{
id: 1,
description: 'Task in master',
status: 'pending',
tags: ['master']
},
{
id: 2,
description: 'Task in feature',
status: 'pending',
tags: ['feature']
},
{
id: 3,
description: 'Task in both',
status: 'pending',
tags: ['master', 'feature']
}
],
tags: {
master: {
name: 'master',
description: 'Main development branch'
},
feature: {
name: 'feature',
description: 'Feature branch'
},
release: {
name: 'release',
description: 'Release branch'
}
master: {
tasks: [
{
id: 1,
description: 'Task in master',
status: 'pending',
tags: ['master']
},
{
id: 3,
description: 'Task in both',
status: 'pending',
tags: ['master', 'feature']
}
]
},
feature: {
tasks: [
{
id: 2,
description: 'Task in feature',
status: 'pending',
tags: ['feature']
},
{
id: 3,
description: 'Task in both',
status: 'pending',
tags: ['master', 'feature']
}
]
},
release: {
tasks: []
},
activeTag: 'master',
metadata: {
nextId: 4
nextId: 4,
activeTag: 'master'
}
};
fs.writeFileSync(tasksPath, JSON.stringify(tasksData, null, 2));
writeFileSync(tasksPath, JSON.stringify(tasksData, null, 2));
});
afterEach(async () => {
await cleanupTestEnvironment(testDir);
// Clean up test directory
if (testDir && existsSync(testDir)) {
rmSync(testDir, { recursive: true, force: true });
}
});
test('should switch to an existing tag', async () => {
const result = await runCommand(['use-tag', 'feature'], testDir);
it('should switch to an existing tag', async () => {
const result = await helpers.taskMaster('use-tag', ['feature'], {
cwd: testDir
});
expect(result.code).toBe(0);
expect(result.stdout).toContain('Successfully switched to tag: feature');
expect(result).toHaveExitCode(0);
expect(result.stdout).toContain('Successfully switched to tag "feature"');
// Verify the active tag was updated
const updatedData = JSON.parse(fs.readFileSync(tasksPath, 'utf8'));
expect(updatedData.activeTag).toBe('feature');
// Verify the active tag was updated in state.json
const statePath = join(testDir, '.taskmaster/state.json');
const stateData = JSON.parse(readFileSync(statePath, 'utf8'));
expect(stateData.currentTag).toBe('feature');
});
test('should show error when switching to non-existent tag', async () => {
const result = await runCommand(['use-tag', 'nonexistent'], testDir);
it('should show error when switching to non-existent tag', async () => {
const result = await helpers.taskMaster('use-tag', ['nonexistent'], {
cwd: testDir
});
expect(result.code).toBe(1);
expect(result).toHaveExitCode(1);
expect(result.stderr).toContain('Tag "nonexistent" does not exist');
});
test('should switch from feature tag back to master', async () => {
it('should switch from feature tag back to master', async () => {
// First switch to feature
await runCommand(['use-tag', 'feature'], testDir);
await helpers.taskMaster('use-tag', ['feature'], { cwd: testDir });
// Then switch back to master
const result = await runCommand(['use-tag', 'master'], testDir);
const result = await helpers.taskMaster('use-tag', ['master'], {
cwd: testDir
});
expect(result.code).toBe(0);
expect(result.stdout).toContain('Successfully switched to tag: master');
expect(result).toHaveExitCode(0);
expect(result.stdout).toContain('Successfully switched to tag "master"');
const updatedData = JSON.parse(fs.readFileSync(tasksPath, 'utf8'));
expect(updatedData.activeTag).toBe('master');
// Verify the active tag was updated in state.json
const statePath = join(testDir, '.taskmaster/state.json');
const stateData = JSON.parse(readFileSync(statePath, 'utf8'));
expect(stateData.currentTag).toBe('master');
});
test('should handle switching to the same tag gracefully', async () => {
const result = await runCommand(['use-tag', 'master'], testDir);
it('should handle switching to the same tag gracefully', async () => {
const result = await helpers.taskMaster('use-tag', ['master'], {
cwd: testDir
});
expect(result.code).toBe(0);
expect(result.stdout).toContain('Already on tag: master');
expect(result).toHaveExitCode(0);
expect(result.stdout).toContain('Successfully switched to tag "master"');
});
test('should work with custom tasks file path', async () => {
const customTasksPath = path.join(testDir, 'custom-tasks.json');
fs.copyFileSync(tasksPath, customTasksPath);
it('should work with custom tasks file path', async () => {
const tasksPath = join(testDir, '.taskmaster/tasks/tasks.json');
const customTasksPath = join(testDir, 'custom-tasks.json');
const content = readFileSync(tasksPath, 'utf8');
writeFileSync(customTasksPath, content);
const result = await runCommand(
['use-tag', 'feature', '-f', customTasksPath],
testDir
const result = await helpers.taskMaster(
'use-tag',
['feature', '-f', customTasksPath],
{ cwd: testDir }
);
expect(result.code).toBe(0);
expect(result.stdout).toContain('Successfully switched to tag: feature');
expect(result).toHaveExitCode(0);
expect(result.stdout).toContain('Successfully switched to tag "feature"');
const updatedData = JSON.parse(fs.readFileSync(customTasksPath, 'utf8'));
expect(updatedData.activeTag).toBe('feature');
// Verify the active tag was updated in state.json
const statePath = join(testDir, '.taskmaster/state.json');
const stateData = JSON.parse(readFileSync(statePath, 'utf8'));
expect(stateData.currentTag).toBe('feature');
});
test('should fail when tasks file does not exist', async () => {
const nonExistentPath = path.join(testDir, 'nonexistent.json');
const result = await runCommand(
['use-tag', 'feature', '-f', nonExistentPath],
testDir
it('should fail when tasks file does not exist', async () => {
const nonExistentPath = join(testDir, 'nonexistent.json');
const result = await helpers.taskMaster(
'use-tag',
['feature', '-f', nonExistentPath],
{ cwd: testDir }
);
expect(result.code).toBe(1);
expect(result.stderr).toContain('Tasks file not found');
expect(result).toHaveExitCode(1);
expect(result.stderr).toContain('does not exist');
});
});

View File

@@ -58,7 +58,10 @@ export class TestLogger {
break;
}
console.log(coloredMessage);
// Only output to console if debugging or it's an error
if ((process.env.DEBUG_TESTS || level === 'ERROR') && !process.env.JEST_SILENT_MODE) {
console.log(coloredMessage);
}
// Write to file if immediate flush requested
if (options.flush) {