Skip to content

Commit

Permalink
use StudioProperty.Button instead of StudioTextfieldToggleView
Browse files Browse the repository at this point in the history
  • Loading branch information
standeren committed Jan 17, 2025
1 parent 1ea3bf3 commit 5ab0fd3
Show file tree
Hide file tree
Showing 30 changed files with 206 additions and 314 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default meta;
export const Preview: Story = (args) => <StudioIconTextfield {...args}></StudioIconTextfield>;

Preview.args = {
Icon: PencilIcon,
icon: <PencilIcon />,
label: 'Write a text',
value: 2.3,
error: 'Your custom error message!',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,26 @@ import { testCustomAttributes } from '../../test-utils/testCustomAttributes';
describe('StudioIconTextfield', () => {
afterEach(jest.clearAllMocks);

it('render the icon', async () => {
it('should render label', () => {
renderStudioIconTextfield();
expect(screen.getByLabelText(label)).toBeInTheDocument();
});

it('should render value when provided', () => {
const value = 'value';
renderStudioIconTextfield({ value });
expect(screen.getByRole('textbox', { name: label })).toHaveValue(value);
});

it('render icon when provided', () => {
const icon = <KeyVerticalIcon />;
renderStudioIconTextfield({ icon });
expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument();
});

it('should render label', () => {
it('does not render the icon if not provided', () => {
renderStudioIconTextfield();
expect(screen.getByLabelText(label)).toBeInTheDocument();
expect(screen.queryByRole('img', { hidden: true })).not.toBeInTheDocument();
});

it('should execute onChange callback when input value changes', async () => {
Expand All @@ -38,7 +50,6 @@ describe('StudioIconTextfield', () => {
const label = 'label';
const onChange = jest.fn();
const defaultProps: StudioIconTextfieldProps = {
Icon: KeyVerticalIcon,
label,
onChange,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@ import React, { forwardRef } from 'react';
import { StudioTextfield, type StudioTextfieldProps } from '../StudioTextfield';
import cn from 'classnames';
import classes from './StudioIconTextfield.module.css';
import type { Override } from '../../types/Override';

export type StudioIconTextfieldProps = {
Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
label: string;
} & StudioTextfieldProps;
export type StudioIconTextfieldProps = Override<
{
icon?: React.ReactNode;
label: string;
},
StudioTextfieldProps
>;

export const StudioIconTextfield = forwardRef<HTMLDivElement, StudioIconTextfieldProps>(
(
{ Icon, label, className: givenClassName, ...rest }: StudioIconTextfieldProps,
{ icon, label, className: givenClassName, ...rest }: StudioIconTextfieldProps,
ref,
): React.ReactElement => {
const className = cn(givenClassName, classes.container);
return (
<div className={className} ref={ref}>
<Icon aria-hidden className={classes.prefixIcon} />
<StudioTextfield label={label} size='small' {...rest} className={classes.textfield} />
<div aria-hidden className={classes.prefixIcon}>
{icon}
</div>
<StudioTextfield className={classes.textfield} label={label} size='small' {...rest} />
</div>
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const ExampleUseCase: ExampleUseCase = (args): React.ReactElement => {
<StudioIconTextfield
error={name !== 'Bernard' ? 'Navnet må være Bernard' : ''}
onChange={(e) => setName(e.target.value)}
Icon={KeyVerticalIcon}
icon={<KeyVerticalIcon />}
size='sm'
label='Nytt navn'
/>
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,73 +17,75 @@ describe('StudioToggleableTextfield', () => {
afterEach(jest.clearAllMocks);

it('Renders the view mode by default', () => {
renderStudioTextField();
expect(screen.getByRole('button', { name: value })).toBeInTheDocument();
renderStudioToggleableTextfield();
expect(screen.getByRole('button', { name: label })).toBeInTheDocument();
expect(screen.getByRole('button', { name: label })).toHaveTextContent(value);
});

it('should toggle to edit-mode when edit button is clicked', async () => {
const user = userEvent.setup();
renderStudioTextField();
await user.click(screen.getByRole('button', { name: value }));
renderStudioToggleableTextfield();
await user.click(screen.getByRole('button', { name: label }));
expect(screen.getByRole('textbox', { name: label })).toBeInTheDocument();
expect(screen.getByRole('textbox', { name: label })).toHaveValue(value);
});

it('should run custom validation when value changes', async () => {
const user = userEvent.setup();
renderStudioTextField({ customValidation });
await user.click(screen.getByRole('button', { name: value }));
renderStudioToggleableTextfield({ customValidation });
await user.click(screen.getByRole('button', { name: label }));
const typedInputValue = 'John';
await user.type(screen.getByRole('textbox', { name: label }), typedInputValue);
expect(customValidation).toHaveBeenCalledTimes(typedInputValue.length);
});

it('should toggle back to view mode on blur', async () => {
const user = userEvent.setup();
renderStudioTextField();
const viewButton = screen.getByRole('button', { name: value });
renderStudioToggleableTextfield();
const viewButton = screen.getByRole('button', { name: label });
await user.click(viewButton);
const editTextfield = screen.getByRole('textbox', { name: label });
expect(editTextfield).toBeInTheDocument();
await user.tab();
expect(screen.getByRole('button', { name: value })).toBeInTheDocument();
expect(screen.getByRole('button', { name: label })).toBeInTheDocument();
});

it('should execute onBlur method when input is blurred', async () => {
const user = userEvent.setup();
renderStudioTextField();
await user.click(screen.getByRole('button', { name: value }));
renderStudioToggleableTextfield();
await user.click(screen.getByRole('button', { name: label }));
await user.tab();
expect(onBlur).toHaveBeenCalledTimes(1);
});

it('should not toggle view on blur when input field has error', async () => {
const user = userEvent.setup();
const error = 'Your name is a required field';
renderStudioTextField({ error });
await user.click(screen.getByRole('button', { name: value }));
renderStudioToggleableTextfield({ error });
await user.click(screen.getByRole('button', { name: label }));
await user.tab();
expect(screen.getByRole('textbox', { name: label })).toBeInvalid();
expect(screen.getByText(error)).toBeInTheDocument();
expect(screen.queryByRole('button', { name: value })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: label })).not.toBeInTheDocument();
});

it('should execute onChange method when input value changes', async () => {
const user = userEvent.setup();
renderStudioTextField();
renderStudioToggleableTextfield();
const inputValue = 'John';
await user.click(screen.getByRole('button', { name: value }));
await user.click(screen.getByRole('button', { name: label }));
await user.type(screen.getByRole('textbox', { name: label }), inputValue);
expect(onChange).toHaveBeenCalledTimes(inputValue.length);
});

it('should render error message if customValidation occured', async () => {
const user = userEvent.setup();
const customError = 'Your name cannot include "test"';
renderStudioTextField({
renderStudioToggleableTextfield({
customValidation: (valueToValidate: string) =>
valueToValidate.includes('test') ? customError : undefined,
});
await user.click(screen.getByRole('button', { name: value }));
await user.click(screen.getByRole('button', { name: label }));
await user.type(screen.getByRole('textbox', { name: label }), 'test');
expect(screen.getByText(customError));
});
Expand All @@ -97,6 +99,6 @@ const defaultProps: StudioToggleableTextfieldProps = {
customValidation,
};

const renderStudioTextField = (props: Partial<StudioToggleableTextfieldProps> = {}) => {
const renderStudioToggleableTextfield = (props: Partial<StudioToggleableTextfieldProps> = {}) => {
return render(<StudioToggleableTextfield {...defaultProps} {...props} />);
};
Loading

0 comments on commit 5ab0fd3

Please sign in to comment.