mentionChip.test.tsx2.4 KBView on GitHub
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import {
  MentionChip,
  parseCedarItemToken,
} from '@/modules/cedar-os/src/cedar-os-components/chatMessages/MentionChip';
import { useCedarStore } from '@/modules/cedar-os/src/store/CedarStore';
import { DEFAULT_THREAD_ID } from '@/modules/cedar-os/src/store/messages/MessageTypes';

/**
 * Phase 9 (design: chat-thread-store) — a committed mention renders as a clickable chip
 * in the transcript; clicking it sets selectedArtifact (opening the artifact column).
 */
describe('parseCedarItemToken', () => {
  it('parses a well-formed cedar-item token', () => {
    expect(parseCedarItemToken('cedar-item:conversation:conv_1')).toEqual({
      kind: 'conversation',
      id: 'conv_1',
    });
  });

  it('preserves ids that themselves contain a colon', () => {
    expect(parseCedarItemToken('cedar-item:slack_thread:C123:167.9')).toEqual({
      kind: 'slack_thread',
      id: 'C123:167.9',
    });
  });

  it('rejects non-tokens and malformed input', () => {
    expect(parseCedarItemToken('https://example.com')).toBeNull();
    expect(parseCedarItemToken('cedar-item:conversation')).toBeNull();
    expect(parseCedarItemToken('cedar-item::id')).toBeNull();
  });
});

describe('MentionChip', () => {
  beforeEach(() => {
    // selectedArtifact is now per-thread; seed an active thread for the click to write to.
    useCedarStore.setState((state) => ({
      ...state,
      threadMap: {
        [DEFAULT_THREAD_ID]: { id: DEFAULT_THREAD_ID, messages: [], selectedArtifact: null },
      },
      mainThreadId: DEFAULT_THREAD_ID,
      activeThreadId: DEFAULT_THREAD_ID,
    }));
  });

  it("renders its label and sets the active thread's selectedArtifact on click", () => {
    render(<MentionChip token=[redacted]>@Numeral</MentionChip>);

    const chip = screen.getByRole('button', { name: /Numeral/ });
    expect(chip).toBeInTheDocument();

    fireEvent.click(chip);
    expect(useCedarStore.getState().threadMap[DEFAULT_THREAD_ID].selectedArtifact).toEqual({
      kind: 'conversation',
      id: 'conv_1',
    });
  });

  it('renders children unchanged for a non-cedar-item token (no chip button)', () => {
    render(<MentionChip token=[redacted]>plain link</MentionChip>);
    expect(screen.queryByRole('button')).not.toBeInTheDocument();
    expect(screen.getByText('plain link')).toBeInTheDocument();
  });
});