feat: teams within a project

Projects keep teams of members in their settings (settings.teams; people
outside the project are dropped, teams are archived, not removed; absent
when saving means unchanged). Tickets go to a team (`team`, also filtered
in the list and in MCP search_issues), and a comment mentioning
@[Frontend](team-FRONT) tells each of its members. Settings has the teams
with their members, the ticket a «Equipo» select, the list a team filter,
and «@» offers the teams after the people.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 16:20:35 +02:00
parent 4acf629106
commit 869acd3f1f
41 changed files with 895 additions and 13 deletions

View File

@@ -403,4 +403,55 @@ describe('Project settings', () => {
});
expect(project.workflow.checklistBeforeDone).toBe(false);
});
it('keeps teams of members, assigns tickets to them and expands their mentions', () => {
const project = newProject();
project.updateSettings('owner', {
...defaultProjectSettings(),
teams: [
{
id: 'front',
name: ' Frontend ',
memberIds: ['dev', 'dev', 'stranger'],
archived: false,
},
],
});
// Normalised, and only people of the project.
expect(project.workflow.teams).toEqual([
{ id: 'FRONT', name: 'Frontend', memberIds: ['dev'], archived: false },
]);
// Absent: unchanged; removing one: refused (archive it instead).
project.updateSettings('owner', defaultProjectSettings());
expect(project.workflow.teams).toHaveLength(1);
expect(() =>
project.updateSettings('owner', {
...defaultProjectSettings(),
teams: [],
}),
).toThrow(/archívalo/);
expect(
project.workflow.mentionedPeople(['owner', 'team-FRONT', 'team-NOPE']),
).toEqual(['owner', 'dev']);
const issue = new IssueFactory().create(
{
projectId: project.id,
projectKey: 'WEB',
number: 1,
title: 'Botón',
type: 'TASK',
reporterId: 'dev',
team: 'FRONT',
},
project.workflow,
);
expect(issue.team).toBe('FRONT');
expect(() =>
issue.updateDetails('dev', { team: 'NOPE' }, project.workflow),
).toThrow(ValidationError);
issue.updateDetails('dev', { team: null }, project.workflow);
expect(issue.team).toBeNull();
});
});