mirror of
https://github.com/strapi/strapi.git
synced 2025-12-16 09:45:08 +00:00
Merge pull request #15635 from strapi/feature/review-workflow-redux-query
Settings: Connect Review Workflow UI, data loader and redux
This commit is contained in:
commit
829535d33b
@ -226,6 +226,7 @@
|
|||||||
"Settings.profile.form.section.profile.page.title": "Profile page",
|
"Settings.profile.form.section.profile.page.title": "Profile page",
|
||||||
"Settings.review-workflows.page.title": "Review Workflow",
|
"Settings.review-workflows.page.title": "Review Workflow",
|
||||||
"Settings.review-workflows.page.subtitle": "{count, plural, one {# stage} other {# stages}}",
|
"Settings.review-workflows.page.subtitle": "{count, plural, one {# stage} other {# stages}}",
|
||||||
|
"Settings.review-workflows.page.isLoading": "Workflow is loading",
|
||||||
"Settings.review-workflows.stage.name.label": "Stage name",
|
"Settings.review-workflows.stage.name.label": "Stage name",
|
||||||
"Settings.roles.create.description": "Define the rights given to the role",
|
"Settings.roles.create.description": "Define the rights given to the role",
|
||||||
"Settings.roles.create.title": "Create a role",
|
"Settings.roles.create.title": "Create a role",
|
||||||
|
|||||||
@ -1,35 +1,42 @@
|
|||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { SettingsPageTitle } from '@strapi/helper-plugin';
|
import { SettingsPageTitle } from '@strapi/helper-plugin';
|
||||||
import { Button, ContentLayout, HeaderLayout, Layout, Main } from '@strapi/design-system';
|
import { Button, ContentLayout, HeaderLayout, Layout, Loader, Main } from '@strapi/design-system';
|
||||||
import { Check } from '@strapi/icons';
|
import { Check } from '@strapi/icons';
|
||||||
|
|
||||||
import { Stages } from './components/Stages';
|
import { Stages } from './components/Stages';
|
||||||
|
import { reducer } from './reducer';
|
||||||
const STAGES = [
|
import { REDUX_NAMESPACE } from './constants';
|
||||||
{
|
import { useInjectReducer } from '../../../../../../admin/src/hooks/useInjectReducer';
|
||||||
uid: 'id-1',
|
import { useReviewWorkflows } from './hooks/useReviewWorkflows';
|
||||||
name: 'To do',
|
import { setWorkflows } from './actions';
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
uid: 'id-2',
|
|
||||||
name: 'Ready to review',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
uid: 'id-3',
|
|
||||||
name: 'In progress',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
uid: 'id-4',
|
|
||||||
name: 'Reviewed',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function ReviewWorkflowsPage() {
|
export function ReviewWorkflowsPage() {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
const { workflows: workflowsData } = useReviewWorkflows();
|
||||||
|
const state = useSelector((state) => state?.[REDUX_NAMESPACE]);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
useInjectReducer(REDUX_NAMESPACE, reducer);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(setWorkflows({ status: workflowsData.status, data: workflowsData.data }));
|
||||||
|
}, [workflowsData.status, workflowsData.data, dispatch]);
|
||||||
|
|
||||||
|
// useInjectReducer() runs on the first rendering after useSelector
|
||||||
|
// which will return undefined. This helps to avoid too many optional
|
||||||
|
// chaining operators down the component.
|
||||||
|
if (!state) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
status,
|
||||||
|
serverState: { workflows },
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
const defaultWorkflow = workflows[0] ?? {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
@ -58,11 +65,20 @@ export function ReviewWorkflowsPage() {
|
|||||||
id: 'Settings.review-workflows.page.subtitle',
|
id: 'Settings.review-workflows.page.subtitle',
|
||||||
defaultMessage: '{count, plural, one {# stage} other {# stages}}',
|
defaultMessage: '{count, plural, one {# stage} other {# stages}}',
|
||||||
},
|
},
|
||||||
{ count: STAGES.length }
|
{ count: defaultWorkflow.stages?.length ?? 0 }
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<ContentLayout>
|
<ContentLayout>
|
||||||
<Stages stages={STAGES} />
|
{status === 'loading' ? (
|
||||||
|
<Loader>
|
||||||
|
{formatMessage({
|
||||||
|
id: 'Settings.review-workflows.page.isLoading',
|
||||||
|
defaultMessage: 'Workflow is loading',
|
||||||
|
})}
|
||||||
|
</Loader>
|
||||||
|
) : (
|
||||||
|
<Stages stages={defaultWorkflow.stages} />
|
||||||
|
)}
|
||||||
</ContentLayout>
|
</ContentLayout>
|
||||||
</Main>
|
</Main>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { ACTION_SET_WORKFLOWS } from '../constants';
|
||||||
|
|
||||||
|
export function setWorkflows({ status, data }) {
|
||||||
|
return {
|
||||||
|
type: ACTION_SET_WORKFLOWS,
|
||||||
|
payload: {
|
||||||
|
status,
|
||||||
|
workflows: data,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { setWorkflows } from '..';
|
||||||
|
|
||||||
|
import { ACTION_SET_WORKFLOWS } from '../../constants';
|
||||||
|
|
||||||
|
describe('Admin | Settings | Review Workflow | actions', () => {
|
||||||
|
test('setWorkflows()', () => {
|
||||||
|
expect(setWorkflows({ status: 'loading', data: null, something: 'else' })).toStrictEqual({
|
||||||
|
type: ACTION_SET_WORKFLOWS,
|
||||||
|
payload: {
|
||||||
|
status: 'loading',
|
||||||
|
workflows: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -22,7 +22,7 @@ const StyledAccordion = styled(Box)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function Stage({ uid, name }) {
|
function Stage({ id, name }) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ function Stage({ uid, name }) {
|
|||||||
<Grid gap={4}>
|
<Grid gap={4}>
|
||||||
<GridItem col={6}>
|
<GridItem col={6}>
|
||||||
<TextInput
|
<TextInput
|
||||||
name={`stage_name[${uid}]`}
|
name={`stage_name[${id}]`}
|
||||||
disabled
|
disabled
|
||||||
label={formatMessage({
|
label={formatMessage({
|
||||||
id: 'Settings.review-workflows.stage.name.label',
|
id: 'Settings.review-workflows.stage.name.label',
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { IntlProvider } from 'react-intl';
|
||||||
|
|
||||||
|
import { ThemeProvider, lightTheme } from '@strapi/design-system';
|
||||||
|
|
||||||
|
import { Stage } from '../Stage';
|
||||||
|
|
||||||
|
const STAGES_FIXTURE = {
|
||||||
|
id: 1,
|
||||||
|
name: 'stage-1',
|
||||||
|
};
|
||||||
|
|
||||||
|
const ComponentFixture = (props) => (
|
||||||
|
<IntlProvider locale="en" messages={{}}>
|
||||||
|
<ThemeProvider theme={lightTheme}>
|
||||||
|
<Stage {...STAGES_FIXTURE} {...props} />
|
||||||
|
</ThemeProvider>
|
||||||
|
</IntlProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
const setup = (props) => render(<ComponentFixture {...props} />);
|
||||||
|
|
||||||
|
const user = userEvent.setup();
|
||||||
|
|
||||||
|
describe('Admin | Settings | Review Workflow | Stage', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a stage', async () => {
|
||||||
|
const { getByRole, queryByRole } = setup();
|
||||||
|
|
||||||
|
expect(queryByRole('textbox')).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
await user.click(getByRole('button'));
|
||||||
|
|
||||||
|
expect(queryByRole('textbox')).toBeInTheDocument();
|
||||||
|
expect(getByRole('textbox').value).toBe(STAGES_FIXTURE.name);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -23,9 +23,9 @@ function Stages({ stages }) {
|
|||||||
<Background background="neutral200" height="100%" width={2} zIndex={1} />
|
<Background background="neutral200" height="100%" width={2} zIndex={1} />
|
||||||
|
|
||||||
<Stack spacing={6} zIndex={2} position="relative" as="ol">
|
<Stack spacing={6} zIndex={2} position="relative" as="ol">
|
||||||
{stages.map(({ uid, ...stage }) => (
|
{stages.map(({ id, ...stage }) => (
|
||||||
<Box key={`stage-${uid}`} as="li">
|
<Box key={`stage-${id}`} as="li">
|
||||||
<Stage {...{ ...stage, uid }} />
|
<Stage {...{ ...stage, id }} />
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { IntlProvider } from 'react-intl';
|
||||||
|
|
||||||
|
import { ThemeProvider, lightTheme } from '@strapi/design-system';
|
||||||
|
|
||||||
|
import { Stages } from '../Stages';
|
||||||
|
|
||||||
|
const STAGES_FIXTURE = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'stage-1',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'stage-2',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const ComponentFixture = (props) => (
|
||||||
|
<IntlProvider locale="en" messages={{}}>
|
||||||
|
<ThemeProvider theme={lightTheme}>
|
||||||
|
<Stages stages={STAGES_FIXTURE} {...props} />
|
||||||
|
</ThemeProvider>
|
||||||
|
</IntlProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
const setup = (props) => render(<ComponentFixture {...props} />);
|
||||||
|
|
||||||
|
describe('Admin | Settings | Review Workflow | Stages', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a list of stages', () => {
|
||||||
|
const { getByText } = setup();
|
||||||
|
|
||||||
|
expect(getByText(STAGES_FIXTURE[0].name)).toBeInTheDocument();
|
||||||
|
expect(getByText(STAGES_FIXTURE[1].name)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,6 +1,10 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
export const REDUX_NAMESPACE = 'settings_review-workflows';
|
||||||
|
|
||||||
|
export const ACTION_SET_WORKFLOWS = `Settings/Review_Workflows/SET_WORKFLOWS`;
|
||||||
|
|
||||||
export const StageType = PropTypes.shape({
|
export const StageType = PropTypes.shape({
|
||||||
uid: PropTypes.string.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -26,10 +26,10 @@ const ComponentFixture = ({ children }) => (
|
|||||||
<QueryClientProvider client={client}>{children}</QueryClientProvider>
|
<QueryClientProvider client={client}>{children}</QueryClientProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
function setup(uid) {
|
function setup(id) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
act(() => {
|
act(() => {
|
||||||
resolve(renderHook(() => useReviewWorkflows(uid), { wrapper: ComponentFixture }));
|
resolve(renderHook(() => useReviewWorkflows(id), { wrapper: ComponentFixture }));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -39,61 +39,65 @@ describe('useReviewWorkflows', () => {
|
|||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('fetch all workflows when calling the hook without a workflow uid', async () => {
|
test('fetch all workflows when calling the hook without a workflow id', async () => {
|
||||||
const { get } = useFetchClient();
|
const { get } = useFetchClient();
|
||||||
|
|
||||||
get.mockResolvedValue({
|
get.mockResolvedValue({
|
||||||
data: [
|
data: {
|
||||||
{
|
data: [
|
||||||
uid: 'bdb46de2-9b0d-11ed-a8fc-0242ac120002',
|
{
|
||||||
stages: [],
|
id: 1,
|
||||||
},
|
stages: [],
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
uid: 'c57bc2dc-9b0d-11ed-a8fc-0242ac120002',
|
id: 2,
|
||||||
stages: [],
|
stages: [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { result, waitFor } = await setup();
|
const { result, waitFor } = await setup();
|
||||||
|
|
||||||
expect(result.current.workflows.isLoading).toBe(true);
|
expect(result.current.workflows.isLoading).toBe(true);
|
||||||
expect(get).toBeCalledWith('/admin/review-workflows/workflows/');
|
expect(get).toBeCalledWith('/admin/review-workflows/workflows/?populate=stages');
|
||||||
|
|
||||||
await waitFor(() => expect(result.current.workflows.isLoading).toBe(false));
|
await waitFor(() => expect(result.current.workflows.isLoading).toBe(false));
|
||||||
|
|
||||||
expect(result.current).toStrictEqual(
|
expect(result.current).toStrictEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
workflows: expect.objectContaining({
|
workflows: expect.objectContaining({
|
||||||
data: expect.arrayContaining([{ uid: expect.any(String), stages: expect.any(Array) }]),
|
data: expect.arrayContaining([{ id: expect.any(Number), stages: expect.any(Array) }]),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('fetch a single workflow when calling the hook with a workflow uid', async () => {
|
test('fetch a single workflow when calling the hook with a workflow id', async () => {
|
||||||
const { get } = useFetchClient();
|
const { get } = useFetchClient();
|
||||||
const uidFixture = 'bdb46de2-9b0d-11ed-a8fc-0242ac120002';
|
const idFixture = 1;
|
||||||
|
|
||||||
get.mockResolvedValue({
|
get.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
uid: uidFixture,
|
data: {
|
||||||
stages: [],
|
id: idFixture,
|
||||||
|
stages: [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { result, waitFor } = await setup(uidFixture);
|
const { result, waitFor } = await setup(idFixture);
|
||||||
|
|
||||||
expect(result.current.workflows.isLoading).toBe(true);
|
expect(result.current.workflows.isLoading).toBe(true);
|
||||||
expect(get).toBeCalledWith(`/admin/review-workflows/workflows/${uidFixture}`);
|
expect(get).toBeCalledWith(`/admin/review-workflows/workflows/${idFixture}?populate=stages`);
|
||||||
|
|
||||||
await waitFor(() => expect(result.current.workflows.isLoading).toBe(false));
|
await waitFor(() => expect(result.current.workflows.isLoading).toBe(false));
|
||||||
|
|
||||||
expect(result.current).toStrictEqual(
|
expect(result.current).toStrictEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
workflows: expect.objectContaining({
|
workflows: expect.objectContaining({
|
||||||
data: expect.objectContaining({ uid: expect.any(String), stages: expect.any(Array) }),
|
data: expect.objectContaining({ id: expect.any(Number), stages: expect.any(Array) }),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,12 +2,15 @@ import { useQuery } from 'react-query';
|
|||||||
|
|
||||||
import { useFetchClient } from '@strapi/helper-plugin';
|
import { useFetchClient } from '@strapi/helper-plugin';
|
||||||
|
|
||||||
export function useReviewWorkflows(workflowUid) {
|
export function useReviewWorkflows(workflowId) {
|
||||||
const { get } = useFetchClient();
|
const { get } = useFetchClient();
|
||||||
|
|
||||||
async function fetchWorkflows() {
|
async function fetchWorkflows() {
|
||||||
|
// eslint-disable-next-line no-unreachable
|
||||||
try {
|
try {
|
||||||
const { data } = await get(`/admin/review-workflows/workflows/${workflowUid ?? ''}`);
|
const {
|
||||||
|
data: { data },
|
||||||
|
} = await get(`/admin/review-workflows/workflows/${workflowId ?? ''}?populate=stages`);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -15,7 +18,7 @@ export function useReviewWorkflows(workflowUid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflows = useQuery(['review-workflows', workflowUid ?? 'default'], fetchWorkflows);
|
const workflows = useQuery(['review-workflows', workflowId ?? 'default'], fetchWorkflows);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
workflows,
|
workflows,
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
import produce from 'immer';
|
||||||
|
|
||||||
|
import { ACTION_SET_WORKFLOWS } from '../constants';
|
||||||
|
|
||||||
|
export const initialState = {
|
||||||
|
status: 'loading',
|
||||||
|
serverState: {
|
||||||
|
workflows: [],
|
||||||
|
},
|
||||||
|
clientState: {
|
||||||
|
workflows: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function reducer(state = initialState, action) {
|
||||||
|
return produce(state, (draft) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case ACTION_SET_WORKFLOWS:
|
||||||
|
draft.status = action.payload.status;
|
||||||
|
|
||||||
|
if (action.payload.workflows) {
|
||||||
|
draft.serverState.workflows = [
|
||||||
|
...state.serverState.workflows,
|
||||||
|
...action.payload.workflows,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
import { initialState, reducer } from '..';
|
||||||
|
|
||||||
|
import { ACTION_SET_WORKFLOWS } from '../../constants';
|
||||||
|
|
||||||
|
const WORKFLOWS_FIXTURE = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
stages: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'stage-1',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'stage-2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('Admin | Settings | Review Workflows | reducer', () => {
|
||||||
|
let state;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
state = initialState;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return the initialState', () => {
|
||||||
|
expect(reducer(state, {})).toStrictEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle ACTION_SET_WORKFLOWS with workflows', () => {
|
||||||
|
const action = {
|
||||||
|
type: ACTION_SET_WORKFLOWS,
|
||||||
|
payload: { status: 'loading-state', workflows: WORKFLOWS_FIXTURE },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual({
|
||||||
|
...initialState,
|
||||||
|
status: 'loading-state',
|
||||||
|
serverState: {
|
||||||
|
...initialState.serverState,
|
||||||
|
workflows: [...initialState.serverState.workflows, ...WORKFLOWS_FIXTURE],
|
||||||
|
},
|
||||||
|
clientState: {
|
||||||
|
workflows: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle ACTION_SET_WORKFLOWS without workflows', () => {
|
||||||
|
const action = {
|
||||||
|
type: ACTION_SET_WORKFLOWS,
|
||||||
|
payload: { status: 'loading', workflows: null },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual({
|
||||||
|
...initialState,
|
||||||
|
serverState: {
|
||||||
|
...initialState.serverState,
|
||||||
|
workflows: [],
|
||||||
|
},
|
||||||
|
clientState: {
|
||||||
|
workflows: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { IntlProvider } from 'react-intl';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { QueryClientProvider, QueryClient } from 'react-query';
|
||||||
|
|
||||||
|
import { ThemeProvider, lightTheme } from '@strapi/design-system';
|
||||||
|
|
||||||
|
import configureStore from '../../../../../../../admin/src/core/store/configureStore';
|
||||||
|
import ReviewWorkflowsPage from '..';
|
||||||
|
import { reducer } from '../reducer';
|
||||||
|
import { useReviewWorkflows } from '../hooks/useReviewWorkflows';
|
||||||
|
|
||||||
|
jest.mock('../hooks/useReviewWorkflows', () => ({
|
||||||
|
...jest.requireActual('../hooks/useReviewWorkflows'),
|
||||||
|
useReviewWorkflows: jest.fn().mockReturnValue({
|
||||||
|
workflows: {
|
||||||
|
status: 'loading',
|
||||||
|
data: null,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const client = new QueryClient({
|
||||||
|
defaultOptions: {
|
||||||
|
queries: {
|
||||||
|
retry: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const ComponentFixture = () => {
|
||||||
|
const store = configureStore([], [reducer]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<QueryClientProvider client={client}>
|
||||||
|
<Provider store={store}>
|
||||||
|
<IntlProvider locale="en" messages={{}}>
|
||||||
|
<ThemeProvider theme={lightTheme}>
|
||||||
|
<ReviewWorkflowsPage />
|
||||||
|
</ThemeProvider>
|
||||||
|
</IntlProvider>
|
||||||
|
</Provider>
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setup = (props) => render(<ComponentFixture {...props} />);
|
||||||
|
|
||||||
|
describe('Admin | Settings | Review Workflow | ReviewWorkflowsPage', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handle initial loading state', () => {
|
||||||
|
const { getByText } = setup();
|
||||||
|
|
||||||
|
expect(getByText('0 stages')).toBeInTheDocument();
|
||||||
|
expect(getByText('Workflow is loading')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('handle loaded stage', () => {
|
||||||
|
useReviewWorkflows.mockReturnValue({
|
||||||
|
workflows: {
|
||||||
|
status: 'success',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
stages: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'stage-1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { getByText, queryByText } = setup();
|
||||||
|
|
||||||
|
expect(getByText('1 stage')).toBeInTheDocument();
|
||||||
|
expect(queryByText('Workflow is loading')).not.toBeInTheDocument();
|
||||||
|
expect(getByText('stage-1')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user