takt/src/__tests__/sessionState.test.ts

187 lines
5.0 KiB
TypeScript

/**
* Session state management tests
*/
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdirSync, rmSync, existsSync } from 'node:fs';
import { join } from 'node:path';
import {
loadSessionState,
saveSessionState,
clearSessionState,
getSessionStatePath,
type SessionState,
} from '../infra/config/project/sessionState.js';
describe('sessionState', () => {
const testDir = join(__dirname, '__temp_session_state_test__');
beforeEach(() => {
if (existsSync(testDir)) {
rmSync(testDir, { recursive: true, force: true });
}
mkdirSync(testDir, { recursive: true });
});
afterEach(() => {
if (existsSync(testDir)) {
rmSync(testDir, { recursive: true, force: true });
}
});
describe('getSessionStatePath', () => {
it('should return correct path', () => {
const path = getSessionStatePath(testDir);
expect(path).toContain('.takt');
expect(path).toContain('session-state.json');
});
});
describe('loadSessionState', () => {
it('should return null when file does not exist', () => {
const state = loadSessionState(testDir);
expect(state).toBeNull();
});
it('should load saved state', () => {
const savedState: SessionState = {
status: 'success',
taskResult: 'Task completed successfully',
timestamp: new Date().toISOString(),
pieceName: 'coding',
taskContent: 'Implement feature X',
lastMovement: 'implement',
};
saveSessionState(testDir, savedState);
const loadedState = loadSessionState(testDir);
expect(loadedState).toEqual(savedState);
});
it('should return null when JSON parsing fails', () => {
const path = getSessionStatePath(testDir);
const configDir = join(testDir, '.takt');
mkdirSync(configDir, { recursive: true });
// Write invalid JSON
const fs = require('node:fs');
fs.writeFileSync(path, 'invalid json', 'utf-8');
const state = loadSessionState(testDir);
expect(state).toBeNull();
});
});
describe('saveSessionState', () => {
it('should save state correctly', () => {
const state: SessionState = {
status: 'success',
taskResult: 'Task completed',
timestamp: new Date().toISOString(),
pieceName: 'minimal',
taskContent: 'Test task',
lastMovement: 'test-movement',
};
saveSessionState(testDir, state);
const path = getSessionStatePath(testDir);
expect(existsSync(path)).toBe(true);
const loaded = loadSessionState(testDir);
expect(loaded).toEqual(state);
});
it('should save error state', () => {
const state: SessionState = {
status: 'error',
errorMessage: 'Something went wrong',
timestamp: new Date().toISOString(),
pieceName: 'coding',
taskContent: 'Failed task',
};
saveSessionState(testDir, state);
const loaded = loadSessionState(testDir);
expect(loaded).toEqual(state);
});
it('should save user_stopped state', () => {
const state: SessionState = {
status: 'user_stopped',
timestamp: new Date().toISOString(),
pieceName: 'coding',
taskContent: 'Interrupted task',
};
saveSessionState(testDir, state);
const loaded = loadSessionState(testDir);
expect(loaded).toEqual(state);
});
});
describe('clearSessionState', () => {
it('should delete state file', () => {
const state: SessionState = {
status: 'success',
timestamp: new Date().toISOString(),
pieceName: 'coding',
};
saveSessionState(testDir, state);
const path = getSessionStatePath(testDir);
expect(existsSync(path)).toBe(true);
clearSessionState(testDir);
expect(existsSync(path)).toBe(false);
});
it('should not throw when file does not exist', () => {
expect(() => clearSessionState(testDir)).not.toThrow();
});
});
describe('integration', () => {
it('should support one-time notification pattern', () => {
// Save state
const state: SessionState = {
status: 'success',
taskResult: 'Done',
timestamp: new Date().toISOString(),
pieceName: 'coding',
};
saveSessionState(testDir, state);
// Load once
const loaded1 = loadSessionState(testDir);
expect(loaded1).toEqual(state);
// Clear immediately
clearSessionState(testDir);
// Load again - should be null
const loaded2 = loadSessionState(testDir);
expect(loaded2).toBeNull();
});
it('should handle truncated strings', () => {
const longString = 'a'.repeat(2000);
const state: SessionState = {
status: 'success',
taskResult: longString,
timestamp: new Date().toISOString(),
pieceName: 'coding',
taskContent: longString,
};
saveSessionState(testDir, state);
const loaded = loadSessionState(testDir);
expect(loaded).toEqual(state);
});
});
});