import { defaultProjectSettings, DevLinkKind, DevLinkState, IssueDevLinkRecordedEvent, IssuePriority, IssueStatusChangedEvent, ProjectWorkflow, SYSTEM_ACTOR_ID, } from '@task-stream/api/tracker/domain'; import { AutomationActionKind, AutomationTriggerKind, normalizeRule, ruleApplies, triggerOf, } from './automation-rules'; const workflow = new ProjectWorkflow(defaultProjectSettings()); const bug = { type: 'BUG', priority: IssuePriority.HIGH, area: 'FRONTEND', labels: ['ui'], }; describe('automation rules', () => { it('reads triggers from events, merged pull requests included', () => { expect( triggerOf( new IssueStatusChangedEvent('u', 'i1', 'p', 'TODO', 'IN_QA', null), ), ).toEqual({ kind: AutomationTriggerKind.STATUS_CHANGED, issueId: 'i1', status: 'IN_QA', }); const merged = new IssueDevLinkRecordedEvent(SYSTEM_ACTOR_ID, 'i2', 'p', { kind: DevLinkKind.PULL_REQUEST, url: 'https://x/pr/1', title: 'x', ref: '#1', state: DevLinkState.MERGED, provider: 'github', author: null, at: '', }); expect(triggerOf(merged)?.kind).toBe( AutomationTriggerKind.PULL_REQUEST_MERGED, ); }); it('checks the trigger, its status and every condition', () => { const rule = { trigger: { kind: AutomationTriggerKind.STATUS_CHANGED, status: 'IN_QA' }, conditions: { types: ['BUG'], label: 'ui' }, }; const into = (status: string) => ({ kind: AutomationTriggerKind.STATUS_CHANGED, status, }); expect(ruleApplies(rule, into('IN_QA'), bug)).toBe(true); expect(ruleApplies(rule, into('DONE'), bug)).toBe(false); expect(ruleApplies(rule, into('IN_QA'), { ...bug, labels: [] })).toBe( false, ); expect(ruleApplies(rule, into('IN_QA'), { ...bug, type: 'TASK' })).toBe( false, ); }); it('refuses actions without a usable value', () => { const rule = (kind: AutomationActionKind, value: string | null) => ({ name: 'R', trigger: { kind: AutomationTriggerKind.ISSUE_CREATED }, conditions: {}, action: { kind, value }, }); const member = (id: string) => id === 'u-ana'; expect( normalizeRule( rule(AutomationActionKind.ADD_LABEL, ' Triage '), workflow, member, ).action, ).toEqual({ kind: AutomationActionKind.ADD_LABEL, value: 'triage', }); expect(() => normalizeRule( rule(AutomationActionKind.SET_STATUS, 'NOPE'), workflow, member, ), ).toThrow(); expect(() => normalizeRule( rule(AutomationActionKind.ASSIGN, 'u-bob'), workflow, member, ), ).toThrow(); expect( normalizeRule( rule(AutomationActionKind.ASSIGN_REPORTER, 'x'), workflow, member, ).action.value, ).toBeNull(); }); });