@strato-admin/cloudscape 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Admin.d.ts +6 -2
- package/dist/Admin.js +14 -8
- package/dist/RecordLink.js +5 -4
- package/dist/Settings.d.ts +17 -0
- package/dist/Settings.js +14 -0
- package/dist/button/BulkDeleteButton.d.ts +4 -1
- package/dist/button/BulkDeleteButton.js +37 -5
- package/dist/button/Button.d.ts +2 -1
- package/dist/button/CancelButton.d.ts +6 -0
- package/dist/button/CancelButton.js +10 -0
- package/dist/button/CreateButton.js +9 -8
- package/dist/button/DeleteButton.d.ts +13 -0
- package/dist/button/DeleteButton.js +36 -0
- package/dist/button/EditButton.d.ts +1 -1
- package/dist/button/EditButton.js +10 -10
- package/dist/button/SaveButton.js +2 -2
- package/dist/button/index.d.ts +2 -0
- package/dist/button/index.js +2 -0
- package/dist/collection-hooks/interfaces.d.ts +7 -3
- package/dist/collection-hooks/useCollection.d.ts +1 -1
- package/dist/collection-hooks/useCollection.js +15 -10
- package/dist/create/Create.d.ts +9 -17
- package/dist/create/Create.js +40 -12
- package/dist/create/CreateHeader.d.ts +2 -2
- package/dist/create/CreateHeader.js +4 -5
- package/dist/defaults.d.ts +6 -0
- package/dist/defaults.js +21 -0
- package/dist/detail/Detail.d.ts +33 -0
- package/dist/detail/Detail.js +22 -0
- package/dist/detail/DetailHeader.d.ts +11 -0
- package/dist/detail/{ShowHeader.js → DetailHeader.js} +7 -5
- package/dist/detail/DetailHub.d.ts +27 -0
- package/dist/detail/DetailHub.js +63 -0
- package/dist/detail/KeyValuePairs.d.ts +7 -1
- package/dist/detail/KeyValuePairs.js +14 -8
- package/dist/detail/index.d.ts +3 -2
- package/dist/detail/index.js +3 -2
- package/dist/edit/Edit.d.ts +8 -19
- package/dist/edit/Edit.js +48 -12
- package/dist/edit/EditHeader.d.ts +2 -2
- package/dist/edit/EditHeader.js +5 -4
- package/dist/field/ArrayField.d.ts +26 -10
- package/dist/field/ArrayField.js +38 -10
- package/dist/field/BadgeField.d.ts +1 -1
- package/dist/field/BadgeField.js +1 -1
- package/dist/field/BooleanField.d.ts +1 -1
- package/dist/field/BooleanField.js +2 -2
- package/dist/field/CurrencyField.d.ts +1 -1
- package/dist/field/CurrencyField.js +1 -1
- package/dist/field/DateField.d.ts +1 -1
- package/dist/field/DateField.js +1 -1
- package/dist/field/IdField.d.ts +1 -1
- package/dist/field/IdField.js +3 -3
- package/dist/field/NumberField.d.ts +1 -1
- package/dist/field/NumberField.js +1 -1
- package/dist/field/ReferenceField.d.ts +1 -1
- package/dist/field/ReferenceField.js +4 -2
- package/dist/field/ReferenceManyField.d.ts +35 -4
- package/dist/field/ReferenceManyField.js +17 -4
- package/dist/field/StatusIndicatorField.d.ts +1 -1
- package/dist/field/StatusIndicatorField.js +6 -5
- package/dist/field/TextField.d.ts +1 -1
- package/dist/field/TextField.js +1 -1
- package/dist/field/types.d.ts +9 -9
- package/dist/form/Form.d.ts +12 -2
- package/dist/form/Form.js +10 -16
- package/dist/form/index.d.ts +1 -1
- package/dist/form/index.js +1 -1
- package/dist/hooks/useSchemaFields.d.ts +22 -0
- package/dist/hooks/useSchemaFields.js +45 -0
- package/dist/i18n/Message.d.ts +15 -0
- package/dist/i18n/Message.js +19 -0
- package/dist/i18n/RecordMessage.d.ts +14 -0
- package/dist/i18n/RecordMessage.js +16 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/index.js +2 -0
- package/dist/i18n/types.d.ts +19 -0
- package/dist/i18n/types.js +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/dist/input/ArrayInput.d.ts +33 -0
- package/dist/input/{AttributeEditor.js → ArrayInput.js} +18 -11
- package/dist/input/AutocompleteInput.d.ts +1 -1
- package/dist/input/AutocompleteInput.js +3 -3
- package/dist/input/BooleanInput.d.ts +6 -0
- package/dist/input/BooleanInput.js +23 -0
- package/dist/input/CommonInputProps.d.ts +6 -0
- package/dist/input/CommonInputProps.js +6 -0
- package/dist/input/FieldTitle.js +4 -4
- package/dist/input/FormField.js +12 -3
- package/dist/input/FormFieldContext.d.ts +1 -1
- package/dist/input/NumberInput.d.ts +1 -1
- package/dist/input/NumberInput.js +3 -3
- package/dist/input/ReferenceInput.d.ts +1 -1
- package/dist/input/ReferenceInput.js +22 -12
- package/dist/input/SelectInput.d.ts +1 -1
- package/dist/input/SelectInput.js +3 -3
- package/dist/input/SliderInput.d.ts +1 -1
- package/dist/input/SliderInput.js +4 -4
- package/dist/input/TextAreaInput.d.ts +1 -1
- package/dist/input/TextAreaInput.js +3 -3
- package/dist/input/TextInput.d.ts +1 -1
- package/dist/input/TextInput.js +6 -12
- package/dist/input/index.d.ts +2 -1
- package/dist/input/index.js +2 -1
- package/dist/input/types.d.ts +33 -2
- package/dist/layout/AppLayout.js +6 -3
- package/dist/layout/Notifications.d.ts +1 -0
- package/dist/layout/Notifications.js +51 -0
- package/dist/layout/Ready.d.ts +6 -0
- package/dist/layout/Ready.js +24 -0
- package/dist/layout/TopNavigation.d.ts +4 -2
- package/dist/layout/TopNavigation.js +7 -7
- package/dist/layout/index.d.ts +2 -0
- package/dist/layout/index.js +2 -0
- package/dist/list/Cards.d.ts +31 -4
- package/dist/list/Cards.js +81 -10
- package/dist/list/List.d.ts +9 -12
- package/dist/list/List.js +41 -11
- package/dist/list/Table.d.ts +8 -4
- package/dist/list/Table.js +55 -55
- package/dist/list/TableHeader.d.ts +2 -2
- package/dist/list/TableHeader.js +4 -5
- package/dist/theme/ThemeManager.js +1 -1
- package/package.json +9 -6
- package/src/Admin.tsx +35 -18
- package/src/RecordLink.stories.tsx +1 -1
- package/src/RecordLink.tsx +5 -4
- package/src/Settings.tsx +16 -0
- package/src/__mocks__/ra-core.tsx +83 -0
- package/src/__mocks__/strato-core.tsx +36 -42
- package/src/button/BulkDeleteButton.test.tsx +45 -8
- package/src/button/BulkDeleteButton.tsx +75 -12
- package/src/button/Button.tsx +31 -2
- package/src/button/CancelButton.tsx +20 -0
- package/src/button/CreateButton.tsx +12 -10
- package/src/button/DeleteButton.tsx +96 -0
- package/src/button/EditButton.tsx +13 -12
- package/src/button/SaveButton.tsx +2 -3
- package/src/button/index.ts +2 -0
- package/src/collection-hooks/interfaces.ts +7 -3
- package/src/collection-hooks/useCollection.test.ts +115 -2
- package/src/collection-hooks/useCollection.ts +15 -10
- package/src/create/Create.test.tsx +3 -3
- package/src/create/Create.tsx +68 -37
- package/src/create/CreateHeader.tsx +6 -10
- package/src/defaults.tsx +28 -0
- package/src/detail/Detail-CollectionFields.test.tsx +84 -0
- package/src/detail/Detail.test.tsx +91 -0
- package/src/detail/Detail.tsx +48 -0
- package/src/detail/{ShowHeader.test.tsx → DetailHeader.test.tsx} +11 -9
- package/src/detail/DetailHeader.tsx +42 -0
- package/src/detail/DetailHub.tsx +88 -0
- package/src/detail/KeyValuePairs.test.tsx +2 -2
- package/src/detail/KeyValuePairs.tsx +25 -18
- package/src/detail/index.ts +3 -2
- package/src/edit/Edit.test.tsx +7 -5
- package/src/edit/Edit.tsx +92 -40
- package/src/edit/EditHeader.tsx +7 -5
- package/src/field/ArrayField.tsx +57 -11
- package/src/field/BadgeField.tsx +2 -3
- package/src/field/BooleanField.test.tsx +2 -3
- package/src/field/BooleanField.tsx +3 -3
- package/src/field/CurrencyField.tsx +1 -1
- package/src/field/DateField.tsx +1 -1
- package/src/field/IdField.test.tsx +8 -20
- package/src/field/IdField.tsx +5 -20
- package/src/field/NumberField.tsx +1 -1
- package/src/field/ReferenceField.test.tsx +15 -6
- package/src/field/ReferenceField.tsx +10 -7
- package/src/field/ReferenceManyField.test.tsx +55 -10
- package/src/field/ReferenceManyField.tsx +84 -13
- package/src/field/StatusIndicatorField.test.tsx +7 -21
- package/src/field/StatusIndicatorField.tsx +8 -20
- package/src/field/TextField.tsx +1 -1
- package/src/field/types.ts +12 -13
- package/src/form/Form.test.tsx +8 -4
- package/src/form/Form.tsx +24 -19
- package/src/form/index.ts +1 -1
- package/src/hooks/useSchemaFields.ts +89 -0
- package/src/i18n/Message.tsx +22 -0
- package/src/i18n/RecordMessage.tsx +22 -0
- package/src/i18n/index.ts +3 -0
- package/src/i18n/types.ts +19 -0
- package/src/index.ts +5 -1
- package/src/input/ArrayInput.test.tsx +81 -0
- package/src/input/{AttributeEditor.tsx → ArrayInput.tsx} +36 -18
- package/src/input/AutocompleteInput.test.tsx +2 -4
- package/src/input/AutocompleteInput.tsx +9 -11
- package/src/input/BooleanInput.tsx +42 -0
- package/src/input/CommonInputProps.tsx +8 -0
- package/src/input/FieldTitle.tsx +3 -15
- package/src/input/FormField.tsx +78 -67
- package/src/input/FormFieldContext.ts +1 -1
- package/src/input/NumberInput.tsx +10 -7
- package/src/input/ReferenceInput.test.tsx +12 -2
- package/src/input/ReferenceInput.tsx +32 -14
- package/src/input/SelectInput.tsx +14 -17
- package/src/input/SliderInput.test.tsx +2 -3
- package/src/input/SliderInput.tsx +48 -38
- package/src/input/TextAreaInput.tsx +10 -6
- package/src/input/TextInput.test.tsx +2 -4
- package/src/input/TextInput.tsx +35 -20
- package/src/input/index.ts +2 -1
- package/src/input/types.ts +40 -8
- package/src/layout/AppLayout.test.tsx +23 -3
- package/src/layout/AppLayout.tsx +11 -8
- package/src/layout/Notifications.test.tsx +102 -0
- package/src/layout/Notifications.tsx +61 -0
- package/src/layout/Ready.tsx +123 -0
- package/src/layout/TopNavigation.test.tsx +2 -3
- package/src/layout/TopNavigation.tsx +9 -8
- package/src/layout/index.ts +2 -0
- package/src/list/Cards.test.tsx +320 -0
- package/src/list/Cards.tsx +146 -16
- package/src/list/List.tsx +87 -26
- package/src/list/Table.test.tsx +40 -5
- package/src/list/Table.tsx +89 -98
- package/src/list/TableHeader.test.tsx +15 -11
- package/src/list/TableHeader.tsx +6 -8
- package/src/theme/ThemeManager.tsx +1 -1
- package/dist/__mocks__/strato-core.js +0 -50
- package/dist/__mocks__to__delete/strato-core.js +0 -50
- package/dist/detail/Show.d.ts +0 -39
- package/dist/detail/Show.js +0 -40
- package/dist/detail/ShowHeader.d.ts +0 -7
- package/dist/input/AttributeEditor.d.ts +0 -25
- package/src/detail/Show.test.tsx +0 -96
- package/src/detail/Show.tsx +0 -104
- package/src/detail/ShowHeader.tsx +0 -35
- package/src/input/AttributeEditor.test.tsx +0 -147
package/src/detail/Show.test.tsx
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
4
|
-
import { useShowContext, useResourceContext } from '@strato-admin/core';
|
|
5
|
-
import Show from './Show';
|
|
6
|
-
|
|
7
|
-
// Mock strato-core
|
|
8
|
-
vi.mock('@strato-admin/core', () => import('../__mocks__/strato-core'));
|
|
9
|
-
|
|
10
|
-
// Mock react-router-dom
|
|
11
|
-
vi.mock('react-router-dom', () => ({
|
|
12
|
-
useNavigate: vi.fn(),
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
// Mock Cloudscape components
|
|
16
|
-
vi.mock('@cloudscape-design/components/container', () => ({
|
|
17
|
-
default: ({ children, header }: any) => (
|
|
18
|
-
<div data-testid="container">
|
|
19
|
-
<div data-testid="container-header">{header}</div>
|
|
20
|
-
<div data-testid="container-content">{children}</div>
|
|
21
|
-
</div>
|
|
22
|
-
),
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
vi.mock('@cloudscape-design/components/header', () => ({
|
|
26
|
-
default: ({ children, actions }: any) => (
|
|
27
|
-
<header>
|
|
28
|
-
<div>{children}</div>
|
|
29
|
-
<div>{actions}</div>
|
|
30
|
-
</header>
|
|
31
|
-
),
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
vi.mock('@cloudscape-design/components/space-between', () => ({
|
|
35
|
-
default: ({ children }: any) => <div>{children}</div>,
|
|
36
|
-
}));
|
|
37
|
-
|
|
38
|
-
vi.mock('@cloudscape-design/components/button', () => ({
|
|
39
|
-
default: ({ children }: any) => <button>{children}</button>,
|
|
40
|
-
}));
|
|
41
|
-
|
|
42
|
-
describe('Show', () => {
|
|
43
|
-
beforeEach(() => {
|
|
44
|
-
vi.clearAllMocks();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should render nothing when loading', () => {
|
|
48
|
-
(useShowContext as any).mockReturnValue({
|
|
49
|
-
isLoading: true,
|
|
50
|
-
record: undefined,
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const { queryByTestId } = render(
|
|
54
|
-
<Show>
|
|
55
|
-
<div data-testid="content" />
|
|
56
|
-
</Show>,
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
expect(queryByTestId('container')).toBeNull();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should render content and title when record is loaded', () => {
|
|
63
|
-
(useShowContext as any).mockReturnValue({
|
|
64
|
-
isLoading: false,
|
|
65
|
-
record: { id: 1 }, defaultTitle: 'Products',
|
|
66
|
-
resource: 'products',
|
|
67
|
-
});
|
|
68
|
-
(useResourceContext as any).mockReturnValue('products');
|
|
69
|
-
|
|
70
|
-
const { getByTestId, getByText } = render(
|
|
71
|
-
<Show>
|
|
72
|
-
<div data-testid="content">Hello World</div>
|
|
73
|
-
</Show>,
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
expect(getByTestId('container')).toBeDefined();
|
|
77
|
-
expect(getByTestId('content').textContent).toBe('Hello World');
|
|
78
|
-
expect(getByText('Products')).toBeDefined();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('should use provided title', () => {
|
|
82
|
-
(useShowContext as any).mockReturnValue({
|
|
83
|
-
isLoading: false,
|
|
84
|
-
record: { id: 1 }, defaultTitle: 'Products',
|
|
85
|
-
resource: 'products',
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const { getByText } = render(
|
|
89
|
-
<Show title="My Product">
|
|
90
|
-
<div />
|
|
91
|
-
</Show>,
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
expect(getByText('My Product')).toBeDefined();
|
|
95
|
-
});
|
|
96
|
-
});
|
package/src/detail/Show.tsx
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ShowBase, useShowContext, type RaRecord, ResourceSchemaProvider } from '@strato-admin/core';
|
|
3
|
-
import Container from '@cloudscape-design/components/container';
|
|
4
|
-
import SpaceBetween from '@cloudscape-design/components/space-between';
|
|
5
|
-
import { ShowHeader } from './ShowHeader';
|
|
6
|
-
import KeyValuePairs from './KeyValuePairs';
|
|
7
|
-
|
|
8
|
-
export interface ShowProps<_RecordType extends RaRecord = RaRecord> {
|
|
9
|
-
children?: React.ReactNode;
|
|
10
|
-
fieldSchema?: React.ReactNode;
|
|
11
|
-
title?: React.ReactNode;
|
|
12
|
-
actions?: React.ReactNode;
|
|
13
|
-
resource?: string;
|
|
14
|
-
id?: any;
|
|
15
|
-
queryOptions?: any;
|
|
16
|
-
include?: string[];
|
|
17
|
-
exclude?: string[];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const ShowUI = ({
|
|
21
|
-
children,
|
|
22
|
-
resource,
|
|
23
|
-
fieldSchema,
|
|
24
|
-
title,
|
|
25
|
-
actions,
|
|
26
|
-
include,
|
|
27
|
-
exclude,
|
|
28
|
-
}: {
|
|
29
|
-
children?: React.ReactNode;
|
|
30
|
-
resource?: string;
|
|
31
|
-
fieldSchema?: React.ReactNode;
|
|
32
|
-
title?: React.ReactNode;
|
|
33
|
-
actions?: React.ReactNode;
|
|
34
|
-
include?: string[];
|
|
35
|
-
exclude?: string[];
|
|
36
|
-
}) => {
|
|
37
|
-
const { record, isLoading } = useShowContext();
|
|
38
|
-
|
|
39
|
-
if (isLoading || !record) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const finalChildren = children || <KeyValuePairs include={include} exclude={exclude} />;
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<ResourceSchemaProvider resource={resource} fieldSchema={fieldSchema}>
|
|
47
|
-
<Container header={<ShowHeader title={title} actions={actions} />}>
|
|
48
|
-
<SpaceBetween direction="vertical" size="l">
|
|
49
|
-
{finalChildren}
|
|
50
|
-
</SpaceBetween>
|
|
51
|
-
</Container>
|
|
52
|
-
</ResourceSchemaProvider>
|
|
53
|
-
);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* A Show component that provides record context and a Cloudscape Container.
|
|
58
|
-
*
|
|
59
|
-
* @example
|
|
60
|
-
* <Show>
|
|
61
|
-
* <KeyValuePairs>
|
|
62
|
-
* <TextField source="name" />
|
|
63
|
-
* <NumberField source="price" />
|
|
64
|
-
* </KeyValuePairs>
|
|
65
|
-
* </Show>
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* // Using FieldSchema from context
|
|
69
|
-
* <Show include={['name', 'price']} />
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* // Passing a custom field schema
|
|
73
|
-
* <Show fieldSchema={<FieldSchema>...</FieldSchema>}>
|
|
74
|
-
* <KeyValuePairs />
|
|
75
|
-
* </Show>
|
|
76
|
-
*/
|
|
77
|
-
export const Show = <RecordType extends RaRecord = RaRecord>({
|
|
78
|
-
children,
|
|
79
|
-
fieldSchema,
|
|
80
|
-
title,
|
|
81
|
-
actions,
|
|
82
|
-
include,
|
|
83
|
-
exclude,
|
|
84
|
-
...props
|
|
85
|
-
}: ShowProps<RecordType>) => {
|
|
86
|
-
return (
|
|
87
|
-
<ShowBase {...props}>
|
|
88
|
-
<ShowUI
|
|
89
|
-
resource={props.resource}
|
|
90
|
-
title={title}
|
|
91
|
-
actions={actions}
|
|
92
|
-
include={include}
|
|
93
|
-
exclude={exclude}
|
|
94
|
-
fieldSchema={fieldSchema}
|
|
95
|
-
>
|
|
96
|
-
{children}
|
|
97
|
-
</ShowUI>
|
|
98
|
-
</ShowBase>
|
|
99
|
-
);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
Show.Header = ShowHeader;
|
|
103
|
-
|
|
104
|
-
export default Show;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import Header, { HeaderProps } from '@cloudscape-design/components/header';
|
|
3
|
-
import SpaceBetween from '@cloudscape-design/components/space-between';
|
|
4
|
-
import { useResourceContext, useShowContext, useTranslate, useResourceDefinitions } from '@strato-admin/core';
|
|
5
|
-
import { EditButton } from '../button/EditButton';
|
|
6
|
-
|
|
7
|
-
export interface ShowHeaderProps extends Omit<HeaderProps, 'children'> {
|
|
8
|
-
title?: React.ReactNode;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const ShowHeader = ({ title, actions, ...props }: ShowHeaderProps) => {
|
|
12
|
-
const translate = useTranslate();
|
|
13
|
-
const { record, defaultTitle } = useShowContext();
|
|
14
|
-
|
|
15
|
-
const headerTitle = React.useMemo(() => {
|
|
16
|
-
if (title !== undefined) {
|
|
17
|
-
return typeof title === 'string' ? translate(title, { _: title }) : title;
|
|
18
|
-
}
|
|
19
|
-
return defaultTitle;
|
|
20
|
-
}, [title, defaultTitle, translate]);
|
|
21
|
-
|
|
22
|
-
const headerActions = actions || (
|
|
23
|
-
<SpaceBetween direction="horizontal" size="xs">
|
|
24
|
-
<EditButton record={record} />
|
|
25
|
-
</SpaceBetween>
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<Header variant="h2" {...props} actions={headerActions}>
|
|
30
|
-
{headerTitle}
|
|
31
|
-
</Header>
|
|
32
|
-
);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export default ShowHeader;
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
4
|
-
import { AttributeEditor } from './AttributeEditor';
|
|
5
|
-
import { useFormContext, useFieldArray } from 'react-hook-form';
|
|
6
|
-
import { useInput, useResourceContext } from '@strato-admin/core';
|
|
7
|
-
import { useFormFieldContext } from './FormFieldContext';
|
|
8
|
-
|
|
9
|
-
// Mock Cloudscape components
|
|
10
|
-
vi.mock('@cloudscape-design/components/attribute-editor', () => ({
|
|
11
|
-
default: ({ items, definition, onAddButtonClick, disableAddButton, hideAddButton }: any) => (
|
|
12
|
-
<div data-testid="attribute-editor">
|
|
13
|
-
{!hideAddButton && (
|
|
14
|
-
<button onClick={onAddButtonClick} disabled={disableAddButton} data-testid="add-button">
|
|
15
|
-
Add item
|
|
16
|
-
</button>
|
|
17
|
-
)}
|
|
18
|
-
{items.map((item: any, index: number) => (
|
|
19
|
-
<div key={index} data-testid={`item-${index}`}>
|
|
20
|
-
{definition.map((def: any, defIndex: number) => (
|
|
21
|
-
<div key={defIndex} data-testid={`field-${defIndex}`}>
|
|
22
|
-
{def.control(item, index)}
|
|
23
|
-
</div>
|
|
24
|
-
))}
|
|
25
|
-
</div>
|
|
26
|
-
))}
|
|
27
|
-
</div>
|
|
28
|
-
),
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
|
-
vi.mock('@cloudscape-design/components/box', () => ({
|
|
32
|
-
default: ({ children }: any) => <div>{children}</div>,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
// Mock ra-core hooks
|
|
36
|
-
vi.mock('@strato-admin/core', () => ({
|
|
37
|
-
useInput: vi.fn(),
|
|
38
|
-
useResourceContext: vi.fn(),
|
|
39
|
-
RecordContextProvider: ({ children }: any) => <>{children}</>,
|
|
40
|
-
ArrayInputContext: {
|
|
41
|
-
Provider: ({ children }: any) => <>{children}</>,
|
|
42
|
-
},
|
|
43
|
-
}));
|
|
44
|
-
|
|
45
|
-
// Mock react-hook-form hooks
|
|
46
|
-
vi.mock('react-hook-form', () => ({
|
|
47
|
-
useFormContext: vi.fn(),
|
|
48
|
-
useFieldArray: vi.fn(),
|
|
49
|
-
}));
|
|
50
|
-
|
|
51
|
-
// Mock local components and contexts
|
|
52
|
-
vi.mock('./FormFieldContext', () => ({
|
|
53
|
-
useFormFieldContext: vi.fn(),
|
|
54
|
-
FormFieldContext: {
|
|
55
|
-
Provider: ({ children }: any) => <>{children}</>,
|
|
56
|
-
},
|
|
57
|
-
}));
|
|
58
|
-
|
|
59
|
-
vi.mock('./FieldTitle', () => ({
|
|
60
|
-
FieldTitle: () => <div data-testid="field-title" />,
|
|
61
|
-
}));
|
|
62
|
-
|
|
63
|
-
vi.mock('./TextInput', () => ({
|
|
64
|
-
default: ({ source }: any) => <div data-testid="text-input" data-source={source} />,
|
|
65
|
-
}));
|
|
66
|
-
|
|
67
|
-
vi.mock('./FormField', () => ({
|
|
68
|
-
default: ({ children }: any) => <div data-testid="form-field">{children}</div>,
|
|
69
|
-
}));
|
|
70
|
-
|
|
71
|
-
describe('AttributeEditor', () => {
|
|
72
|
-
const defaultFormContext = { control: {} };
|
|
73
|
-
const defaultFieldArray = {
|
|
74
|
-
fields: [{}],
|
|
75
|
-
append: vi.fn(),
|
|
76
|
-
remove: vi.fn(),
|
|
77
|
-
};
|
|
78
|
-
const defaultInput = {
|
|
79
|
-
id: 'test',
|
|
80
|
-
field: { name: 'test', value: [], onChange: vi.fn(), onBlur: vi.fn() },
|
|
81
|
-
fieldState: { error: undefined, isTouched: false, isDirty: false },
|
|
82
|
-
formState: { isSubmitted: false },
|
|
83
|
-
isRequired: false,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
beforeEach(() => {
|
|
87
|
-
vi.mocked(useFormContext).mockReturnValue(defaultFormContext as any);
|
|
88
|
-
vi.mocked(useFieldArray).mockReturnValue(defaultFieldArray as any);
|
|
89
|
-
vi.mocked(useInput).mockReturnValue(defaultInput as any);
|
|
90
|
-
vi.mocked(useFormFieldContext).mockReturnValue(undefined);
|
|
91
|
-
vi.mocked(useResourceContext).mockReturnValue('test-resource');
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('should prefix source prop of immediate children', () => {
|
|
95
|
-
const Child = ({ source }: any) => <div data-testid="child">{source}</div>;
|
|
96
|
-
|
|
97
|
-
const { getByTestId } = render(
|
|
98
|
-
<AttributeEditor source="products">
|
|
99
|
-
<Child source="id" />
|
|
100
|
-
</AttributeEditor>,
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
expect(getByTestId('child').textContent).toBe('products.0.id');
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should NOT add source prop to children that do not have one', () => {
|
|
107
|
-
const NonInput = ({ children }: any) => <div data-testid="non-input">{children}</div>;
|
|
108
|
-
|
|
109
|
-
const { getByTestId } = render(
|
|
110
|
-
<AttributeEditor source="products">
|
|
111
|
-
<NonInput />
|
|
112
|
-
</AttributeEditor>,
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
expect(getByTestId('non-input').getAttribute('source')).toBeNull();
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should disable the add button when disableAddButton is true', () => {
|
|
119
|
-
vi.mocked(useFieldArray).mockReturnValue({
|
|
120
|
-
...defaultFieldArray,
|
|
121
|
-
fields: [],
|
|
122
|
-
} as any);
|
|
123
|
-
|
|
124
|
-
const { getByTestId } = render(
|
|
125
|
-
<AttributeEditor source="products" disableAddButton>
|
|
126
|
-
<div resource="id" />
|
|
127
|
-
</AttributeEditor>,
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
expect(getByTestId('add-button').hasAttribute('disabled')).toBe(true);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('should hide the add button when hideAddButton is true', () => {
|
|
134
|
-
vi.mocked(useFieldArray).mockReturnValue({
|
|
135
|
-
...defaultFieldArray,
|
|
136
|
-
fields: [],
|
|
137
|
-
} as any);
|
|
138
|
-
|
|
139
|
-
const { queryByTestId } = render(
|
|
140
|
-
<AttributeEditor source="products" hideAddButton>
|
|
141
|
-
<div resource="id" />
|
|
142
|
-
</AttributeEditor>,
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
expect(queryByTestId('add-button')).toBeNull();
|
|
146
|
-
});
|
|
147
|
-
});
|