feat: a home page with life
Greeting and summary of the day, the coming week, the latest across my projects, who is online now, the week in numbers (mine and the team's, with a streak), sprints under way, «Retomar», project cards with their activity, what to pick up when nothing is mine and first steps for newcomers. REST (GET /api/me/home), GraphQL (myHome) and MCP (get_my_week). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1904,4 +1904,71 @@ describe('task-stream (e2e)', () => {
|
||||
(d) => !d['portfolio'].some((p: { key: string }) => p.key === key),
|
||||
);
|
||||
});
|
||||
|
||||
it('fills the home page: agenda, activity, the week and who is here', async () => {
|
||||
const key = 'H' + Date.now().toString(36).slice(-5).toUpperCase();
|
||||
await rest('token-ana', 'POST', '/projects', { key, name: key });
|
||||
await eventually(
|
||||
() => rest('token-ana', 'GET', `/projects/${key}`),
|
||||
(r) => r.status === 200,
|
||||
);
|
||||
await rest('token-ana', 'POST', `/projects/${key}/members`, {
|
||||
userId: '102',
|
||||
});
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
const ticket = (
|
||||
await rest('token-ana', 'POST', `/projects/${key}/issues`, {
|
||||
type: 'TASK',
|
||||
title: 'Para hoy',
|
||||
assigneeId: '101',
|
||||
dueDate: today,
|
||||
})
|
||||
).body['key'];
|
||||
const issue = await eventually(
|
||||
() => rest('token-bob', 'GET', `/issues/${ticket}`),
|
||||
(r) => r.status === 200,
|
||||
);
|
||||
// Bob is on it right now.
|
||||
await rest('token-bob', 'PUT', `/issues/${issue.body['id']}/presence`, {
|
||||
editing: true,
|
||||
});
|
||||
|
||||
const home = await eventually(
|
||||
() => rest('token-ana', 'GET', '/me/home'),
|
||||
(r) =>
|
||||
r.body?.agenda?.some(
|
||||
(a: { issueKey: string }) => a.issueKey === ticket,
|
||||
) &&
|
||||
r.body.activity.some(
|
||||
(a: { issueKey: string }) => a.issueKey === ticket,
|
||||
),
|
||||
);
|
||||
expect(home.body.agenda).toContainEqual(
|
||||
expect.objectContaining({ day: today, kind: 'ISSUE', issueKey: ticket }),
|
||||
);
|
||||
expect(home.body.online).toContainEqual(
|
||||
expect.objectContaining({
|
||||
user: { id: '102', name: 'Bob (frontend)' },
|
||||
projectKey: key,
|
||||
issueKey: ticket,
|
||||
editing: true,
|
||||
}),
|
||||
);
|
||||
expect(home.body.team.perDay).toHaveLength(14);
|
||||
expect(home.body.firstSteps).toMatchObject({
|
||||
project: true,
|
||||
invited: true,
|
||||
ticket: true,
|
||||
});
|
||||
const card = home.body.projects.find(
|
||||
(p: { projectId: string }) => p.projectId === issue.body['projectId'],
|
||||
);
|
||||
expect(card).toMatchObject({ open: 1 });
|
||||
expect(card.activity).toHaveLength(14);
|
||||
const { myHome } = await gql(
|
||||
'token-ana',
|
||||
`query { myHome { me { thisWeek streak } suggestions { kind } } }`,
|
||||
);
|
||||
expect(myHome.me.streak).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user