feat(messaging-ui): rendered Messenger components — the drop-in UI
Turns the SDK from hooks-only into a real UI SDK: <Messenger> (conversation list + open thread + composer), plus <ConversationList> and <Thread>, all driven by the existing useConversations/useMessages hooks over the injected adapter — zero transport imports (boundary intact). - themeable via --miu-* CSS variables; default theme ships as ./styles.css - optimistic send, typing indicator, seen ticks, reactions display, unread badges - render smoke tests (jsdom + MockAdapter): mounts, auto-selects first thread, sends a message, switches threads (3 tests) — 48 total green - tsup: css bundled to dist/styles.css; dts scoped to TS entries Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { MessagingProvider } from '../provider';
|
||||
import { Messenger } from './messenger';
|
||||
import { MockAdapter } from '../adapters/mock';
|
||||
|
||||
function mount() {
|
||||
return render(
|
||||
<MessagingProvider adapter={new MockAdapter()}>
|
||||
<Messenger />
|
||||
</MessagingProvider>,
|
||||
);
|
||||
}
|
||||
|
||||
describe('<Messenger /> (rendered UI over an adapter)', () => {
|
||||
it('renders the conversation list and auto-selects the first thread', async () => {
|
||||
mount();
|
||||
// Seeded group conversation title from the mock.
|
||||
expect(await screen.findByText('Storm response — East side')).toBeTruthy();
|
||||
// Auto-selected thread shows its seeded message.
|
||||
expect(await screen.findByText('Crew is rolling out at 7.')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('sends a message through the adapter and shows it in the thread', async () => {
|
||||
mount();
|
||||
await screen.findByText('Crew is rolling out at 7.');
|
||||
|
||||
const input = screen.getByLabelText('Message') as HTMLInputElement;
|
||||
fireEvent.change(input, { target: { value: 'on our way' } });
|
||||
fireEvent.click(screen.getByText('Send'));
|
||||
|
||||
await waitFor(() => expect(screen.getByText('on our way')).toBeTruthy());
|
||||
// Composer cleared after send.
|
||||
expect(input.value).toBe('');
|
||||
});
|
||||
|
||||
it('switches threads when another conversation is clicked', async () => {
|
||||
mount();
|
||||
// Click the DM (its title is the other participant's name from the mock directory).
|
||||
fireEvent.click(await screen.findByText('Sofia Ramirez'));
|
||||
expect(await screen.findByText('Can you review the Henderson estimate?')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user