import { describe, it, expect, vi } from 'vitest';
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { ClubHierarchyBuilder } from '../components/founder-portal/club-hierarchy-builder';
import { ClubPermissionMatrix } from '../components/founder-portal/club-permission-matrix';
import { DEFAULT_CLUB_RANKS, DEFAULT_CLUB_CAPABILITIES, DEFAULT_RANK_PERMISSIONS } from '../lib/club-data';
import { ClubMember } from '../components/founder-portal/types';
describe('WEB-13: ClubHierarchyBuilder & ClubPermissionMatrix', () => {
const mockMembers: ClubMember[] = [
{
uid: 'rider-01',
clubId: 'club-test',
status: 'active',
role: 'owner',
displayRank: 'President',
displayName: 'Marcus Vance',
handle: '@marcus_v',
updatedAt: new Date().toISOString(),
},
{
uid: 'rider-02',
clubId: 'club-test',
status: 'active',
role: 'admin',
displayRank: 'Vice President',
displayName: 'Elena Rostova',
handle: '@elena_rides',
updatedAt: new Date().toISOString(),
},
{
uid: 'rider-03',
clubId: 'club-test',
status: 'active',
role: 'member',
displayRank: 'Road Captain',
displayName: 'Dave Miller',
handle: '@dave_m',
updatedAt: new Date().toISOString(),
},
];
it('renders all organizational tiers and rank nodes in hierarchy builder', () => {
const handleSelectRank = vi.fn();
const handleUpdateMemberRank = vi.fn().mockResolvedValue(undefined);
render(
);
expect(screen.getByText('Club Hierarchy Builder')).toBeDefined();
expect(screen.getByText('Tier 1 • Executive Command')).toBeDefined();
expect(screen.getByText('Tier 2 • Leadership & Administration')).toBeDefined();
expect(screen.getByText('Tier 3 • Tactical Operations & Pack Safety')).toBeDefined();
expect(screen.getByText('Tier 4 • Squad Formation & Prospects')).toBeDefined();
expect(screen.getByText('President')).toBeDefined();
expect(screen.getByText('Vice President')).toBeDefined();
expect(screen.getByText('Road Captain')).toBeDefined();
expect(screen.getByText('Tail Gunner')).toBeDefined();
});
it('selects rank node and triggers onSelectRank callback', () => {
const handleSelectRank = vi.fn();
const handleUpdateMemberRank = vi.fn().mockResolvedValue(undefined);
render(
);
const roadCaptainNode = screen.getByText('Road Captain');
fireEvent.click(roadCaptainNode);
expect(handleSelectRank).toHaveBeenCalledWith('road_captain');
});
it('opens assign member modal and executes rank update', async () => {
const handleSelectRank = vi.fn();
const handleUpdateMemberRank = vi.fn().mockResolvedValue(undefined);
render(
);
const assignButtons = screen.getAllByText('Assign Rider');
fireEvent.click(assignButtons[0]);
expect(screen.getByText(/Assign to /)).toBeDefined();
const select = screen.getByRole('combobox');
fireEvent.change(select, { target: { value: 'rider-03' } });
const submitBtn = screen.getByRole('button', { name: /Assign Rank/i });
fireEvent.click(submitBtn);
expect(handleUpdateMemberRank).toHaveBeenCalledWith('rider-03', expect.any(String));
});
it('renders permission matrix table with capabilities and allows toggling', () => {
const handleToggle = vi.fn();
const handleReset = vi.fn();
const handleSave = vi.fn().mockResolvedValue(undefined);
render(
);
expect(screen.getByText('Operational Permission Matrix')).toBeDefined();
expect(screen.getByText('Plan Club Rides')).toBeDefined();
expect(screen.getByText('Review Applications')).toBeDefined();
expect(screen.getByText('Post Announcements')).toBeDefined();
expect(screen.getByText('Moderate Club Wall')).toBeDefined();
// Find toggle button for road captain and click it
const toggleButton = screen.getByRole('button', { name: 'Toggle Plan Club Rides for Road Captain' });
fireEvent.click(toggleButton);
expect(handleToggle).toHaveBeenCalledWith('road_captain', 'planRides');
});
it('triggers save matrix and reset defaults', async () => {
const handleToggle = vi.fn();
const handleReset = vi.fn();
const handleSave = vi.fn().mockResolvedValue(undefined);
render(
);
const resetBtn = screen.getByRole('button', { name: /Reset Defaults/i });
fireEvent.click(resetBtn);
expect(handleReset).toHaveBeenCalled();
const saveBtn = screen.getByRole('button', { name: /Save Matrix/i });
fireEvent.click(saveBtn);
expect(handleSave).toHaveBeenCalled();
});
});