alnilam-cli
Version:
Git-native AI career coach that converts multi-year ambitions into weekly execution
242 lines (241 loc) • 10.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// Mock the API module before importing the goal command
jest.mock('../api.js', () => ({
createGoal: jest.fn(),
listGoals: jest.fn(),
}));
const api_js_1 = require("../api.js");
describe('Goal Management', () => {
beforeEach(() => {
jest.clearAllMocks();
// Reset console methods
jest.spyOn(console, 'log').mockImplementation(() => { });
jest.spyOn(console, 'error').mockImplementation(() => { });
jest.spyOn(process, 'exit').mockImplementation(() => {
throw new Error('process.exit called');
});
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('Goal Creation', () => {
it('should validate horizon values', async () => {
const validHorizons = ['multi-year', 'annual', 'quarterly', 'weekly'];
validHorizons.forEach(horizon => {
expect(validHorizons.includes(horizon)).toBe(true);
});
const invalidHorizons = ['daily', 'monthly', 'invalid'];
invalidHorizons.forEach(horizon => {
expect(validHorizons.includes(horizon)).toBe(false);
});
});
it('should create goal with required fields', async () => {
const mockGoal = {
id: 'test-id',
title: 'Test Goal',
horizon: 'weekly',
created_at: '2025-07-02T10:00:00Z',
updated_at: '2025-07-02T10:00:00Z'
};
api_js_1.createGoal.mockResolvedValue(mockGoal);
const goalData = {
title: 'Test Goal',
horizon: 'weekly',
description: undefined,
target_date: undefined,
};
const result = await (0, api_js_1.createGoal)(goalData);
expect(api_js_1.createGoal).toHaveBeenCalledWith(goalData);
expect(result).toEqual(mockGoal);
});
it('should create goal with optional fields', async () => {
const mockGoal = {
id: 'test-id',
title: 'Test Goal with Details',
horizon: 'quarterly',
description: 'A detailed test goal',
target_date: '2025-12-31',
created_at: '2025-07-02T10:00:00Z',
updated_at: '2025-07-02T10:00:00Z'
};
api_js_1.createGoal.mockResolvedValue(mockGoal);
const goalData = {
title: 'Test Goal with Details',
horizon: 'quarterly',
description: 'A detailed test goal',
target_date: '2025-12-31',
};
const result = await (0, api_js_1.createGoal)(goalData);
expect(api_js_1.createGoal).toHaveBeenCalledWith(goalData);
expect(result).toEqual(mockGoal);
});
it('should handle createGoal API errors', async () => {
const errorMessage = 'Failed to create goal';
api_js_1.createGoal.mockRejectedValue(new Error(errorMessage));
const goalData = {
title: 'Test Goal',
horizon: 'weekly',
description: undefined,
target_date: undefined,
};
await expect((0, api_js_1.createGoal)(goalData)).rejects.toThrow(errorMessage);
});
});
describe('Goal Listing', () => {
it('should list goals without filters', async () => {
const mockGoals = [
{
id: 'goal-1',
title: 'Goal 1',
horizon: 'weekly',
status: 'active',
created_at: '2025-07-01T10:00:00Z',
},
{
id: 'goal-2',
title: 'Goal 2',
horizon: 'quarterly',
status: 'active',
created_at: '2025-07-02T10:00:00Z',
}
];
api_js_1.listGoals.mockResolvedValue(mockGoals);
const result = await (0, api_js_1.listGoals)({});
expect(api_js_1.listGoals).toHaveBeenCalledWith({});
expect(result).toEqual(mockGoals);
expect(result).toHaveLength(2);
});
it('should list goals with horizon filter', async () => {
const mockGoals = [
{
id: 'goal-1',
title: 'Weekly Goal',
horizon: 'weekly',
status: 'active',
created_at: '2025-07-01T10:00:00Z',
}
];
api_js_1.listGoals.mockResolvedValue(mockGoals);
const params = { horizon: 'weekly', status: 'active' };
const result = await (0, api_js_1.listGoals)(params);
expect(api_js_1.listGoals).toHaveBeenCalledWith(params);
expect(result).toEqual(mockGoals);
expect(result[0].horizon).toBe('weekly');
});
it('should validate horizon filter values', async () => {
const validHorizons = ['multi-year', 'annual', 'quarterly', 'weekly'];
validHorizons.forEach(horizon => {
expect(validHorizons.includes(horizon)).toBe(true);
});
const invalidHorizons = ['daily', 'monthly', 'invalid'];
invalidHorizons.forEach(horizon => {
expect(validHorizons.includes(horizon)).toBe(false);
});
});
it('should handle empty goal list', async () => {
api_js_1.listGoals.mockResolvedValue([]);
const result = await (0, api_js_1.listGoals)({});
expect(api_js_1.listGoals).toHaveBeenCalledWith({});
expect(result).toEqual([]);
expect(result).toHaveLength(0);
});
it('should handle listGoals API errors', async () => {
const errorMessage = 'Failed to fetch goals';
api_js_1.listGoals.mockRejectedValue(new Error(errorMessage));
await expect((0, api_js_1.listGoals)({})).rejects.toThrow(errorMessage);
});
});
describe('Goal Data Validation', () => {
it('should handle goals with all optional fields', async () => {
const completeGoal = {
id: 'complete-goal',
title: 'Complete Goal',
horizon: 'annual',
description: 'A goal with all fields',
target_date: '2025-12-31',
status: 'active',
created_at: '2025-07-02T10:00:00Z',
updated_at: '2025-07-02T10:00:00Z'
};
api_js_1.listGoals.mockResolvedValue([completeGoal]);
const result = await (0, api_js_1.listGoals)({});
expect(result[0]).toMatchObject({
id: expect.any(String),
title: expect.any(String),
horizon: expect.stringMatching(/^(multi-year|annual|quarterly|weekly)$/),
description: expect.any(String),
target_date: expect.stringMatching(/^\d{4}-\d{2}-\d{2}$/),
status: expect.any(String),
created_at: expect.any(String),
updated_at: expect.any(String)
});
});
it('should handle goals with minimal fields', async () => {
const minimalGoal = {
id: 'minimal-goal',
title: 'Minimal Goal',
horizon: 'weekly',
status: 'active',
created_at: '2025-07-02T10:00:00Z',
};
api_js_1.listGoals.mockResolvedValue([minimalGoal]);
const result = await (0, api_js_1.listGoals)({});
expect(result[0]).toMatchObject({
id: expect.any(String),
title: expect.any(String),
horizon: expect.stringMatching(/^(multi-year|annual|quarterly|weekly)$/),
status: expect.any(String),
created_at: expect.any(String)
});
// Optional fields should be undefined
expect(result[0].description).toBeUndefined();
expect(result[0].target_date).toBeUndefined();
expect(result[0].updated_at).toBeUndefined();
});
});
describe('Date Handling', () => {
it('should handle valid date formats', () => {
const validDates = [
'2025-07-02',
'2025-12-31',
'2026-01-01'
];
validDates.forEach(date => {
expect(date).toMatch(/^\d{4}-\d{2}-\d{2}$/);
expect(new Date(date).toString()).not.toBe('Invalid Date');
});
});
it('should detect invalid date formats', () => {
const invalidDates = [
'07-02-2025',
'2025/07/02',
'2025-13-01',
'invalid-date'
];
invalidDates.forEach(date => {
if (date.match(/^\d{4}-\d{2}-\d{2}$/)) {
// Check if it's a valid date even if format is correct
const dateObj = new Date(date);
expect(dateObj.toString()).toBe('Invalid Date');
}
else {
// Format is incorrect
expect(date).not.toMatch(/^\d{4}-\d{2}-\d{2}$/);
}
});
});
});
describe('Status Values', () => {
it('should handle valid status values', () => {
const validStatuses = ['active', 'completed', 'paused', 'cancelled'];
validStatuses.forEach(status => {
expect(['active', 'completed', 'paused', 'cancelled']).toContain(status);
});
});
it('should default to active status', () => {
const defaultStatus = 'active';
expect(['active', 'completed', 'paused', 'cancelled']).toContain(defaultStatus);
});
});
});