Files
Codewalkers/apps/server/db/repositories/drizzle/initiative.test.ts
Lukas May 34578d39c6 refactor: Restructure monorepo to apps/server/ and apps/web/ layout
Move src/ → apps/server/ and packages/web/ → apps/web/ to adopt
standard monorepo conventions (apps/ for runnable apps, packages/
for reusable libraries). Update all config files, shared package
imports, test fixtures, and documentation to reflect new paths.

Key fixes:
- Update workspace config to ["apps/*", "packages/*"]
- Update tsconfig.json rootDir/include for apps/server/
- Add apps/web/** to vitest exclude list
- Update drizzle.config.ts schema path
- Fix ensure-schema.ts migration path detection (3 levels up in dev,
  2 levels up in dist)
- Fix tests/integration/cli-server.test.ts import paths
- Update packages/shared imports to apps/server/ paths
- Update all docs/ files with new paths
2026-03-03 11:22:53 +01:00

151 lines
4.6 KiB
TypeScript

/**
* DrizzleInitiativeRepository Tests
*
* Tests for the Initiative repository adapter.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { DrizzleInitiativeRepository } from './initiative.js';
import { createTestDatabase } from './test-helpers.js';
import type { DrizzleDatabase } from '../../index.js';
describe('DrizzleInitiativeRepository', () => {
let db: DrizzleDatabase;
let repo: DrizzleInitiativeRepository;
beforeEach(() => {
db = createTestDatabase();
repo = new DrizzleInitiativeRepository(db);
});
describe('create', () => {
it('should create an initiative with generated id and timestamps', async () => {
const initiative = await repo.create({
name: 'Test Initiative',
});
expect(initiative.id).toBeDefined();
expect(initiative.id.length).toBeGreaterThan(0);
expect(initiative.name).toBe('Test Initiative');
expect(initiative.status).toBe('active');
expect(initiative.createdAt).toBeInstanceOf(Date);
expect(initiative.updatedAt).toBeInstanceOf(Date);
});
it('should use provided status', async () => {
const initiative = await repo.create({
name: 'Completed Initiative',
status: 'completed',
});
expect(initiative.status).toBe('completed');
});
});
describe('findById', () => {
it('should return null for non-existent initiative', async () => {
const result = await repo.findById('non-existent-id');
expect(result).toBeNull();
});
it('should find an existing initiative', async () => {
const created = await repo.create({
name: 'Find Me',
});
const found = await repo.findById(created.id);
expect(found).not.toBeNull();
expect(found!.id).toBe(created.id);
expect(found!.name).toBe('Find Me');
});
});
describe('findAll', () => {
it('should return empty array initially', async () => {
const all = await repo.findAll();
expect(all).toEqual([]);
});
it('should return all initiatives', async () => {
await repo.create({ name: 'Initiative 1' });
await repo.create({ name: 'Initiative 2' });
await repo.create({ name: 'Initiative 3' });
const all = await repo.findAll();
expect(all.length).toBe(3);
});
});
describe('update', () => {
it('should update fields and updatedAt', async () => {
const created = await repo.create({
name: 'Original Name',
status: 'active',
});
// Small delay to ensure updatedAt differs
await new Promise((resolve) => setTimeout(resolve, 10));
const updated = await repo.update(created.id, {
name: 'Updated Name',
status: 'completed',
});
expect(updated.name).toBe('Updated Name');
expect(updated.status).toBe('completed');
expect(updated.updatedAt.getTime()).toBeGreaterThanOrEqual(created.updatedAt.getTime());
});
it('should throw for non-existent initiative', async () => {
await expect(
repo.update('non-existent-id', { name: 'New Name' })
).rejects.toThrow('Initiative not found');
});
});
describe('delete', () => {
it('should delete an existing initiative', async () => {
const created = await repo.create({ name: 'To Delete' });
await repo.delete(created.id);
const found = await repo.findById(created.id);
expect(found).toBeNull();
});
it('should throw for non-existent initiative', async () => {
await expect(repo.delete('non-existent-id')).rejects.toThrow(
'Initiative not found'
);
});
});
describe('findByStatus', () => {
it('should return empty array for no matches', async () => {
await repo.create({ name: 'Active 1', status: 'active' });
const completed = await repo.findByStatus('completed');
expect(completed).toEqual([]);
});
it('should filter by status', async () => {
await repo.create({ name: 'Active 1', status: 'active' });
await repo.create({ name: 'Active 2', status: 'active' });
await repo.create({ name: 'Completed', status: 'completed' });
await repo.create({ name: 'Archived', status: 'archived' });
const active = await repo.findByStatus('active');
expect(active).toHaveLength(2);
expect(active.every((i) => i.status === 'active')).toBe(true);
const completed = await repo.findByStatus('completed');
expect(completed).toHaveLength(1);
expect(completed[0].name).toBe('Completed');
const archived = await repo.findByStatus('archived');
expect(archived).toHaveLength(1);
expect(archived[0].name).toBe('Archived');
});
});
});