feat: mentions and following tickets

Mention project members in comments with @, follow and unfollow tickets,
and get told when something changes on the tickets you follow. Commenting
on a ticket starts following it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 09:41:32 +02:00
parent efa06a0723
commit 88928b402f
49 changed files with 1318 additions and 41 deletions

View File

@@ -8,6 +8,7 @@ import { IssueStatusChangedEvent } from '../events/issue-status-changed.event';
import { IssueFactory } from '../factories/issue.factory';
import { replay } from '../testing';
import { Issue } from './issue';
import { mentionedUserIds, withoutMentionMarkup } from './mentions';
import { IssueLinkType, IssueStatus, IssueType } from './issue.enums';
const factory = new IssueFactory();
@@ -206,4 +207,31 @@ describe('Issue', () => {
expect(rebuilt.attachments.map((a) => a.id)).toEqual(['a-2']);
});
});
describe('followers', () => {
it('follows and unfollows once, and survives a replay', () => {
const issue = newIssue();
issue.watch('u-dev', 'u-dev');
issue.watch('u-dev', 'u-dev');
issue.watch('u-pm', 'u-pm');
issue.unwatch('u-dev', 'u-dev');
issue.unwatch('u-dev', 'u-dev');
expect(issue.watchers).toEqual(['u-pm']);
expect(replay(issue, Issue).rebuilt.watchers).toEqual(['u-pm']);
expect(issue.getUncommittedEvents()).toHaveLength(4);
});
});
describe('mentions', () => {
it('reads who a text mentions, once each', () => {
const text =
'Hola @[Ana García](u-ana) y @[Bob](u-bob), @[Ana García](u-ana) otra vez. @sinmarca';
expect(mentionedUserIds(text)).toEqual(['u-ana', 'u-bob']);
expect(withoutMentionMarkup(text)).toBe(
'Hola @Ana García y @Bob, @Ana García otra vez. @sinmarca',
);
});
});
});