Files
syndarix/frontend/tests/components/admin/organizations/MemberActionMenu.test.tsx
Felipe Cardoso 4420756741 Add organization members management components and tests
- Implemented `OrganizationMembersContent`, `OrganizationMembersTable`, and `AddMemberDialog` components for organization members management.
- Added unit tests for `OrganizationMembersContent` and `OrganizationMembersTable`, covering rendering, state handling, and edge cases.
- Enhanced `useOrganizationMembers` and `useGetOrganization` hooks to support members list and pagination data integration.
- Updated E2E tests to include organization members page interactions and improved reliability.
2025-11-06 21:57:57 +01:00

135 lines
3.7 KiB
TypeScript

/**
* Tests for MemberActionMenu Component
*/
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemberActionMenu } from '@/components/admin/organizations/MemberActionMenu';
import type { OrganizationMember } from '@/lib/api/hooks/useAdmin';
// Mock hooks
const mockRemoveMember = jest.fn();
jest.mock('@/lib/api/hooks/useAdmin', () => ({
useRemoveOrganizationMember: () => ({
mutateAsync: mockRemoveMember,
}),
}));
// Mock toast
jest.mock('sonner', () => ({
toast: {
success: jest.fn(),
error: jest.fn(),
},
}));
describe('MemberActionMenu', () => {
const mockMember: OrganizationMember = {
user_id: 'user-1',
email: 'john@test.com',
first_name: 'John',
last_name: 'Doe',
role: 'member',
joined_at: '2025-01-01T00:00:00Z',
};
const props = {
member: mockMember,
organizationId: 'org-1',
};
beforeEach(() => {
jest.clearAllMocks();
mockRemoveMember.mockResolvedValue({});
});
it('renders action menu button', () => {
render(<MemberActionMenu {...props} />);
const button = screen.getByRole('button', { name: /Actions for John Doe/i });
expect(button).toBeInTheDocument();
});
it('opens menu when button clicked', async () => {
const user = userEvent.setup();
render(<MemberActionMenu {...props} />);
const menuButton = screen.getByRole('button', { name: /Actions for/i });
await user.click(menuButton);
await waitFor(() => {
expect(screen.getByText('Remove Member')).toBeVisible();
});
});
it('shows remove member option in menu', async () => {
const user = userEvent.setup();
render(<MemberActionMenu {...props} />);
const menuButton = screen.getByRole('button', { name: /Actions for/i });
await user.click(menuButton);
await waitFor(() => {
const removeOption = screen.getByText('Remove Member');
expect(removeOption).toBeVisible();
});
});
it('opens confirmation dialog when remove clicked', async () => {
const user = userEvent.setup();
render(<MemberActionMenu {...props} />);
const menuButton = screen.getByRole('button', { name: /Actions for/i });
await user.click(menuButton);
const removeOption = await screen.findByText('Remove Member');
await user.click(removeOption);
await waitFor(() => {
expect(screen.getByText(/Are you sure you want to remove.*John Doe.*from this organization/)).toBeVisible();
});
});
it('closes dialog when cancel clicked', async () => {
const user = userEvent.setup();
render(<MemberActionMenu {...props} />);
// Open menu
const menuButton = screen.getByRole('button', { name: /Actions for/i });
await user.click(menuButton);
// Click remove
const removeOption = await screen.findByText('Remove Member');
await user.click(removeOption);
// Wait for dialog
await waitFor(() => {
expect(screen.getByRole('button', { name: 'Cancel' })).toBeVisible();
});
// Click cancel
const cancelButton = screen.getByRole('button', { name: 'Cancel' });
await user.click(cancelButton);
// Dialog should close
await waitFor(() => {
const confirmText = screen.queryByText(/Are you sure you want to remove/);
expect(confirmText).toBeNull();
});
});
it('uses email as fallback when name is missing', () => {
const memberWithoutName = {
...mockMember,
first_name: '',
last_name: null,
};
render(<MemberActionMenu member={memberWithoutName} organizationId="org-1" />);
const button = screen.getByRole('button', { name: /Actions for john@test.com/i });
expect(button).toBeInTheDocument();
});
});