129 lines
3.4 KiB
TypeScript
129 lines
3.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
getTaskChangeStateBucket,
|
|
isTaskChangeSummaryCacheable,
|
|
} from '../../../src/shared/utils/taskChangeState';
|
|
|
|
describe('taskChangeState utils', () => {
|
|
it('falls back to persisted legacy reviewState when history has no review signal', () => {
|
|
const bucket = getTaskChangeStateBucket({
|
|
status: 'completed',
|
|
reviewState: 'approved',
|
|
historyEvents: [
|
|
{
|
|
id: '1',
|
|
timestamp: '2026-01-01T00:00:00Z',
|
|
type: 'task_created',
|
|
status: 'completed',
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(bucket).toBe('approved');
|
|
expect(isTaskChangeSummaryCacheable(bucket)).toBe(true);
|
|
});
|
|
|
|
it('falls back to the kanban overlay when history has no review signal', () => {
|
|
expect(
|
|
getTaskChangeStateBucket({
|
|
status: 'completed',
|
|
kanbanColumn: 'review',
|
|
historyEvents: [
|
|
{
|
|
id: '1',
|
|
timestamp: '2026-01-01T00:00:00Z',
|
|
type: 'task_created',
|
|
status: 'completed',
|
|
},
|
|
],
|
|
})
|
|
).toBe('review');
|
|
});
|
|
|
|
it('keeps explicit pending reopen as active after approval', () => {
|
|
expect(
|
|
getTaskChangeStateBucket({
|
|
status: 'pending',
|
|
reviewState: 'approved',
|
|
historyEvents: [
|
|
{
|
|
id: '1',
|
|
timestamp: '2026-01-01T00:00:00Z',
|
|
type: 'review_approved',
|
|
from: 'review',
|
|
to: 'approved',
|
|
actor: 'alice',
|
|
},
|
|
{
|
|
id: '2',
|
|
timestamp: '2026-01-01T00:01:00Z',
|
|
type: 'status_changed',
|
|
from: 'completed',
|
|
to: 'pending',
|
|
actor: 'alice',
|
|
},
|
|
],
|
|
})
|
|
).toBe('active');
|
|
});
|
|
|
|
it('treats in-progress tasks approved through kanban overlay as approved', () => {
|
|
const bucket = getTaskChangeStateBucket({
|
|
status: 'in_progress',
|
|
kanbanColumn: 'approved',
|
|
});
|
|
|
|
expect(bucket).toBe('approved');
|
|
expect(isTaskChangeSummaryCacheable(bucket)).toBe(true);
|
|
});
|
|
|
|
it('does not treat pending tasks with stale approved kanban overlay as approved', () => {
|
|
expect(
|
|
getTaskChangeStateBucket({
|
|
status: 'pending',
|
|
kanbanColumn: 'approved',
|
|
})
|
|
).toBe('active');
|
|
});
|
|
|
|
it('does not treat pending tasks with stale review kanban overlay as review', () => {
|
|
expect(
|
|
getTaskChangeStateBucket({
|
|
status: 'pending',
|
|
kanbanColumn: 'review',
|
|
})
|
|
).toBe('active');
|
|
});
|
|
|
|
it('lets current kanban review overlay win over stale approved review state', () => {
|
|
expect(
|
|
getTaskChangeStateBucket({
|
|
status: 'completed',
|
|
reviewState: 'approved',
|
|
kanbanColumn: 'review',
|
|
})
|
|
).toBe('review');
|
|
});
|
|
|
|
it('does not cache completed tasks that still need fixes', () => {
|
|
const bucket = getTaskChangeStateBucket({
|
|
status: 'completed',
|
|
reviewState: 'needsFix',
|
|
});
|
|
|
|
expect(bucket).toBe('active');
|
|
expect(isTaskChangeSummaryCacheable(bucket)).toBe(false);
|
|
});
|
|
|
|
it('lets current approved overlay win over stale needsFix for change summary caching', () => {
|
|
const bucket = getTaskChangeStateBucket({
|
|
status: 'completed',
|
|
reviewState: 'needsFix',
|
|
kanbanColumn: 'approved',
|
|
});
|
|
|
|
expect(bucket).toBe('approved');
|
|
expect(isTaskChangeSummaryCacheable(bucket)).toBe(true);
|
|
});
|
|
});
|