mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 14:22:02 +00:00
- Introduced comprehensive unit tests for the validation storage module, covering functions such as writeValidation, readValidation, getAllValidations, deleteValidation, and others. - Implemented tests to ensure correct behavior for validation creation, retrieval, deletion, and freshness checks. - Enhanced test coverage for edge cases, including handling of non-existent validations and directory structure validation.
308 lines
9.4 KiB
TypeScript
308 lines
9.4 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
import {
|
|
writeValidation,
|
|
readValidation,
|
|
getAllValidations,
|
|
deleteValidation,
|
|
isValidationStale,
|
|
getValidationWithFreshness,
|
|
markValidationViewed,
|
|
getUnviewedValidationsCount,
|
|
type StoredValidation,
|
|
} from '@/lib/validation-storage.js';
|
|
import fs from 'fs/promises';
|
|
import path from 'path';
|
|
import os from 'os';
|
|
|
|
describe('validation-storage.ts', () => {
|
|
let testProjectPath: string;
|
|
|
|
beforeEach(async () => {
|
|
testProjectPath = path.join(os.tmpdir(), `validation-storage-test-${Date.now()}`);
|
|
await fs.mkdir(testProjectPath, { recursive: true });
|
|
});
|
|
|
|
afterEach(async () => {
|
|
try {
|
|
await fs.rm(testProjectPath, { recursive: true, force: true });
|
|
} catch {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
const createMockValidation = (overrides: Partial<StoredValidation> = {}): StoredValidation => ({
|
|
issueNumber: 123,
|
|
issueTitle: 'Test Issue',
|
|
validatedAt: new Date().toISOString(),
|
|
model: 'haiku',
|
|
result: {
|
|
verdict: 'valid',
|
|
confidence: 'high',
|
|
reasoning: 'Test reasoning',
|
|
},
|
|
...overrides,
|
|
});
|
|
|
|
describe('writeValidation', () => {
|
|
it('should write validation to storage', async () => {
|
|
const validation = createMockValidation();
|
|
|
|
await writeValidation(testProjectPath, 123, validation);
|
|
|
|
// Verify file was created
|
|
const validationPath = path.join(
|
|
testProjectPath,
|
|
'.automaker',
|
|
'validations',
|
|
'123',
|
|
'validation.json'
|
|
);
|
|
const content = await fs.readFile(validationPath, 'utf-8');
|
|
expect(JSON.parse(content)).toEqual(validation);
|
|
});
|
|
|
|
it('should create nested directories if they do not exist', async () => {
|
|
const validation = createMockValidation({ issueNumber: 456 });
|
|
|
|
await writeValidation(testProjectPath, 456, validation);
|
|
|
|
const validationPath = path.join(
|
|
testProjectPath,
|
|
'.automaker',
|
|
'validations',
|
|
'456',
|
|
'validation.json'
|
|
);
|
|
const content = await fs.readFile(validationPath, 'utf-8');
|
|
expect(JSON.parse(content)).toEqual(validation);
|
|
});
|
|
});
|
|
|
|
describe('readValidation', () => {
|
|
it('should read validation from storage', async () => {
|
|
const validation = createMockValidation();
|
|
await writeValidation(testProjectPath, 123, validation);
|
|
|
|
const result = await readValidation(testProjectPath, 123);
|
|
|
|
expect(result).toEqual(validation);
|
|
});
|
|
|
|
it('should return null when validation does not exist', async () => {
|
|
const result = await readValidation(testProjectPath, 999);
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('getAllValidations', () => {
|
|
it('should return all validations for a project', async () => {
|
|
const validation1 = createMockValidation({ issueNumber: 1, issueTitle: 'Issue 1' });
|
|
const validation2 = createMockValidation({ issueNumber: 2, issueTitle: 'Issue 2' });
|
|
const validation3 = createMockValidation({ issueNumber: 3, issueTitle: 'Issue 3' });
|
|
|
|
await writeValidation(testProjectPath, 1, validation1);
|
|
await writeValidation(testProjectPath, 2, validation2);
|
|
await writeValidation(testProjectPath, 3, validation3);
|
|
|
|
const result = await getAllValidations(testProjectPath);
|
|
|
|
expect(result).toHaveLength(3);
|
|
expect(result[0]).toEqual(validation1);
|
|
expect(result[1]).toEqual(validation2);
|
|
expect(result[2]).toEqual(validation3);
|
|
});
|
|
|
|
it('should return empty array when no validations exist', async () => {
|
|
const result = await getAllValidations(testProjectPath);
|
|
|
|
expect(result).toEqual([]);
|
|
});
|
|
|
|
it('should skip non-numeric directories', async () => {
|
|
const validation = createMockValidation({ issueNumber: 1 });
|
|
await writeValidation(testProjectPath, 1, validation);
|
|
|
|
// Create a non-numeric directory
|
|
const invalidDir = path.join(testProjectPath, '.automaker', 'validations', 'invalid');
|
|
await fs.mkdir(invalidDir, { recursive: true });
|
|
|
|
const result = await getAllValidations(testProjectPath);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toEqual(validation);
|
|
});
|
|
});
|
|
|
|
describe('deleteValidation', () => {
|
|
it('should delete validation from storage', async () => {
|
|
const validation = createMockValidation();
|
|
await writeValidation(testProjectPath, 123, validation);
|
|
|
|
const result = await deleteValidation(testProjectPath, 123);
|
|
|
|
expect(result).toBe(true);
|
|
|
|
const readResult = await readValidation(testProjectPath, 123);
|
|
expect(readResult).toBeNull();
|
|
});
|
|
|
|
it('should return true even when validation does not exist', async () => {
|
|
const result = await deleteValidation(testProjectPath, 999);
|
|
|
|
expect(result).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('isValidationStale', () => {
|
|
it('should return false for recent validation', () => {
|
|
const validation = createMockValidation({
|
|
validatedAt: new Date().toISOString(),
|
|
});
|
|
|
|
const result = isValidationStale(validation);
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('should return true for validation older than 24 hours', () => {
|
|
const oldDate = new Date();
|
|
oldDate.setHours(oldDate.getHours() - 25); // 25 hours ago
|
|
|
|
const validation = createMockValidation({
|
|
validatedAt: oldDate.toISOString(),
|
|
});
|
|
|
|
const result = isValidationStale(validation);
|
|
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('should return false for validation exactly at 24 hours', () => {
|
|
const exactDate = new Date();
|
|
exactDate.setHours(exactDate.getHours() - 24);
|
|
|
|
const validation = createMockValidation({
|
|
validatedAt: exactDate.toISOString(),
|
|
});
|
|
|
|
const result = isValidationStale(validation);
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('getValidationWithFreshness', () => {
|
|
it('should return validation with isStale false for recent validation', async () => {
|
|
const validation = createMockValidation({
|
|
validatedAt: new Date().toISOString(),
|
|
});
|
|
await writeValidation(testProjectPath, 123, validation);
|
|
|
|
const result = await getValidationWithFreshness(testProjectPath, 123);
|
|
|
|
expect(result).not.toBeNull();
|
|
expect(result!.validation).toEqual(validation);
|
|
expect(result!.isStale).toBe(false);
|
|
});
|
|
|
|
it('should return validation with isStale true for old validation', async () => {
|
|
const oldDate = new Date();
|
|
oldDate.setHours(oldDate.getHours() - 25);
|
|
|
|
const validation = createMockValidation({
|
|
validatedAt: oldDate.toISOString(),
|
|
});
|
|
await writeValidation(testProjectPath, 123, validation);
|
|
|
|
const result = await getValidationWithFreshness(testProjectPath, 123);
|
|
|
|
expect(result).not.toBeNull();
|
|
expect(result!.isStale).toBe(true);
|
|
});
|
|
|
|
it('should return null when validation does not exist', async () => {
|
|
const result = await getValidationWithFreshness(testProjectPath, 999);
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('markValidationViewed', () => {
|
|
it('should mark validation as viewed', async () => {
|
|
const validation = createMockValidation();
|
|
await writeValidation(testProjectPath, 123, validation);
|
|
|
|
const result = await markValidationViewed(testProjectPath, 123);
|
|
|
|
expect(result).toBe(true);
|
|
|
|
const updated = await readValidation(testProjectPath, 123);
|
|
expect(updated).not.toBeNull();
|
|
expect(updated!.viewedAt).toBeDefined();
|
|
});
|
|
|
|
it('should return false when validation does not exist', async () => {
|
|
const result = await markValidationViewed(testProjectPath, 999);
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('getUnviewedValidationsCount', () => {
|
|
it('should return count of unviewed non-stale validations', async () => {
|
|
const validation1 = createMockValidation({ issueNumber: 1 });
|
|
const validation2 = createMockValidation({ issueNumber: 2 });
|
|
const validation3 = createMockValidation({
|
|
issueNumber: 3,
|
|
viewedAt: new Date().toISOString(),
|
|
});
|
|
|
|
await writeValidation(testProjectPath, 1, validation1);
|
|
await writeValidation(testProjectPath, 2, validation2);
|
|
await writeValidation(testProjectPath, 3, validation3);
|
|
|
|
const result = await getUnviewedValidationsCount(testProjectPath);
|
|
|
|
expect(result).toBe(2);
|
|
});
|
|
|
|
it('should not count stale validations', async () => {
|
|
const oldDate = new Date();
|
|
oldDate.setHours(oldDate.getHours() - 25);
|
|
|
|
const validation1 = createMockValidation({ issueNumber: 1 });
|
|
const validation2 = createMockValidation({
|
|
issueNumber: 2,
|
|
validatedAt: oldDate.toISOString(),
|
|
});
|
|
|
|
await writeValidation(testProjectPath, 1, validation1);
|
|
await writeValidation(testProjectPath, 2, validation2);
|
|
|
|
const result = await getUnviewedValidationsCount(testProjectPath);
|
|
|
|
expect(result).toBe(1);
|
|
});
|
|
|
|
it('should return 0 when no validations exist', async () => {
|
|
const result = await getUnviewedValidationsCount(testProjectPath);
|
|
|
|
expect(result).toBe(0);
|
|
});
|
|
|
|
it('should return 0 when all validations are viewed', async () => {
|
|
const validation = createMockValidation({
|
|
issueNumber: 1,
|
|
viewedAt: new Date().toISOString(),
|
|
});
|
|
|
|
await writeValidation(testProjectPath, 1, validation);
|
|
|
|
const result = await getUnviewedValidationsCount(testProjectPath);
|
|
|
|
expect(result).toBe(0);
|
|
});
|
|
});
|
|
});
|