190 lines
5.8 KiB
TypeScript
190 lines
5.8 KiB
TypeScript
/**
|
|
* Tests for isWorkflowPath and loadWorkflowByIdentifier
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { tmpdir } from 'node:os';
|
|
import {
|
|
isWorkflowPath,
|
|
loadWorkflowByIdentifier,
|
|
listWorkflows,
|
|
loadAllWorkflows,
|
|
} from '../infra/config/loaders/workflowLoader.js';
|
|
|
|
const SAMPLE_WORKFLOW = `name: test-workflow
|
|
description: Test workflow
|
|
initial_movement: step1
|
|
max_iterations: 1
|
|
|
|
movements:
|
|
- name: step1
|
|
agent: coder
|
|
instruction: "{task}"
|
|
`;
|
|
|
|
describe('isWorkflowPath', () => {
|
|
it('should return true for absolute paths', () => {
|
|
expect(isWorkflowPath('/path/to/workflow.yaml')).toBe(true);
|
|
expect(isWorkflowPath('/workflow')).toBe(true);
|
|
});
|
|
|
|
it('should return true for home directory paths', () => {
|
|
expect(isWorkflowPath('~/workflow.yaml')).toBe(true);
|
|
expect(isWorkflowPath('~/.takt/pieces/custom.yaml')).toBe(true);
|
|
});
|
|
|
|
it('should return true for relative paths starting with ./', () => {
|
|
expect(isWorkflowPath('./workflow.yaml')).toBe(true);
|
|
expect(isWorkflowPath('./subdir/workflow.yaml')).toBe(true);
|
|
});
|
|
|
|
it('should return true for relative paths starting with ../', () => {
|
|
expect(isWorkflowPath('../workflow.yaml')).toBe(true);
|
|
expect(isWorkflowPath('../subdir/workflow.yaml')).toBe(true);
|
|
});
|
|
|
|
it('should return true for paths ending with .yaml', () => {
|
|
expect(isWorkflowPath('custom.yaml')).toBe(true);
|
|
expect(isWorkflowPath('my-workflow.yaml')).toBe(true);
|
|
});
|
|
|
|
it('should return true for paths ending with .yml', () => {
|
|
expect(isWorkflowPath('custom.yml')).toBe(true);
|
|
expect(isWorkflowPath('my-workflow.yml')).toBe(true);
|
|
});
|
|
|
|
it('should return false for plain workflow names', () => {
|
|
expect(isWorkflowPath('default')).toBe(false);
|
|
expect(isWorkflowPath('simple')).toBe(false);
|
|
expect(isWorkflowPath('magi')).toBe(false);
|
|
expect(isWorkflowPath('my-custom-workflow')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('loadWorkflowByIdentifier', () => {
|
|
let tempDir: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = mkdtempSync(join(tmpdir(), 'takt-test-'));
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('should load workflow by name (builtin)', () => {
|
|
const workflow = loadWorkflowByIdentifier('default', process.cwd());
|
|
expect(workflow).not.toBeNull();
|
|
expect(workflow!.name).toBe('default');
|
|
});
|
|
|
|
it('should load workflow by absolute path', () => {
|
|
const filePath = join(tempDir, 'test.yaml');
|
|
writeFileSync(filePath, SAMPLE_WORKFLOW);
|
|
|
|
const workflow = loadWorkflowByIdentifier(filePath, tempDir);
|
|
expect(workflow).not.toBeNull();
|
|
expect(workflow!.name).toBe('test-workflow');
|
|
});
|
|
|
|
it('should load workflow by relative path', () => {
|
|
const filePath = join(tempDir, 'test.yaml');
|
|
writeFileSync(filePath, SAMPLE_WORKFLOW);
|
|
|
|
const workflow = loadWorkflowByIdentifier('./test.yaml', tempDir);
|
|
expect(workflow).not.toBeNull();
|
|
expect(workflow!.name).toBe('test-workflow');
|
|
});
|
|
|
|
it('should load workflow by filename with .yaml extension', () => {
|
|
const filePath = join(tempDir, 'test.yaml');
|
|
writeFileSync(filePath, SAMPLE_WORKFLOW);
|
|
|
|
const workflow = loadWorkflowByIdentifier('test.yaml', tempDir);
|
|
expect(workflow).not.toBeNull();
|
|
expect(workflow!.name).toBe('test-workflow');
|
|
});
|
|
|
|
it('should return null for non-existent name', () => {
|
|
const workflow = loadWorkflowByIdentifier('non-existent-workflow-xyz', process.cwd());
|
|
expect(workflow).toBeNull();
|
|
});
|
|
|
|
it('should return null for non-existent path', () => {
|
|
const workflow = loadWorkflowByIdentifier('./non-existent.yaml', tempDir);
|
|
expect(workflow).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('listWorkflows with project-local', () => {
|
|
let tempDir: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = mkdtempSync(join(tmpdir(), 'takt-test-'));
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('should include project-local workflows when cwd is provided', () => {
|
|
const projectWorkflowsDir = join(tempDir, '.takt', 'workflows');
|
|
mkdirSync(projectWorkflowsDir, { recursive: true });
|
|
writeFileSync(join(projectWorkflowsDir, 'project-custom.yaml'), SAMPLE_WORKFLOW);
|
|
|
|
const workflows = listWorkflows(tempDir);
|
|
expect(workflows).toContain('project-custom');
|
|
});
|
|
|
|
it('should include builtin workflows regardless of cwd', () => {
|
|
const workflows = listWorkflows(tempDir);
|
|
expect(workflows).toContain('default');
|
|
});
|
|
|
|
});
|
|
|
|
describe('loadAllWorkflows with project-local', () => {
|
|
let tempDir: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = mkdtempSync(join(tmpdir(), 'takt-test-'));
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('should include project-local workflows when cwd is provided', () => {
|
|
const projectWorkflowsDir = join(tempDir, '.takt', 'workflows');
|
|
mkdirSync(projectWorkflowsDir, { recursive: true });
|
|
writeFileSync(join(projectWorkflowsDir, 'project-custom.yaml'), SAMPLE_WORKFLOW);
|
|
|
|
const workflows = loadAllWorkflows(tempDir);
|
|
expect(workflows.has('project-custom')).toBe(true);
|
|
expect(workflows.get('project-custom')!.name).toBe('test-workflow');
|
|
});
|
|
|
|
it('should have project-local override builtin when same name', () => {
|
|
const projectWorkflowsDir = join(tempDir, '.takt', 'workflows');
|
|
mkdirSync(projectWorkflowsDir, { recursive: true });
|
|
|
|
const overrideWorkflow = `name: project-override
|
|
description: Project override
|
|
initial_movement: step1
|
|
max_iterations: 1
|
|
|
|
movements:
|
|
- name: step1
|
|
agent: coder
|
|
instruction: "{task}"
|
|
`;
|
|
writeFileSync(join(projectWorkflowsDir, 'default.yaml'), overrideWorkflow);
|
|
|
|
const workflows = loadAllWorkflows(tempDir);
|
|
expect(workflows.get('default')!.name).toBe('project-override');
|
|
});
|
|
|
|
});
|