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
27 changes: 27 additions & 0 deletions ui/src/components/CustomSelect/__tests__/CustomSelect.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { render, screen } from '@testing-library/react';
import { expect, describe, it } from '@jest/globals';
import '@testing-library/jest-dom/jest-globals';
import '@testing-library/jest-dom';
import { ChakraProvider } from '@chakra-ui/react';
import { CustomSelect } from '../CustomSelect';
import { Option } from '../Option';

describe('CustomSelect', () => {
it('forwards data-testid to the toggle button', () => {
render(
<ChakraProvider>
<CustomSelect
value='one'
data-testid='connector-widget-select'
onChange={() => {}}
placeholder='Choose'
>
<Option value='one'>One</Option>
<Option value='two'>Two</Option>
</CustomSelect>
</ChakraProvider>,
);

expect(screen.getByTestId('connector-widget-select')).toBeInTheDocument();
});
});
46 changes: 46 additions & 0 deletions ui/src/components/DataTable/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
import { Table, Tbody, Td, Th, Thead, Tr } from '@chakra-ui/react';
import { flexRender, getCoreRowModel, useReactTable, ColumnDef, Row } from '@tanstack/react-table';
<<<<<<< HEAD
import { useState } from 'react';
=======
import { useState, ReactNode, ComponentProps } from 'react';

type DataTableRowProps = ComponentProps<typeof Tr>;
>>>>>>> deba42b89 (feat(CE): data-testid hooks for models, Data Apps, and workflows (#1835))

type DataTableProps<TData, TValue> = {
columns: ColumnDef<TData, TValue>[];
data: TData[];
onRowClick?: (row: Row<TData>) => void;
<<<<<<< HEAD
};

const DataTable = <TData, TValue>({ data, columns, onRowClick }: DataTableProps<TData, TValue>) => {
=======
noRowsComponent?: ReactNode;
getRowProps?: (row: Row<TData>) => DataTableRowProps;
};

const DataTable = <TData, TValue>({
data,
columns,
onRowClick,
noRowsComponent,
getRowProps,
}: DataTableProps<TData, TValue>) => {
>>>>>>> deba42b89 (feat(CE): data-testid hooks for models, Data Apps, and workflows (#1835))
const [rowSelection, setRowSelection] = useState({});

const table = useReactTable({
Expand Down Expand Up @@ -43,6 +63,7 @@ const DataTable = <TData, TValue>({ data, columns, onRowClick }: DataTableProps<
))}
</Thead>
<Tbody>
<<<<<<< HEAD
{table.getRowModel().rows.map((row) => (
<Tr
key={row.id}
Expand All @@ -57,6 +78,31 @@ const DataTable = <TData, TValue>({ data, columns, onRowClick }: DataTableProps<
))}
</Tr>
))}
=======
{table.getRowModel().rows.length > 0
? table.getRowModel().rows.map((row) => (
<Tr
key={row.id}
{...(getRowProps?.(row) ?? {})}
_hover={{ backgroundColor: 'gray.200', cursor: 'pointer' }}
onClick={() => onRowClick?.(row)}
backgroundColor='gray.100'
>
{row.getVisibleCells().map((cell) => (
<Td key={cell.id} padding='16px' maxWidth={'450px'}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</Td>
))}
</Tr>
))
: noRowsComponent && (
<Tr backgroundColor='gray.100'>
<Td colSpan={columns.length} padding='16px' textAlign='center'>
{noRowsComponent}
</Td>
</Tr>
)}
>>>>>>> deba42b89 (feat(CE): data-testid hooks for models, Data Apps, and workflows (#1835))
</Tbody>
</Table>
);
Expand Down
58 changes: 58 additions & 0 deletions ui/src/components/DataTable/__tests__/Table.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { render, screen, fireEvent } from '@testing-library/react';
import { expect, describe, it, jest } from '@jest/globals';
import '@testing-library/jest-dom/jest-globals';
import '@testing-library/jest-dom';
import { ChakraProvider } from '@chakra-ui/react';
import type { ColumnDef, Row as TanStackRow } from '@tanstack/react-table';
import DataTable from '../Table';

type RowData = { id: string; name: string };

describe('DataTable', () => {
const columns: ColumnDef<RowData, string>[] = [
{ accessorKey: 'name', header: 'Name', cell: (info) => info.getValue() },
];

const data: RowData[] = [
{ id: 'a', name: 'Alpha' },
{ id: 'b', name: 'Beta' },
];

it('merges getRowProps onto each row', () => {
render(
<ChakraProvider>
<DataTable
data={data}
columns={columns}
getRowProps={(row) => ({
'data-testid': `row-${row.original.id}`,
'data-row-label': row.original.name,
})}
/>
</ChakraProvider>,
);

const first = screen.getByTestId('row-a');
expect(first).toHaveAttribute('data-row-label', 'Alpha');
expect(screen.getByTestId('row-b')).toHaveAttribute('data-row-label', 'Beta');
});

it('invokes onRowClick with the row when a row is clicked', () => {
const onRowClick = jest.fn();
render(
<ChakraProvider>
<DataTable
data={data}
columns={columns}
getRowProps={(row) => ({ 'data-testid': `row-${row.original.id}` })}
onRowClick={onRowClick}
/>
</ChakraProvider>,
);

fireEvent.click(screen.getByTestId('row-a'));
expect(onRowClick).toHaveBeenCalledTimes(1);
const clicked = onRowClick.mock.calls[0][0] as TanStackRow<RowData>;
expect(clicked.original).toEqual(data[0]);
});
});
51 changes: 51 additions & 0 deletions ui/src/components/FormFooter/__tests__/FormFooter.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { ComponentProps } from 'react';
import { render, screen } from '@testing-library/react';
import { expect, describe, it } from '@jest/globals';
import '@testing-library/jest-dom/jest-globals';
import '@testing-library/jest-dom';
import { ChakraProvider } from '@chakra-ui/react';
import { MemoryRouter } from 'react-router-dom';
import FormFooter from '../FormFooter';

const renderFormFooter = (props: ComponentProps<typeof FormFooter>) =>
render(
<MemoryRouter>
<ChakraProvider>
<FormFooter {...props} />
</ChakraProvider>
</MemoryRouter>,
);

describe('FormFooter', () => {
it('exposes stepped-form data-testid derived from cta label for Continue', () => {
renderFormFooter({
ctaName: 'Continue',
isContinueCtaRequired: true,
});
expect(screen.getByTestId('stepped-form-continue')).toHaveTextContent('Continue');
});

it('normalizes cta label to kebab-case for data-testid', () => {
renderFormFooter({
ctaName: 'Save Changes',
isContinueCtaRequired: true,
});
expect(screen.getByTestId('stepped-form-save-changes')).toHaveTextContent('Save Changes');
});

it('collapses internal spaces in cta name for data-testid', () => {
renderFormFooter({
ctaName: 'Save Draft',
isContinueCtaRequired: true,
});
expect(screen.getByTestId('stepped-form-save-draft')).toBeInTheDocument();
});

it('does not render primary CTA when isContinueCtaRequired is false', () => {
renderFormFooter({
ctaName: 'Continue',
isContinueCtaRequired: false,
});
expect(screen.queryByTestId('stepped-form-continue')).not.toBeInTheDocument();
});
});
90 changes: 90 additions & 0 deletions ui/src/components/InputField/InputField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Box, Text, Input, Tooltip as ChakraTooltip } from '@chakra-ui/react';
import { FiInfo } from 'react-icons/fi';

type InputFieldProps = {
label: string;
name: string;
value: string;
onChange: React.ChangeEventHandler<HTMLInputElement> | undefined;
id?: string;
type?: 'text' | 'password' | 'number';
placeholder?: string;
helperText?: string;
isTooltip?: boolean;
tooltipLabel?: string;
disabled?: boolean;
isRequired?: boolean;
testId?: string;
};

const InputField = ({
label,
name,
onChange,
value,
id,
type = 'text',
placeholder = '',
helperText,
isTooltip = false,
tooltipLabel,
disabled = false,
isRequired = false,
testId,
}: InputFieldProps) => (
<Box width='100%' display='flex' flexDirection='column' gap='8px'>
<Box display='flex' alignItems='center' gap='4px'>
<Text fontWeight='semibold' size='sm'>
{label}
</Text>
{isRequired && (
<Text size='sm' color='error.400'>
*
</Text>
)}
{isTooltip && (
<ChakraTooltip
hasArrow
label={tooltipLabel}
fontSize='xs'
placement='top-start'
backgroundColor='black.500'
color='gray.100'
borderRadius='6px'
padding='8px'
>
<Text color='gray.600' data-testid='tooltip-trigger'>
<FiInfo />
</Text>
</ChakraTooltip>
)}
</Box>
<Input
id={id}
placeholder={placeholder}
backgroundColor='gray.100'
onChange={onChange}
value={value}
borderStyle='solid'
borderWidth='1px'
borderColor='gray.400'
fontSize='14px'
borderRadius='6px'
_placeholder={{ color: 'gray.600' }}
_focusVisible={{ borderColor: 'gray.400' }}
_hover={{ borderColor: 'gray.400' }}
name={name}
type={type}
required
data-testid={testId ?? 'input-field'}
disabled={disabled}
/>
{helperText && (
<Text fontWeight={500} size='xs' color='gray.600'>
{helperText}
</Text>
)}
</Box>
);

export default InputField;
Loading
Loading