Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions apps/www/src/registry/components/alert/alert.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,36 @@ import { describe, expect, it } from 'vitest';
import { PdfAlert } from './alert';

describe('PdfAlert', () => {
it('renders without throwing', () => {
expect(() => PdfAlert({ title: 'Test' })).not.toThrow();
const variants = ['info', 'success', 'warning', 'error'] as const;

it('renders with title only', () => {
expect(() => PdfAlert({ title: 'Heads up' })).not.toThrow();
});

it('renders with string children only', () => {
expect(() => PdfAlert({ children: 'Body text' })).not.toThrow();
});

it('returns null when both title and children are missing', () => {
// alert.tsx:193 — early return null when there's nothing to render.
expect(PdfAlert({})).toBeNull();
});
it('accepts variant prop', () => {
expect(() => PdfAlert({ title: 'Test', variant: 'success' })).not.toThrow();

it('renders all variants with title and children', () => {
for (const variant of variants) {
expect(() => PdfAlert({ variant, title: 'T', children: 'Body' })).not.toThrow();
}
});

it('respects showIcon and showBorder toggles', () => {
expect(() => PdfAlert({ title: 'T', showIcon: false, showBorder: false })).not.toThrow();
expect(() => PdfAlert({ title: 'T', showIcon: true, showBorder: true })).not.toThrow();
expect(() => PdfAlert({ title: 'T', showIcon: false, showBorder: true })).not.toThrow();
expect(() => PdfAlert({ title: 'T', showIcon: true, showBorder: false })).not.toThrow();
});

it('accepts non-string children and style overrides', () => {
expect(() => PdfAlert({ title: 'T', children: null, style: { marginTop: 8 } })).not.toThrow();
expect(() => PdfAlert({ title: 'T', style: { marginTop: 8, padding: 4 } })).not.toThrow();
});
});
51 changes: 47 additions & 4 deletions apps/www/src/registry/components/badge/badge.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,53 @@ import { describe, expect, it } from 'vitest';
import { Badge } from './badge';

describe('Badge', () => {
it('renders without throwing', () => {
expect(() => Badge({ label: 'Test' })).not.toThrow();
const variants = [
'default',
'primary',
'success',
'warning',
'destructive',
'info',
'outline',
] as const;
const sizes = ['sm', 'md', 'lg'] as const;

it('renders with label', () => {
expect(() => Badge({ label: 'New' })).not.toThrow();
});

it('renders with string children when label is absent', () => {
expect(() => Badge({ children: 'Draft' })).not.toThrow();
});

it('label takes precedence over children (both branches are safe)', () => {
// badge.tsx:131 — `label ?? children ?? ''`
expect(() => Badge({ label: 'A', children: 'B' })).not.toThrow();
});

it('renders with neither label nor children (empty text fallback)', () => {
expect(() => Badge({})).not.toThrow();
});
it('accepts variant prop', () => {
expect(() => Badge({ label: 'Test', variant: 'primary' })).not.toThrow();

it('renders all variants', () => {
for (const variant of variants) {
expect(() => Badge({ label: 'x', variant })).not.toThrow();
}
});

it('renders all sizes', () => {
for (const size of sizes) {
expect(() => Badge({ label: 'x', size })).not.toThrow();
}
});

it('accepts background and color overrides (tokens and raw hex)', () => {
expect(() => Badge({ label: 'x', background: '#ff0', color: '#000' })).not.toThrow();
expect(() => Badge({ label: 'x', background: 'primary', color: 'foreground' })).not.toThrow();
});

it('accepts a style override', () => {
expect(() => Badge({ label: 'x', style: { marginLeft: 4 } })).not.toThrow();
expect(() => Badge({ label: 'x', style: { marginLeft: 4, opacity: 0.8 } })).not.toThrow();
});
});
50 changes: 46 additions & 4 deletions apps/www/src/registry/components/card/card.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,54 @@ import { describe, expect, it } from 'vitest';
import { PdfCard } from './card';

describe('PdfCard', () => {
it('renders without throwing', () => {
expect(() => PdfCard({ children: 'Content' })).not.toThrow();
const variants = ['default', 'bordered', 'muted'] as const;
const paddings = ['sm', 'md', 'lg'] as const;

it('renders with string children', () => {
expect(() => PdfCard({ children: 'Body' })).not.toThrow();
});

it('renders with title and string children', () => {
expect(() => PdfCard({ title: 'T', children: 'Body' })).not.toThrow();
});

it('renders with no content at all', () => {
expect(() => PdfCard({})).not.toThrow();
});

it('renders with non-string children (null pass-through)', () => {
// card.tsx:88 — non-string children are passed through without wrapping.
expect(() => PdfCard({ children: null })).not.toThrow();
});
it('accepts variant prop', () => {

it('renders all variants', () => {
for (const variant of variants) {
expect(() => PdfCard({ variant, children: 'x' })).not.toThrow();
}
});

it('renders all padding presets', () => {
for (const padding of paddings) {
expect(() => PdfCard({ padding, children: 'x' })).not.toThrow();
}
});

it('honors wrap prop in both modes', () => {
expect(() => PdfCard({ wrap: true, children: 'x' })).not.toThrow();
expect(() => PdfCard({ wrap: false, children: 'x' })).not.toThrow();
});

it('accepts a style override and combines with variant', () => {
expect(() => PdfCard({ children: 'x', style: { borderRadius: 12 } })).not.toThrow();
expect(() =>
PdfCard({ title: 'Test', variant: 'bordered', children: 'Content' })
PdfCard({
title: 'T',
variant: 'bordered',
padding: 'lg',
wrap: true,
children: 'x',
style: { marginTop: 8 },
})
).not.toThrow();
});
});
71 changes: 67 additions & 4 deletions apps/www/src/registry/components/data-table/data-table.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,74 @@
import { describe, expect, it } from 'vitest';
import { DataTable } from './data-table';
import type { DataTableColumn } from './data-table.types';

interface Row extends Record<string, unknown> {
name: string;
score: number;
status: string;
}

const columns: DataTableColumn<Row>[] = [
{ key: 'name', header: 'Name', align: 'left' },
{ key: 'score', header: 'Score', align: 'right', width: 80 },
{ key: 'status', header: 'Status', align: 'center' },
];

const data: Row[] = [
{ name: 'Ada', score: 99, status: 'active' },
{ name: 'Grace', score: 88, status: 'active' },
{ name: 'Linus', score: 77, status: 'inactive' },
];

describe('DataTable', () => {
it('renders without throwing', () => {
expect(() => DataTable({ columns: [], data: [] })).not.toThrow();
it('renders with empty columns and data', () => {
expect(() => DataTable<Row>({ columns: [], data: [] })).not.toThrow();
});

it('renders with columns but no rows', () => {
expect(() => DataTable<Row>({ columns, data: [] })).not.toThrow();
});

it('renders with rows and all column aligns/widths', () => {
expect(() => DataTable<Row>({ columns, data })).not.toThrow();
});
it('accepts size prop', () => {
expect(() => DataTable({ columns: [], data: [], size: 'compact' })).not.toThrow();

it('renders both size variants', () => {
expect(() => DataTable<Row>({ columns, data, size: 'default' })).not.toThrow();
expect(() => DataTable<Row>({ columns, data, size: 'compact' })).not.toThrow();
});

it('honors stripe, noWrap, and style overrides', () => {
expect(() =>
DataTable<Row>({
columns,
data,
stripe: true,
noWrap: true,
style: { marginTop: 8 },
})
).not.toThrow();
});

it('invokes custom cell render and footer render', () => {
const renderScore = (value: unknown) =>
typeof value === 'number' ? `${value}%` : String(value ?? '');
expect(() =>
DataTable<Row>({
columns: [
{ key: 'name', header: 'Name' },
{ key: 'score', header: 'Score', render: renderScore, renderFooter: renderScore },
],
data,
footer: { score: 264 },
})
).not.toThrow();
});
Comment on lines +53 to +66
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Test intent and assertion are mismatched for render callbacks.

Line 53 says callback invocation is tested, but the test only checks not.toThrow. This can pass even if render/renderFooter are never called.

Suggested fix
 it('invokes custom cell render and footer render', () => {
-  const renderScore = (value: unknown) =>
-    typeof value === 'number' ? `${value}%` : String(value ?? '');
+  let cellRenderCalled = false;
+  let footerRenderCalled = false;
+  const formatScore = (value: unknown) =>
+    typeof value === 'number' ? `${value}%` : String(value ?? '');
   expect(() =>
     DataTable<Row>({
       columns: [
         { key: 'name', header: 'Name' },
-        { key: 'score', header: 'Score', render: renderScore, renderFooter: renderScore },
+        {
+          key: 'score',
+          header: 'Score',
+          render: (value) => {
+            cellRenderCalled = true;
+            return formatScore(value);
+          },
+          renderFooter: (value) => {
+            footerRenderCalled = true;
+            return formatScore(value);
+          },
+        },
       ],
       data,
       footer: { score: 264 },
     })
   ).not.toThrow();
+  expect(cellRenderCalled).toBe(true);
+  expect(footerRenderCalled).toBe(true);
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/registry/components/data-table/data-table.test.tsx` around lines
53 - 66, The test currently only asserts DataTable<Row> instantiation does not
throw, but doesn't verify that the column render callbacks are actually invoked;
replace the inline renderScore with a jest.fn() spy (or wrap renderScore) and
render the DataTable component (using the same DataTable component factory or
React render from `@testing-library/react`) so that the table mounts and triggers
cell/footer rendering, then assert the spy was called for cell rendering and for
footer rendering (or assert rendered output contains the formatted values like
"264%"); update the test that references DataTable, renderScore, and the footer
prop to assert calls or rendered DOM instead of only not.toThrow().


it('renders table variants through the underlying Table', () => {
// data-table.tsx:24 — variant is forwarded to <Table variant={...}/>.
for (const variant of ['grid', 'striped', 'minimal', 'bordered'] as const) {
expect(() => DataTable<Row>({ columns, data, variant })).not.toThrow();
}
});
});
44 changes: 41 additions & 3 deletions apps/www/src/registry/components/divider/divider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,48 @@ import { describe, expect, it } from 'vitest';
import { Divider } from './divider';

describe('Divider', () => {
it('renders without throwing', () => {
const variants = ['solid', 'dashed', 'dotted'] as const;
const thicknesses = ['thin', 'medium', 'thick'] as const;
const spacings = ['none', 'sm', 'md', 'lg'] as const;

it('renders with no props', () => {
expect(() => Divider({})).not.toThrow();
});
it('accepts variant prop', () => {
expect(() => Divider({ variant: 'dashed' })).not.toThrow();

it('renders all variants', () => {
for (const variant of variants) {
expect(() => Divider({ variant })).not.toThrow();
}
});

it('renders all thicknesses', () => {
for (const thickness of thicknesses) {
expect(() => Divider({ thickness })).not.toThrow();
}
});

it('renders all spacing presets', () => {
for (const spacing of spacings) {
expect(() => Divider({ spacing })).not.toThrow();
}
});

it('renders the labeled branch', () => {
expect(() => Divider({ label: 'OR' })).not.toThrow();
// Labeled divider still honors variant/thickness/spacing.
for (const variant of variants) {
expect(() =>
Divider({ label: 'Section', variant, thickness: 'medium', spacing: 'lg' })
).not.toThrow();
}
});

it('accepts width (number and string), color token, and style override', () => {
expect(() => Divider({ width: 200 })).not.toThrow();
expect(() => Divider({ width: '50%' })).not.toThrow();
expect(() => Divider({ color: 'primary' })).not.toThrow();
expect(() => Divider({ color: '#cccccc' })).not.toThrow();
expect(() => Divider({ label: 'OR', color: 'primary', width: '75%' })).not.toThrow();
expect(() => Divider({ style: { marginTop: 8 } })).not.toThrow();
});
});
71 changes: 68 additions & 3 deletions apps/www/src/registry/components/form/form.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,76 @@
import { describe, expect, it } from 'vitest';
import { PdfForm } from './form';
import type { PdfFormGroup } from './form.types';

describe('PdfForm', () => {
it('renders without throwing', () => {
const variants = ['underline', 'box', 'outlined', 'ghost'] as const;
const layouts = ['single', 'two-column', 'three-column'] as const;

const baseGroup: PdfFormGroup = {
title: 'Contact',
fields: [
{ label: 'Name' },
{ label: 'Email', hint: '[email protected]' },
{ label: 'Phone', height: 24 },
],
};

it('renders with empty groups array', () => {
expect(() => PdfForm({ groups: [] })).not.toThrow();
});
it('accepts layout prop', () => {
expect(() => PdfForm({ groups: [], variant: 'box' })).not.toThrow();

it('renders all variants', () => {
for (const variant of variants) {
expect(() => PdfForm({ groups: [baseGroup], variant })).not.toThrow();
}
});

it('renders all column layouts', () => {
for (const layout of layouts) {
expect(() => PdfForm({ groups: [{ ...baseGroup, layout }] })).not.toThrow();
}
});

it('renders both labelPositions', () => {
for (const labelPosition of ['above', 'left'] as const) {
expect(() => PdfForm({ groups: [baseGroup], labelPosition })).not.toThrow();
}
});

it('renders with title/subtitle (adds form divider)', () => {
// form.tsx:108 — title or subtitle triggers the formDivider row.
expect(() =>
PdfForm({ title: 'Application', subtitle: 'Fill every field', groups: [baseGroup] })
).not.toThrow();
expect(() => PdfForm({ title: 'Application', groups: [baseGroup] })).not.toThrow();
expect(() => PdfForm({ subtitle: 'Only', groups: [baseGroup] })).not.toThrow();
});

it('renders groups with no title, empty fields, and uneven column chunks', () => {
expect(() => PdfForm({ groups: [{ fields: [] }] })).not.toThrow();
expect(() =>
PdfForm({
groups: [
{ fields: [{ label: 'A' }], layout: 'three-column' },
{ fields: [{ label: 'A' }, { label: 'B' }], layout: 'three-column' },
{
fields: [
{ label: 'A' },
{ label: 'B' },
{ label: 'C' },
{ label: 'D' },
{ label: 'E' },
],
layout: 'two-column',
},
],
})
).not.toThrow();
});

it('accepts noWrap and a style override', () => {
expect(() =>
PdfForm({ groups: [baseGroup], noWrap: true, style: { padding: 12 } })
).not.toThrow();
});
});
Loading