import React from 'react' import { describe, it, expect, vi } from 'vitest' import { render, screen } from '@testing-library/react' import { MemoryRouter } from 'react-router-dom' // Mocked first so Directory (and ProjectLayout, which it imports entryNoun // from) resolve the deployment hook and api without a live fetch. let mockDeployment = {} vi.mock('../api', () => ({ getProject: vi.fn(), createProject: vi.fn() })) vi.mock('../context/DeploymentProvider', () => ({ useDeployment: () => mockDeployment, })) import Directory from './Directory.jsx' function renderDir(overrides = {}) { mockDeployment = { name: 'Wiggleverse', tagline: 'a directory of projects', projects: [], viewer: null, defaultProjectId: null, refresh: vi.fn(), ...overrides, } return render() } describe('Directory', () => { it('renders a card per visible project with the type-driven noun + link', () => { renderDir({ projects: [ { id: 'ohm', name: 'Open Human Model', type: 'document', visibility: 'public' }, { id: 'ecomm', name: 'Ecomm', type: 'bdd', visibility: 'public' }, ], }) const ohm = screen.getByText('Open Human Model').closest('a') expect(ohm).toHaveAttribute('href', '/p/ohm/') const ecomm = screen.getByText('Ecomm').closest('a') expect(ecomm).toHaveAttribute('href', '/p/ecomm/') // bdd โ†’ "Features", document โ†’ "RFCs" expect(screen.getByText('RFCs')).toBeInTheDocument() expect(screen.getByText('Features')).toBeInTheDocument() }) it('renders the deployment name and tagline', () => { renderDir({ projects: [{ id: 'ohm', name: 'OHM', type: 'document', visibility: 'public' }] }) expect(screen.getByText('Wiggleverse')).toBeInTheDocument() expect(screen.getByText('a directory of projects')).toBeInTheDocument() }) it('renders an empty list without crashing when no projects are visible', () => { renderDir({ projects: [] }) expect(screen.getByText('Wiggleverse')).toBeInTheDocument() }) // ยง22 S5 โ€” role-aware empty states (C3.1 / C3.2). it('shows a "Create your first project" CTA to a global Owner on an empty directory', () => { renderDir({ projects: [], viewer: { can_create_project: true } }) expect(screen.getByText('Create your first project')).toBeInTheDocument() }) it('shows a "nothing shared with you yet" note to a non-owner on an empty directory', () => { renderDir({ projects: [], viewer: { can_create_project: false } }) expect(screen.getByText(/Nothing has been shared with you yet/i)).toBeInTheDocument() expect(screen.queryByText('Create your first project')).not.toBeInTheDocument() }) it('offers a "New project" control to an Owner when the directory is non-empty', () => { renderDir({ projects: [{ id: 'ohm', name: 'OHM', type: 'document', visibility: 'public' }], viewer: { can_create_project: true }, }) expect(screen.getByText('New project')).toBeInTheDocument() }) it('does not offer a create control to a non-owner when the directory is non-empty', () => { renderDir({ projects: [{ id: 'ohm', name: 'OHM', type: 'document', visibility: 'public' }], viewer: { can_create_project: false }, }) expect(screen.queryByText('New project')).not.toBeInTheDocument() }) })