Skip to content

Commit

Permalink
Editable Tree tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Foxhoundn committed Jul 2, 2024
1 parent b5dd09f commit a368541
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 104 deletions.
115 changes: 11 additions & 104 deletions src/components/Tree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,9 @@ import { useMemo, useState } from 'react';
import styled from 'styled-components';
import {
ReqoreHorizontalSpacer,
ReqoreInput,
ReqoreModal,
ReqoreP,
ReqorePanel,
ReqorePopover,
ReqoreTag,
ReqoreTextarea,
useReqoreProperty,
} from '../..';
import { GAP_FROM_SIZE, TSizes } from '../../constants/sizes';
Expand All @@ -28,9 +24,9 @@ import { IWithReqoreSize } from '../../types/global';
import ReqoreButton, { IReqoreButtonProps } from '../Button';
import ReqoreControlGroup from '../ControlGroup';
import { ReqoreExportModal } from '../ExportModal';
import { IReqoreModalProps } from '../Modal';
import { IReqorePanelAction, IReqorePanelProps } from '../Panel';
import { getExportActions, getZoomActions, sizeToZoom, zoomToSize } from '../Table/helpers';
import { IReqoreTreeManagementDialog, ReqoreTreeManagementDialog } from './modal';

export interface IReqoreTreeProps extends IReqorePanelProps, IWithReqoreSize {
data: Record<string, unknown> | Array<any>;
Expand Down Expand Up @@ -67,104 +63,6 @@ export const StyledTreeWrapper = styled.div<ITreeStyle>`
margin-left: ${({ level, size }) => (level ? level * GAP_FROM_SIZE[size] : 0)}px;
`;

export interface IReqoreTreeManagementDialog extends IReqoreModalProps {
open?: boolean;
path?: string;
parentPath?: string;
type?: 'object' | 'array';
parentType?: 'object' | 'array';
data?: { key: string; value: any };
onSave?: (data: {
key: string;
value: any;
originalData?: { key?: string; value?: any };
}) => void;
}

export const ReqoreTreeManagementDialog = ({
path,
parentType,
type,
data,
onClose,
onSave,
}: IReqoreTreeManagementDialog) => {
const [key, setKey] = useState(data?.key);
const [value, setValue] = useState<any>(data?.value);

return (
<ReqoreModal
isOpen
label={path ? `Updating "${path}"` : 'Adding new item'}
onClose={onClose}
minimal
panelSize='small'
actions={[
{
intent: 'success',
disabled: type === 'object' ? !key || !value : !value,
label: 'Save',
icon: 'CheckLine',
onClick: () => {
onSave({
key,
value,
originalData: data,
});
onClose();
},
},
]}
>
<ReqoreControlGroup vertical>
{type === 'object' || (data?.key && parentType !== 'array') ? (
<ReqoreControlGroup fluid stack>
<ReqoreTag fixed width='100px' label='Key' />
<ReqoreInput
disabled={data && parentType === 'array'}
value={key}
onChange={(e) => setKey(e.target.value)}
placeholder='Key'
fluid
/>
</ReqoreControlGroup>
) : null}
{typeof data?.value !== 'object' && (
<ReqoreControlGroup fluid stack verticalAlign='flex-start'>
<ReqoreTag fixed width='100px' label='Value' />

<ReqoreTextarea
value={value}
scaleWithContent
onChange={(e: any) => setValue(e.target.value)}
placeholder='Value'
fluid
disabled={value === '[]' || value === '{}'}
/>
<ReqoreButton
fixed
onClick={() => (value === '[]' ? setValue('') : setValue('[]'))}
intent={value === '[]' ? 'info' : undefined}
compact
textAlign='center'
>
[...]
</ReqoreButton>
<ReqoreButton
fixed
onClick={() => (value === '{}' ? setValue('') : setValue('{}'))}
intent={value === '{}' ? 'info' : undefined}
compact
textAlign='center'
label='{...}'
/>
</ReqoreControlGroup>
)}
</ReqoreControlGroup>
</ReqoreModal>
);
};

export const ReqoreTree = ({
data,
size = 'normal',
Expand Down Expand Up @@ -253,6 +151,7 @@ export const ReqoreTree = ({
<ReqoreButton
compact
minimal
className='reqore-tree-edit'
icon='EditLine'
flat
size='tiny'
Expand Down Expand Up @@ -288,6 +187,7 @@ export const ReqoreTree = ({
compact
leftIconColor='muted'
minimal
className='reqore-tree-delete'
icon='IndeterminateCircleLine'
intent='muted'
flat
Expand All @@ -310,7 +210,12 @@ export const ReqoreTree = ({
};

return (
<StyledTreeWrapper key={index} size={zoomToSize[zoom]} level={level}>
<StyledTreeWrapper
key={index}
size={zoomToSize[zoom]}
level={level}
className='reqore-tree-item'
>
{isObject ? (
<ReqoreControlGroup size={zoomToSize[zoom]} verticalAlign='center'>
{level !== 1 && <ReqoreHorizontalSpacer width={5} />}
Expand Down Expand Up @@ -576,12 +481,14 @@ export const ReqoreTree = ({
actions={actions}
>
{renderTree(data)}

{editable && (
<StyledTreeWrapper size={zoomToSize[zoom]} level={1}>
<ReqoreButton
size={size}
flat
fixed
className='reqore-tree-add'
icon='AddCircleLine'
onClick={() => {
setManagementDialog({
Expand Down
108 changes: 108 additions & 0 deletions src/components/Tree/modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { useState } from 'react';
import { ReqoreTextarea } from '../..';
import ReqoreButton from '../Button';
import ReqoreControlGroup from '../ControlGroup';
import ReqoreInput from '../Input';
import { IReqoreModalProps, ReqoreModal } from '../Modal';
import ReqoreTag from '../Tag';

export interface IReqoreTreeManagementDialog extends IReqoreModalProps {
open?: boolean;
path?: string;
parentPath?: string;
type?: 'object' | 'array';
parentType?: 'object' | 'array';
data?: { key: string; value: any };
onSave?: (data: {
key: string;
value: any;
originalData?: { key?: string; value?: any };
}) => void;
}

export const ReqoreTreeManagementDialog = ({
path,
parentType,
type,
data,
onClose,
onSave,
}: IReqoreTreeManagementDialog) => {
const [key, setKey] = useState(data?.key);
const [value, setValue] = useState<any>(data?.value);

return (
<ReqoreModal
isOpen
label={path ? `Updating "${path}"` : 'Adding new item'}
onClose={onClose}
minimal
panelSize='small'
actions={[
{
intent: 'success',
className: 'reqore-tree-save',
disabled: type === 'object' ? !key || !value : !value,
label: 'Save',
icon: 'CheckLine',
onClick: () => {
onSave({
key,
value,
originalData: data,
});
onClose();
},
},
]}
>
<ReqoreControlGroup vertical>
{type === 'object' || (data?.key && parentType !== 'array') ? (
<ReqoreControlGroup fluid stack>
<ReqoreTag fixed width='100px' label='Key' />
<ReqoreInput
disabled={data && parentType === 'array'}
value={key}
onChange={(e) => setKey(e.target.value)}
placeholder='Key'
fluid
/>
</ReqoreControlGroup>
) : null}
{typeof data?.value !== 'object' && (
<ReqoreControlGroup fluid stack verticalAlign='flex-start'>
<ReqoreTag fixed width='100px' label='Value' />

<ReqoreTextarea
value={value}
scaleWithContent
onChange={(e: any) => setValue(e.target.value)}
placeholder='Value'
fluid
disabled={value === '[]' || value === '{}'}
/>
<ReqoreButton
fixed
className='reqore-tree-modal-list'
onClick={() => (value === '[]' ? setValue('') : setValue('[]'))}
intent={value === '[]' ? 'info' : undefined}
compact
textAlign='center'
>
[...]
</ReqoreButton>
<ReqoreButton
fixed
className='reqore-tree-modal-object'
onClick={() => (value === '{}' ? setValue('') : setValue('{}'))}
intent={value === '{}' ? 'info' : undefined}
compact
textAlign='center'
label='{...}'
/>
</ReqoreControlGroup>
)}
</ReqoreControlGroup>
</ReqoreModal>
);
};
81 changes: 81 additions & 0 deletions src/stories/Tree/Tree.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { expect } from '@storybook/jest';
import { StoryObj } from '@storybook/react';
import { fireEvent } from '@storybook/testing-library';
import { noop } from 'lodash';
import { useState } from 'react';
import { _testsClickButton, _testsWaitForText } from '../../../__tests__/utils';
import { IReqoreTreeProps, ReqoreTree } from '../../components/Tree';
import MockObject from '../../mock/object.json';
import { StoryMeta } from '../utils';
Expand Down Expand Up @@ -201,3 +204,81 @@ export const WithDefaultZoom: Story = {
defaultZoom: 2,
},
};

export const NewArrayItemCanBeAdded: Story = {
...EditableArray,
play: async () => {
await expect(document.querySelectorAll('.reqore-tree-item').length).toBe(8);
await _testsClickButton({ selector: '.reqore-tree-add' });
await _testsWaitForText('Adding new item');
await expect(document.querySelector('.reqore-tree-save')).toBeDisabled();
await fireEvent.change(document.querySelector('.reqore-textarea'), {
target: { value: 'New item' },
});
await expect(document.querySelector('.reqore-tree-save')).toBeEnabled();
await _testsClickButton({ selector: '.reqore-tree-save' });
await expect(document.querySelectorAll('.reqore-tree-item').length).toBe(9);
await _testsWaitForText('"New item"');
},
};

export const NewArrayItemCanBeEdited: Story = {
...NewArrayItemCanBeAdded,
play: async (args) => {
await NewArrayItemCanBeAdded.play(args);
await _testsClickButton({ selector: '.reqore-tree-edit' });
await fireEvent.change(document.querySelectorAll('.reqore-textarea')[0], {
target: { value: 'New item edited' },
});
await expect(document.querySelector('.reqore-tree-save')).toBeEnabled();
await _testsClickButton({ selector: '.reqore-tree-save' });
await expect(document.querySelectorAll('.reqore-tree-item').length).toBe(9);
await _testsWaitForText('"New item edited"');
},
};

export const NewObjectItemCanBeAdded: Story = {
...EditableObject,
play: async () => {
await expect(document.querySelectorAll('.reqore-tree-item').length).toBe(22);
await _testsClickButton({ selector: '.reqore-tree-add' });
await _testsWaitForText('Adding new item');
await expect(document.querySelector('.reqore-tree-save')).toBeDisabled();
await fireEvent.change(document.querySelector('.reqore-input'), {
target: { value: 'New item' },
});
await fireEvent.change(document.querySelectorAll('.reqore-textarea')[0], {
target: { value: 'New item value' },
});
await expect(document.querySelector('.reqore-tree-save')).toBeEnabled();
await _testsClickButton({ selector: '.reqore-tree-save' });
await expect(document.querySelectorAll('.reqore-tree-item').length).toBe(23);
await _testsWaitForText('New item:');
await _testsWaitForText('"New item value"');
},
};

export const ObjectItemCanBeEdited: Story = {
...EditableObject,
play: async () => {
await _testsClickButton({ selector: '.reqore-tree-edit', nth: 19 });
await fireEvent.change(document.querySelectorAll('.reqore-input')[0], {
target: { value: 'updated item key' },
});
await expect(document.querySelector('.reqore-tree-save')).toBeEnabled();
await _testsClickButton({ selector: '.reqore-tree-save' });
await expect(document.querySelectorAll('.reqore-tree-item').length).toBe(22);
await _testsWaitForText('updated item key');
await _testsClickButton({ label: 'updated item key' });
await _testsClickButton({ label: '1' });
},
};

export const ItemsCanBeDeleted: Story = {
...EditableObject,
play: async () => {
await _testsClickButton({ selector: '.reqore-tree-delete', nth: 4 });
await _testsClickButton({ selector: '.reqore-tree-delete', nth: 18 });
await expect(document.querySelectorAll('.reqore-tree-item').length).toBe(20);
},
};

0 comments on commit a368541

Please sign in to comment.