Thomas Trompette
2025-09-10 17:25:40 +02:00
committed by GitHub
parent bcf1bba302
commit 3bfb5bbd86
34 changed files with 642 additions and 118 deletions
@@ -1,4 +1,3 @@
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
import { act, renderHook } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import { WorkflowVisualizerComponentInstanceContext } from '../../../workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
@@ -44,17 +43,6 @@ const wrapper = ({ children }: { children: React.ReactNode }) => {
};
describe('useCreateStep', () => {
const mockWorkflow = {
id: '123',
currentVersion: {
id: '456',
status: 'DRAFT',
steps: [],
trigger: { type: 'manual' },
},
versions: [],
};
beforeEach(() => {
jest.clearAllMocks();
});
@@ -63,15 +51,9 @@ describe('useCreateStep', () => {
const mockWorkflowVersionId = 'version-123';
mockGetUpdatableWorkflowVersion.mockResolvedValue(mockWorkflowVersionId);
const { result } = renderHook(
() =>
useCreateStep({
workflow: mockWorkflow as unknown as WorkflowWithCurrentVersion,
}),
{
wrapper,
},
);
const { result } = renderHook(() => useCreateStep(), {
wrapper,
});
await act(async () => {
await result.current.createStep({
@@ -6,11 +6,14 @@ const mockGetUpdatableWorkflowVersion = jest.fn();
const mockDeleteStepsOutputSchema = jest.fn();
const mockCloseCommandMenu = jest.fn();
jest.mock('@/workflow/hooks/useDeleteWorkflowVersionStep', () => ({
useDeleteWorkflowVersionStep: () => ({
deleteWorkflowVersionStep: mockDeleteWorkflowVersionStep,
jest.mock(
'@/workflow/workflow-steps/hooks/useDeleteWorkflowVersionStep',
() => ({
useDeleteWorkflowVersionStep: () => ({
deleteWorkflowVersionStep: mockDeleteWorkflowVersionStep,
}),
}),
}));
);
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow', () => ({
useGetUpdatableWorkflowVersionOrThrow: () => ({
@@ -0,0 +1,70 @@
import { useDuplicateStep } from '@/workflow/workflow-steps/hooks/useDuplicateStep';
import { act, renderHook } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import { WorkflowVisualizerComponentInstanceContext } from '../../../workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
const mockGetUpdatableWorkflowVersion = jest.fn();
const mockDuplicateWorkflowVersionStep = jest.fn().mockResolvedValue({
data: {
duplicateWorkflowVersionStep: { createdStep: { id: '2', type: 'CODE' } },
},
});
jest.mock(
'@/workflow/workflow-steps/hooks/useDuplicateWorkflowVersionStep',
() => ({
useDuplicateWorkflowVersionStep: () => ({
duplicateWorkflowVersionStep: mockDuplicateWorkflowVersionStep,
}),
}),
);
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow', () => ({
useGetUpdatableWorkflowVersionOrThrow: () => ({
getUpdatableWorkflowVersion: mockGetUpdatableWorkflowVersion,
}),
}));
const wrapper = ({ children }: { children: React.ReactNode }) => {
const workflowVisualizerComponentInstanceId =
'workflow-visualizer-instance-id';
return (
<RecoilRoot>
<WorkflowVisualizerComponentInstanceContext.Provider
value={{
instanceId: workflowVisualizerComponentInstanceId,
}}
>
{children}
</WorkflowVisualizerComponentInstanceContext.Provider>
</RecoilRoot>
);
};
describe('useDuplicateStep', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should create step in workflow version', async () => {
const mockWorkflowVersionId = 'version-123';
mockGetUpdatableWorkflowVersion.mockResolvedValue(mockWorkflowVersionId);
const { result } = renderHook(() => useDuplicateStep(), {
wrapper,
});
await act(async () => {
await result.current.duplicateStep({
stepId: 'step-1',
});
});
expect(mockGetUpdatableWorkflowVersion).toHaveBeenCalled();
expect(mockDuplicateWorkflowVersionStep).toHaveBeenCalledWith({
stepId: 'step-1',
workflowVersionId: mockWorkflowVersionId,
});
});
});
@@ -1,20 +1,13 @@
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
import { workflowLastCreatedStepIdComponentState } from '@/workflow/states/workflowLastCreatedStepIdComponentState';
import {
type WorkflowStepType,
type WorkflowWithCurrentVersion,
} from '@/workflow/types/Workflow';
import { type WorkflowStepType } from '@/workflow/types/Workflow';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { useCreateWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useCreateWorkflowVersionStep';
import { useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
export const useCreateStep = ({
workflow,
}: {
workflow: WorkflowWithCurrentVersion | undefined;
}) => {
export const useCreateStep = () => {
const [isLoading, setIsLoading] = useState(false);
const { createWorkflowVersionStep } = useCreateWorkflowVersionStep();
const setWorkflowSelectedNode = useSetRecoilComponentState(
@@ -27,12 +20,6 @@ export const useCreateStep = ({
const { getUpdatableWorkflowVersion } =
useGetUpdatableWorkflowVersionOrThrow();
if (!isDefined(workflow)) {
return {
createStep: async () => undefined,
};
}
const createStep = async ({
newStepType,
parentStepId,
@@ -1,7 +1,7 @@
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useDeleteWorkflowVersionStep } from '@/workflow/hooks/useDeleteWorkflowVersionStep';
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
import { useDeleteWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useDeleteWorkflowVersionStep';
export const useDeleteStep = () => {
const { deleteWorkflowVersionStep } = useDeleteWorkflowVersionStep();
@@ -0,0 +1,39 @@
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
import { DELETE_WORKFLOW_VERSION_STEP } from '@/workflow/graphql/mutations/deleteWorkflowVersionStep';
import { useUpdateWorkflowVersionCache } from '@/workflow/workflow-steps/hooks/useUpdateWorkflowVersionCache';
import { useMutation } from '@apollo/client';
import {
type DeleteWorkflowVersionStepInput,
type DeleteWorkflowVersionStepMutation,
type DeleteWorkflowVersionStepMutationVariables,
} from '~/generated-metadata/graphql';
export const useDeleteWorkflowVersionStep = () => {
const apolloCoreClient = useApolloCoreClient();
const { updateWorkflowVersionCache } = useUpdateWorkflowVersionCache();
const [mutate] = useMutation<
DeleteWorkflowVersionStepMutation,
DeleteWorkflowVersionStepMutationVariables
>(DELETE_WORKFLOW_VERSION_STEP, {
client: apolloCoreClient,
});
const deleteWorkflowVersionStep = async (
input: DeleteWorkflowVersionStepInput,
) => {
const result = await mutate({ variables: { input } });
const workflowVersionStepChanges = result?.data?.deleteWorkflowVersionStep;
updateWorkflowVersionCache({
workflowVersionStepChanges,
workflowVersionId: input.workflowVersionId,
});
return workflowVersionStepChanges;
};
return { deleteWorkflowVersionStep };
};
@@ -0,0 +1,57 @@
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
import { workflowLastCreatedStepIdComponentState } from '@/workflow/states/workflowLastCreatedStepIdComponentState';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { useDuplicateWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useDuplicateWorkflowVersionStep';
import { useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
export const useDuplicateStep = () => {
const [isLoading, setIsLoading] = useState(false);
const { duplicateWorkflowVersionStep } = useDuplicateWorkflowVersionStep();
const setWorkflowSelectedNode = useSetRecoilComponentState(
workflowSelectedNodeComponentState,
);
const setWorkflowLastCreatedStepId = useSetRecoilComponentState(
workflowLastCreatedStepIdComponentState,
);
const { getUpdatableWorkflowVersion } =
useGetUpdatableWorkflowVersionOrThrow();
const duplicateStep = async ({ stepId }: { stepId: string }) => {
if (isLoading === true) {
return;
}
setIsLoading(true);
try {
const workflowVersionId = await getUpdatableWorkflowVersion();
const workflowVersionStepChanges = (
await duplicateWorkflowVersionStep({
workflowVersionId,
stepId,
})
)?.data?.duplicateWorkflowVersionStep;
const createdStep = workflowVersionStepChanges?.createdStep;
if (!isDefined(createdStep)) {
throw new Error("Couldn't duplicate step");
}
setWorkflowSelectedNode(createdStep.id);
setWorkflowLastCreatedStepId(createdStep.id);
return createdStep;
} finally {
setIsLoading(false);
}
};
return {
duplicateStep,
};
};
@@ -0,0 +1,55 @@
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { DUPLICATE_WORKFLOW_VERSION_STEP } from '@/workflow/graphql/mutations/duplicateWorkflowVersionStep';
import { flowComponentState } from '@/workflow/states/flowComponentState';
import { useUpdateWorkflowVersionCache } from '@/workflow/workflow-steps/hooks/useUpdateWorkflowVersionCache';
import { useMutation } from '@apollo/client';
import { isDefined } from 'twenty-shared/utils';
import {
type DuplicateWorkflowVersionStepInput,
type DuplicateWorkflowVersionStepMutation,
type DuplicateWorkflowVersionStepMutationVariables,
} from '~/generated-metadata/graphql';
export const useDuplicateWorkflowVersionStep = () => {
const apolloCoreClient = useApolloCoreClient();
const { updateWorkflowVersionCache } = useUpdateWorkflowVersionCache();
const setFlow = useSetRecoilComponentState(flowComponentState);
const [mutate] = useMutation<
DuplicateWorkflowVersionStepMutation,
DuplicateWorkflowVersionStepMutationVariables
>(DUPLICATE_WORKFLOW_VERSION_STEP, {
client: apolloCoreClient,
});
const duplicateWorkflowVersionStep = async (
input: DuplicateWorkflowVersionStepInput,
) => {
const result = await mutate({
variables: { input },
});
const workflowVersionStepChanges =
result?.data?.duplicateWorkflowVersionStep;
const updatedWorkflowVersion = updateWorkflowVersionCache({
workflowVersionStepChanges,
workflowVersionId: input.workflowVersionId,
});
if (isDefined(updatedWorkflowVersion)) {
setFlow({
workflowVersionId: updatedWorkflowVersion.id,
trigger: updatedWorkflowVersion.trigger,
steps: updatedWorkflowVersion.steps,
});
}
return result;
};
return { duplicateWorkflowVersionStep };
};