// @vitest-environment jsdom /** What the MembersDialog page claims, pinned. */ import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { MembersDialog } from './MembersDialog' import { MembersPill } from './MembersPill' afterEach(cleanup) const members = [ { id: 'me', name: 'You' }, { id: 'ana', name: 'Ana Duarte', caption: 'Assignee' }, ] describe('MembersDialog', () => { it('lists every member with their caption, and counts them in the title', async () => { render( {}} />) const dialog = await screen.findByRole('dialog', { name: /Members/ }) expect(dialog.textContent).toContain('Ana Duarte') expect(dialog.textContent).toContain('Assignee') expect(dialog.textContent).toContain('2') }) it('offers no Join, Leave or Add when none is given', async () => { render( {}} />) await screen.findByRole('dialog') expect(screen.queryByRole('button', { name: /^(Join|Leave|Add members)$/ })).toBeNull() }) it('says Join to a non-member and Leave to a member, and calls onToggle once', async () => { const user = userEvent.setup() const onToggle = vi.fn() const { rerender } = render( {}} />) await user.click(await screen.findByRole('button', { name: 'Join' })) expect(onToggle).toHaveBeenCalledTimes(1) rerender( {}} />) await user.click(await screen.findByRole('button', { name: 'Leave' })) expect(onToggle).toHaveBeenCalledTimes(2) }) it("puts Leave on the viewer's own row, and that row first", async () => { render( {}, id: 'me' }} onClose={() => {}} />) const leave = await screen.findByRole('button', { name: 'Leave' }) const row = leave.parentElement! expect(row.textContent).toContain('You') expect(row.parentElement!.textContent!.indexOf('You')).toBeLessThan(row.parentElement!.textContent!.indexOf('Ana Duarte')) }) it('keeps Leave on top when the viewer has no row of their own', async () => { render( {}, id: 'me' }} onClose={() => {}} />) expect(await screen.findByRole('button', { name: 'Leave' })).toBeTruthy() }) it('goes to the add layer and back, and Invite waits for a choice', async () => { const user = userEvent.setup() render( {}} onClose={() => {}} />) await user.click(await screen.findByRole('button', { name: 'Add members' })) expect((await screen.findByRole('button', { name: 'Invite' })).hasAttribute('disabled')).toBe(true) await user.click(screen.getByRole('button', { name: 'Back to members' })) expect(await screen.findByRole('button', { name: 'Add members' })).toBeTruthy() }) it('stays on the add layer when onAdd returns false', async () => { const user = userEvent.setup() const onAdd = vi.fn(() => false) render( {}} />) await user.type(await screen.findByRole('combobox'), 'Ravi') await user.click(await screen.findByRole('option', { name: /Ravi Mehta/ })) await user.click(screen.getByRole('button', { name: 'Invite' })) expect(onAdd).toHaveBeenCalledWith([{ id: 'ravi', label: 'Ravi Mehta' }]) expect(screen.getByRole('button', { name: 'Invite' })).toBeTruthy() }) }) describe('MembersPill', () => { it('names the total, and draws nothing for none', () => { const { container, rerender } = render( {}} />) expect(screen.getByRole('button', { name: '4 members' })).toBeTruthy() rerender() expect(container.textContent).toBe('') }) })