feat: tickets I follow, and more news for followers
"Que sigo" on the home page lists the open tickets I follow, whoever works on them; `watching` filters my issues (REST, GraphQL, MCP) and a project's search (none without a session). Followers now also hear when a ticket's priority or due date changes, and when it enters or leaves a sprint. Smaller edits (title, labels…) still do not notify. Docs (with the REPLIED row the replies change missed), Word and PDF updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import {
|
||||
CommentAddedEvent,
|
||||
IssueAssignedEvent,
|
||||
IssuePriority,
|
||||
IssueSprintChangedEvent,
|
||||
IssueStatusChangedEvent,
|
||||
IssueUpdatedEvent,
|
||||
NotificationKind,
|
||||
NotificationReadModel,
|
||||
NotificationSettingsReadModel,
|
||||
@@ -14,6 +17,7 @@ import { FakeUserDirectory } from '../../testing/in-memory';
|
||||
import { ChangeFeed } from '../ports/change-feed';
|
||||
import { FindCommentsRepository } from '../ports/find-comments.repository';
|
||||
import { FindIssuesRepository } from '../ports/find-issues.repository';
|
||||
import { FindSprintsRepository } from '../ports/find-sprints.repository';
|
||||
import { FindProjectsRepository } from '../ports/find-projects.repository';
|
||||
import { NotificationMailer } from '../ports/notification-mailer';
|
||||
import { NotificationsRepository } from '../ports/notifications.repository';
|
||||
@@ -108,6 +112,10 @@ function setup(mailEnabled = false) {
|
||||
? { id, author: { id: 'pm', name: 'PM' }, deleted: false }
|
||||
: null,
|
||||
} as unknown as FindCommentsRepository,
|
||||
{
|
||||
findById: async (id: string) =>
|
||||
id === 's-14' ? { id, name: 'Sprint 14' } : null,
|
||||
} as unknown as FindSprintsRepository,
|
||||
);
|
||||
return { repo, published, mailed, handler };
|
||||
}
|
||||
@@ -236,6 +244,60 @@ describe('notifications', () => {
|
||||
expect(repo.all[0].summary).toContain('respondió a tu comentario');
|
||||
});
|
||||
|
||||
it('tells followers of a new priority, due date or sprint, not of smaller edits', async () => {
|
||||
const { handler, repo } = setup();
|
||||
await handler.handle(
|
||||
at(
|
||||
new IssueUpdatedEvent('ana', 'i-1', 'p-1', {
|
||||
priority: IssuePriority.HIGH,
|
||||
dueDate: '2026-11-14',
|
||||
}),
|
||||
),
|
||||
);
|
||||
await handler.handle(
|
||||
at(new IssueUpdatedEvent('ana', 'i-1', 'p-1', { title: 'Login' }), 3),
|
||||
);
|
||||
await handler.handle(
|
||||
at(new IssueSprintChangedEvent('ana', 'i-1', 'p-1', 's-14', null), 4),
|
||||
);
|
||||
await handler.handle(
|
||||
at(new IssueSprintChangedEvent('ana', 'i-1', 'p-1', null, 's-14'), 5),
|
||||
);
|
||||
|
||||
expect(repo.all.map((n) => [n.userId, n.kind, n.summary])).toEqual([
|
||||
[
|
||||
'pm',
|
||||
NotificationKind.WATCHED,
|
||||
'user ana cambió WEB-1: Login roto: prioridad Alta, fecha límite el 14 de noviembre de 2026',
|
||||
],
|
||||
[
|
||||
'bob',
|
||||
NotificationKind.WATCHED,
|
||||
'user ana cambió WEB-1: Login roto: prioridad Alta, fecha límite el 14 de noviembre de 2026',
|
||||
],
|
||||
[
|
||||
'pm',
|
||||
NotificationKind.WATCHED,
|
||||
'user ana metió WEB-1: Login roto en el sprint Sprint 14',
|
||||
],
|
||||
[
|
||||
'bob',
|
||||
NotificationKind.WATCHED,
|
||||
'user ana metió WEB-1: Login roto en el sprint Sprint 14',
|
||||
],
|
||||
[
|
||||
'pm',
|
||||
NotificationKind.WATCHED,
|
||||
'user ana sacó WEB-1: Login roto del sprint y lo devolvió al backlog',
|
||||
],
|
||||
[
|
||||
'bob',
|
||||
NotificationKind.WATCHED,
|
||||
'user ana sacó WEB-1: Login roto del sprint y lo devolvió al backlog',
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('copies by e-mail only to whoever asked for it, when mail is configured', async () => {
|
||||
const { handler, repo, mailed } = setup(true);
|
||||
repo.emailOn.add('bob');
|
||||
|
||||
Reference in New Issue
Block a user