// @vitest-environment happy-dom // // Detail-dialog display mapping: the read-only `ViewValue` must render values // with the SAME "pro" display logic as the table (shared `display-value.tsx` // primitives), keyed off the stamped display type (`cellStyle ?? type`): // - served option → colored badge with the localized label, // - `cellStyle:'url'` on a text column → clickable external link (new tab), // - `cellStyle:'status'` bare token (kanban stage) → colored, translated pill, // - a `labels`/`tags` array → a row of badges (never a raw mini-table / JSON). import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, render, screen } from '@testing-library/react' // Identity-ish translator with a tiny stage dictionary, matching how the host // resolves an addon's i18n keys (t(token, { defaultValue })). vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (k: string, opts?: any) => k === 'backlog' ? 'Pendiente' : opts?.defaultValue ?? k, i18n: { language: 'es' }, }), })) import { ViewValue } from '../dialogs/dynamic-record' afterEach(cleanup) describe('ViewValue — detail dialog display mapping', () => { it('renders a served option as a colored badge with the localized label', () => { render( ) const badge = screen.getByText('Almacenable') expect(badge).toBeTruthy() // Never the raw enum token. expect(screen.queryByText('storable')).toBeNull() }) it('renders a cellStyle:url text column as a clickable external link', () => { const { container } = render( ) const link = container.querySelector('a') as HTMLAnchorElement expect(link).toBeTruthy() expect(link.getAttribute('href')).toBe('https://github.com/asteby/x') expect(link.getAttribute('target')).toBe('_blank') }) it('renders a bare stage token (cellStyle:status) as a translated colored pill', () => { const { container } = render( ) // Localized via the manifest i18n key, not the raw "backlog". expect(screen.getByText('Pendiente')).toBeTruthy() expect(container.textContent).not.toContain('backlog') // Colored: the badge carries an inline background style. const styled = container.querySelector('[style*="background"]') expect(styled).toBeTruthy() }) it('renders a labels array (cellStyle:tags) as a row of badges', () => { render( ) expect(screen.getByText('bug')).toBeTruthy() expect(screen.getByText('urgent')).toBeTruthy() }) it('renders label objects with color as colored badges', () => { render( ) expect(screen.getByText('Bug')).toBeTruthy() expect(screen.getByText('P1')).toBeTruthy() }) it('keeps the "—" empty marker for an empty labels array', () => { const { container } = render( ) expect(container.textContent).toContain('—') }) it('renders plain text external_id without a relation initials avatar', () => { const { container } = render( ) expect(screen.getByText('6a8c931523ea7')).toBeTruthy() // Must NOT render the InitialsAvatar lead ("6" chip) used for FKs. expect(container.querySelector('[data-slot="avatar"]')).toBeNull() expect(container.textContent).not.toMatch(/^6\s*6a8c/) }) it('renders nested provider_data objects as pretty JSON, not key: {…}', () => { render( ) expect(screen.getByText('03')).toBeTruthy() expect(screen.getByText(/"Folio": 950/)).toBeTruthy() expect(screen.queryByText(/Inv:\s*\{\.\.\.\}/i)).toBeNull() }) })