agent-ecosystem/test/renderer/components/team/members/MemberList.test.ts
2026-04-23 18:27:03 +03:00

101 lines
2.6 KiB
TypeScript

import React, { act } from 'react';
import { createRoot } from 'react-dom/client';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import type { MemberSpawnStatusEntry, ResolvedTeamMember } from '@shared/types';
vi.mock('@renderer/components/team/members/MemberCard', () => ({
MemberCard: ({
member,
spawnError,
}: {
member: ResolvedTeamMember;
spawnError?: string;
}) => React.createElement('div', { 'data-testid': `member-${member.name}` }, spawnError ?? ''),
}));
import { MemberList } from '@renderer/components/team/members/MemberList';
const member: ResolvedTeamMember = {
name: 'bob',
status: 'unknown',
taskCount: 0,
currentTaskId: null,
lastActiveAt: null,
messageCount: 0,
color: 'blue',
agentType: 'developer',
role: 'Developer',
providerId: 'opencode',
model: 'opencode/minimax-m2.5-free',
removedAt: undefined,
};
function failedSpawnStatus(reason: string): MemberSpawnStatusEntry {
return {
status: 'error',
launchState: 'failed_to_start',
updatedAt: '2026-04-23T10:00:00.000Z',
runtimeAlive: false,
bootstrapConfirmed: false,
hardFailure: true,
hardFailureReason: reason,
agentToolAccepted: false,
};
}
describe('MemberList spawn-status memoization', () => {
beforeEach(() => {
vi.stubGlobal(
'ResizeObserver',
class ResizeObserver {
observe(): void {}
disconnect(): void {}
}
);
});
afterEach(() => {
vi.unstubAllGlobals();
document.body.innerHTML = '';
});
it('rerenders cards when only the hard failure reason changes', async () => {
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
const host = document.createElement('div');
document.body.appendChild(host);
const root = createRoot(host);
const members = [member];
await act(async () => {
root.render(
React.createElement(MemberList, {
members,
isTeamAlive: true,
memberSpawnStatuses: new Map([['bob', failedSpawnStatus('initial OpenCode failure')]]),
})
);
await Promise.resolve();
});
expect(host.textContent).toContain('initial OpenCode failure');
await act(async () => {
root.render(
React.createElement(MemberList, {
members,
isTeamAlive: true,
memberSpawnStatuses: new Map([['bob', failedSpawnStatus('updated OpenCode failure')]]),
})
);
await Promise.resolve();
});
expect(host.textContent).toContain('updated OpenCode failure');
await act(async () => {
root.unmount();
await Promise.resolve();
});
});
});