Add variable path (#10720)
<img width="537" alt="Capture d’écran 2025-03-07 à 09 44 21" src="https://github.com/user-attachments/assets/52c4d292-01af-4389-aa66-551be2358dd7" /> - search through step output schema the variable - build the variable path - returns the variable label - display both
This commit is contained in:
@ -1,4 +1,6 @@
|
||||
import { extractVariableLabel } from '@/workflow/workflow-variables/utils/extractVariableLabel';
|
||||
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
|
||||
import { extractRawVariableNamePart } from '@/workflow/workflow-variables/utils/extractRawVariableNamePart';
|
||||
import { searchVariableThroughOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughOutputSchema';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
@ -60,17 +62,48 @@ const StyledDelete = styled.button`
|
||||
type VariableChipProps = {
|
||||
rawVariableName: string;
|
||||
onRemove?: () => void;
|
||||
isFullRecord?: boolean;
|
||||
};
|
||||
|
||||
export const VariableChip = ({
|
||||
rawVariableName,
|
||||
onRemove,
|
||||
isFullRecord = false,
|
||||
}: VariableChipProps) => {
|
||||
const theme = useTheme();
|
||||
const { getStepsOutputSchema } = useStepsOutputSchema({});
|
||||
const stepId = extractRawVariableNamePart({
|
||||
rawVariableName,
|
||||
part: 'stepId',
|
||||
});
|
||||
|
||||
if (!isDefined(stepId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const stepOutputSchema = getStepsOutputSchema([stepId])?.[0];
|
||||
|
||||
if (!isDefined(stepOutputSchema)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { variableLabel, variablePathLabel } =
|
||||
searchVariableThroughOutputSchema({
|
||||
stepOutputSchema,
|
||||
rawVariableName,
|
||||
isFullRecord,
|
||||
});
|
||||
|
||||
const label = isDefined(variableLabel)
|
||||
? variableLabel
|
||||
: extractRawVariableNamePart({
|
||||
rawVariableName,
|
||||
part: 'selectedField',
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledChip deletable={isDefined(onRemove)}>
|
||||
<StyledLabel>{extractVariableLabel(rawVariableName)}</StyledLabel>
|
||||
<StyledLabel title={variablePathLabel}>{label}</StyledLabel>
|
||||
|
||||
{onRemove ? (
|
||||
<StyledDelete onClick={onRemove} aria-label="Remove variable">
|
||||
|
||||
@ -10,15 +10,21 @@ const StyledContainer = styled.div`
|
||||
type VariableChipStandaloneProps = {
|
||||
rawVariableName: string;
|
||||
onRemove?: () => void;
|
||||
isFullRecord?: boolean;
|
||||
};
|
||||
|
||||
export const VariableChipStandalone = ({
|
||||
rawVariableName,
|
||||
onRemove,
|
||||
isFullRecord,
|
||||
}: VariableChipStandaloneProps) => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<VariableChip rawVariableName={rawVariableName} onRemove={onRemove} />
|
||||
<VariableChip
|
||||
rawVariableName={rawVariableName}
|
||||
onRemove={onRemove}
|
||||
isFullRecord={isFullRecord}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormAddressFieldInput } from '../FormAddressFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormAddressFieldInput> = {
|
||||
@ -7,6 +9,7 @@ const meta: Meta<typeof FormAddressFieldInput> = {
|
||||
component: FormAddressFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -40,12 +43,12 @@ export const WithVariables: Story = {
|
||||
args: {
|
||||
label: 'Address',
|
||||
defaultValue: {
|
||||
addressStreet1: '{{a.street1}}',
|
||||
addressStreet2: '{{a.street2}}',
|
||||
addressCity: '{{a.city}}',
|
||||
addressState: '{{a.state}}',
|
||||
addressCountry: '{{a.country}}',
|
||||
addressPostcode: '{{a.postcode}}',
|
||||
addressStreet1: `{{${MOCKED_STEP_ID}.address.street1}}`,
|
||||
addressStreet2: `{{${MOCKED_STEP_ID}.address.street2}}`,
|
||||
addressCity: `{{${MOCKED_STEP_ID}.address.city}}`,
|
||||
addressState: `{{${MOCKED_STEP_ID}.address.state}}`,
|
||||
addressCountry: `{{${MOCKED_STEP_ID}.address.country}}`,
|
||||
addressPostcode: `{{${MOCKED_STEP_ID}.address.postcode}}`,
|
||||
addressLat: 39.781721,
|
||||
addressLng: -89.650148,
|
||||
},
|
||||
@ -58,14 +61,12 @@ export const WithVariables: Story = {
|
||||
const street2Variable = await canvas.findByText('street2');
|
||||
const cityVariable = await canvas.findByText('city');
|
||||
const stateVariable = await canvas.findByText('state');
|
||||
const countryVariable = await canvas.findByText('country');
|
||||
const postcodeVariable = await canvas.findByText('postcode');
|
||||
|
||||
expect(street1Variable).toBeVisible();
|
||||
expect(street2Variable).toBeVisible();
|
||||
expect(cityVariable).toBeVisible();
|
||||
expect(stateVariable).toBeVisible();
|
||||
expect(countryVariable).toBeVisible();
|
||||
expect(postcodeVariable).toBeVisible();
|
||||
|
||||
const variablePickers = await canvas.findAllByText('VariablePicker');
|
||||
|
||||
@ -2,6 +2,8 @@ import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
|
||||
import { FieldCurrencyValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, within } from '@storybook/test';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormCurrencyFieldInput } from '../FormCurrencyFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormCurrencyFieldInput> = {
|
||||
@ -9,6 +11,7 @@ const meta: Meta<typeof FormCurrencyFieldInput> = {
|
||||
component: FormCurrencyFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -36,18 +39,18 @@ export const WithVariable: Story = {
|
||||
args: {
|
||||
label: 'Salary',
|
||||
defaultValue: {
|
||||
currencyCode: CurrencyCode.USD,
|
||||
amountMicros: '{{a.b.c}}',
|
||||
currencyCode: `{{${MOCKED_STEP_ID}.amount.currencyCode}}` as CurrencyCode,
|
||||
amountMicros: `{{${MOCKED_STEP_ID}.amount.amountMicros}}`,
|
||||
},
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const currency = await canvas.findByText(/USD/);
|
||||
expect(currency).toBeVisible();
|
||||
const amountMicros = await canvas.findByText('My Amount Micros');
|
||||
const currencyCode = await canvas.findByText('My Currency Code');
|
||||
|
||||
const amountVariable = await canvas.findByText('c');
|
||||
expect(amountVariable).toBeVisible();
|
||||
expect(amountMicros).toBeVisible();
|
||||
expect(currencyCode).toBeVisible();
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -12,6 +12,8 @@ import {
|
||||
} from '@storybook/test';
|
||||
import { DateTime } from 'luxon';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormDateFieldInput } from '../FormDateFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormDateFieldInput> = {
|
||||
@ -19,7 +21,7 @@ const meta: Meta<typeof FormDateFieldInput> = {
|
||||
component: FormDateFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [I18nFrontDecorator],
|
||||
decorators: [I18nFrontDecorator, WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -308,7 +310,7 @@ export const SwitchesToStandaloneVariable: Story = {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.createdAt}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -322,7 +324,7 @@ export const SwitchesToStandaloneVariable: Story = {
|
||||
const addVariableButton = await canvas.findByText('Add variable');
|
||||
await userEvent.click(addVariableButton);
|
||||
|
||||
const variableTag = await canvas.findByText('test');
|
||||
const variableTag = await canvas.findByText('Creation date');
|
||||
expect(variableTag).toBeVisible();
|
||||
|
||||
const removeVariableButton = canvasElement.querySelector(
|
||||
@ -395,14 +397,14 @@ export const Disabled: Story = {
|
||||
export const DisabledWithVariable: Story = {
|
||||
args: {
|
||||
label: 'Created At',
|
||||
defaultValue: `{{a.b.c}}`,
|
||||
defaultValue: `{{${MOCKED_STEP_ID}.createdAt}}`,
|
||||
onPersist: fn(),
|
||||
readonly: true,
|
||||
VariablePicker: ({ onVariableSelect }) => {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.createdAt}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -410,10 +412,11 @@ export const DisabledWithVariable: Story = {
|
||||
);
|
||||
},
|
||||
},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const variableChip = await canvas.findByText('c');
|
||||
const variableChip = await canvas.findByText('Creation date');
|
||||
expect(variableChip).toBeVisible();
|
||||
},
|
||||
};
|
||||
|
||||
@ -13,13 +13,15 @@ import {
|
||||
} from '@storybook/test';
|
||||
import { DateTime } from 'luxon';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
|
||||
const meta: Meta<typeof FormDateTimeFieldInput> = {
|
||||
title: 'UI/Data/Field/Form/Input/FormDateTimeFieldInput',
|
||||
component: FormDateTimeFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [I18nFrontDecorator],
|
||||
decorators: [I18nFrontDecorator, WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -337,7 +339,7 @@ export const SwitchesToStandaloneVariable: Story = {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.createdAt}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -351,7 +353,7 @@ export const SwitchesToStandaloneVariable: Story = {
|
||||
const addVariableButton = await canvas.findByText('Add variable');
|
||||
await userEvent.click(addVariableButton);
|
||||
|
||||
const variableTag = await canvas.findByText('test');
|
||||
const variableTag = await canvas.findByText('Creation date');
|
||||
expect(variableTag).toBeVisible();
|
||||
|
||||
const removeVariableButton = canvasElement.querySelector(
|
||||
@ -426,14 +428,14 @@ export const Disabled: Story = {
|
||||
export const DisabledWithVariable: Story = {
|
||||
args: {
|
||||
label: 'Created At',
|
||||
defaultValue: `{{a.b.c}}`,
|
||||
defaultValue: `{{${MOCKED_STEP_ID}.createdAt}}`,
|
||||
onPersist: fn(),
|
||||
readonly: true,
|
||||
VariablePicker: ({ onVariableSelect }) => {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.createdAt}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -444,7 +446,7 @@ export const DisabledWithVariable: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const variableChip = await canvas.findByText('c');
|
||||
const variableChip = await canvas.findByText('Creation date');
|
||||
expect(variableChip).toBeVisible();
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormEmailsFieldInput } from '../FormEmailsFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormEmailsFieldInput> = {
|
||||
@ -7,6 +9,7 @@ const meta: Meta<typeof FormEmailsFieldInput> = {
|
||||
component: FormEmailsFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -34,7 +37,7 @@ export const WithVariable: Story = {
|
||||
args: {
|
||||
label: 'Emails',
|
||||
defaultValue: {
|
||||
primaryEmail: '{{a.b.c}}',
|
||||
primaryEmail: `{{${MOCKED_STEP_ID}.name}}`,
|
||||
additionalEmails: [],
|
||||
},
|
||||
VariablePicker: () => <div>VariablePicker</div>,
|
||||
@ -42,7 +45,7 @@ export const WithVariable: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const primaryEmailVariable = await canvas.findByText('c');
|
||||
const primaryEmailVariable = await canvas.findByText('Name');
|
||||
expect(primaryEmailVariable).toBeVisible();
|
||||
|
||||
const variablePicker = await canvas.findByText('VariablePicker');
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormFullNameFieldInput } from '../FormFullNameFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormFullNameFieldInput> = {
|
||||
@ -7,6 +9,7 @@ const meta: Meta<typeof FormFullNameFieldInput> = {
|
||||
component: FormFullNameFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -34,18 +37,18 @@ export const WithVariable: Story = {
|
||||
args: {
|
||||
label: 'Name',
|
||||
defaultValue: {
|
||||
firstName: '{{a.firstName}}',
|
||||
lastName: '{{a.lastName}}',
|
||||
firstName: `{{${MOCKED_STEP_ID}.fullName.firstName}}`,
|
||||
lastName: `{{${MOCKED_STEP_ID}.fullName.lastName}}`,
|
||||
},
|
||||
VariablePicker: () => <div>VariablePicker</div>,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const firstNameVariable = await canvas.findByText('firstName');
|
||||
const firstNameVariable = await canvas.findByText('Full Name First Name');
|
||||
expect(firstNameVariable).toBeVisible();
|
||||
|
||||
const lastNameVariable = await canvas.findByText('lastName');
|
||||
const lastNameVariable = await canvas.findByText('Full Name Last Name');
|
||||
expect(lastNameVariable).toBeVisible();
|
||||
|
||||
const variablePickers = await canvas.findAllByText('VariablePicker');
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { fn, userEvent, within } from '@storybook/test';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { FormLinksFieldInput } from '../FormLinksFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormLinksFieldInput> = {
|
||||
@ -8,6 +9,7 @@ const meta: Meta<typeof FormLinksFieldInput> = {
|
||||
component: FormLinksFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -35,18 +37,18 @@ export const WithVariables: Story = {
|
||||
args: {
|
||||
label: 'Domain Name',
|
||||
defaultValue: {
|
||||
primaryLinkLabel: '{{a.label}}',
|
||||
primaryLinkUrl: '{{a.url}}',
|
||||
primaryLinkLabel: '{{04d5f3bf-9714-400d-ba27-644006a5fb1b.name}}',
|
||||
primaryLinkUrl: '{{04d5f3bf-9714-400d-ba27-644006a5fb1b.stage}}',
|
||||
},
|
||||
VariablePicker: () => <div>VariablePicker</div>,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const primaryLinkLabelVariable = await canvas.findByText('label');
|
||||
const primaryLinkLabelVariable = await canvas.findByText('Name');
|
||||
expect(primaryLinkLabelVariable).toBeVisible();
|
||||
|
||||
const primaryLinkUrlVariable = await canvas.findByText('url');
|
||||
const primaryLinkUrlVariable = await canvas.findByText('Stage');
|
||||
expect(primaryLinkUrlVariable).toBeVisible();
|
||||
|
||||
const variablePickers = await canvas.findAllByText('VariablePicker');
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { fn, userEvent, within } from '@storybook/test';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormMultiSelectFieldInput } from '../FormMultiSelectFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormMultiSelectFieldInput> = {
|
||||
@ -8,6 +10,7 @@ const meta: Meta<typeof FormMultiSelectFieldInput> = {
|
||||
component: FormMultiSelectFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -117,14 +120,14 @@ export const Disabled: Story = {
|
||||
export const DisabledWithVariable: Story = {
|
||||
args: {
|
||||
label: 'Created At',
|
||||
defaultValue: `{{a.b.c}}`,
|
||||
defaultValue: `{{${MOCKED_STEP_ID}.stage}}`,
|
||||
onPersist: fn(),
|
||||
readonly: true,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const variableChip = await canvas.findByText('c');
|
||||
const variableChip = await canvas.findByText('Stage');
|
||||
expect(variableChip).toBeVisible();
|
||||
|
||||
await userEvent.click(variableChip);
|
||||
|
||||
@ -2,6 +2,8 @@ import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
|
||||
|
||||
import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormPhoneFieldInput } from '../FormPhoneFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormPhoneFieldInput> = {
|
||||
@ -9,6 +11,7 @@ const meta: Meta<typeof FormPhoneFieldInput> = {
|
||||
component: FormPhoneFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -108,20 +111,17 @@ export const WithVariablesAsDefaultValues: Story = {
|
||||
args: {
|
||||
label: 'Phone',
|
||||
defaultValue: {
|
||||
primaryPhoneCountryCode: '{{a.countryCode}}',
|
||||
primaryPhoneNumber: '{{a.phoneNumber}}',
|
||||
primaryPhoneCountryCode: `{{${MOCKED_STEP_ID}.name}}`,
|
||||
primaryPhoneNumber: `{{${MOCKED_STEP_ID}.amount.amountMicros}}`,
|
||||
},
|
||||
VariablePicker: () => <div>VariablePicker</div>,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const countryCodeVariable = await canvas.findByText('countryCode');
|
||||
const countryCodeVariable = await canvas.findByText('Name');
|
||||
expect(countryCodeVariable).toBeVisible();
|
||||
|
||||
const phoneNumberVariable = await canvas.findByText('phoneNumber');
|
||||
expect(phoneNumberVariable).toBeVisible();
|
||||
|
||||
const variablePickers = await canvas.findAllByText('VariablePicker');
|
||||
|
||||
expect(variablePickers).toHaveLength(1);
|
||||
@ -139,7 +139,7 @@ export const SelectingVariables: Story = {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.phoneNumber}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -162,12 +162,12 @@ export const SelectingVariables: Story = {
|
||||
|
||||
await userEvent.click(phoneNumberVariablePicker);
|
||||
|
||||
const phoneNumberVariable = await canvas.findByText('test');
|
||||
const phoneNumberVariable = await canvas.findByText('phoneNumber');
|
||||
expect(phoneNumberVariable).toBeVisible();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(args.onPersist).toHaveBeenCalledWith({
|
||||
primaryPhoneNumber: '{{test}}',
|
||||
primaryPhoneNumber: `{{${MOCKED_STEP_ID}.phoneNumber}}`,
|
||||
primaryPhoneCountryCode: '',
|
||||
primaryPhoneCallingCode: '',
|
||||
});
|
||||
|
||||
@ -2,6 +2,8 @@ import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { fn, userEvent, waitFor, within } from '@storybook/test';
|
||||
import { getUserDevice } from 'twenty-ui';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormRawJsonFieldInput } from '../FormRawJsonFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormRawJsonFieldInput> = {
|
||||
@ -9,6 +11,7 @@ const meta: Meta<typeof FormRawJsonFieldInput> = {
|
||||
component: FormRawJsonFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -37,7 +40,7 @@ export const Readonly: Story = {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.name}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -142,7 +145,7 @@ export const DoesNotIgnoreInvalidJson: Story = {
|
||||
export const DisplayDefaultValueWithVariablesProperly: Story = {
|
||||
args: {
|
||||
placeholder: 'Enter valid json',
|
||||
defaultValue: '{ "a": { "b" : {{var.test}} } }',
|
||||
defaultValue: `{ "a": { "b" : {{${MOCKED_STEP_ID}.name}} } }`,
|
||||
onPersist: fn(),
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
@ -150,7 +153,7 @@ export const DisplayDefaultValueWithVariablesProperly: Story = {
|
||||
|
||||
await canvas.findByText(/{ "a": { "b" : /);
|
||||
|
||||
const variableTag = await canvas.findByText('test');
|
||||
const variableTag = await canvas.findByText('Name');
|
||||
await expect(variableTag).toBeVisible();
|
||||
|
||||
await canvas.findByText(/ } }/);
|
||||
@ -304,7 +307,7 @@ export const HasHistory: Story = {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.name}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -331,7 +334,9 @@ export const HasHistory: Story = {
|
||||
|
||||
await userEvent.type(editor, ' }');
|
||||
|
||||
expect(args.onPersist).toHaveBeenLastCalledWith('{ "a": {{test}} }');
|
||||
expect(args.onPersist).toHaveBeenLastCalledWith(
|
||||
`{ "a": {{${MOCKED_STEP_ID}.name}} }`,
|
||||
);
|
||||
|
||||
await userEvent.type(editor, `{${controlKey}>}z{/${controlKey}}`);
|
||||
|
||||
@ -343,7 +348,9 @@ export const HasHistory: Story = {
|
||||
`{Shift>}{${controlKey}>}z{/${controlKey}}{/Shift}`,
|
||||
);
|
||||
|
||||
expect(editor).toHaveTextContent('{ "a": test }');
|
||||
expect(args.onPersist).toHaveBeenLastCalledWith('{ "a": {{test}} }');
|
||||
expect(editor).toHaveTextContent('{ "a": Name }');
|
||||
expect(args.onPersist).toHaveBeenLastCalledWith(
|
||||
`{ "a": {{${MOCKED_STEP_ID}.name}} }`,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { fn, userEvent, within } from '@storybook/test';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormSelectFieldInput } from '../FormSelectFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormSelectFieldInput> = {
|
||||
@ -8,6 +10,7 @@ const meta: Meta<typeof FormSelectFieldInput> = {
|
||||
component: FormSelectFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -117,7 +120,7 @@ export const Disabled: Story = {
|
||||
export const DisabledWithVariable: Story = {
|
||||
args: {
|
||||
label: 'Created At',
|
||||
defaultValue: `{{a.b.c}}`,
|
||||
defaultValue: `{{${MOCKED_STEP_ID}.createdAt}}`,
|
||||
options: [
|
||||
{
|
||||
label: 'Work Policy 1',
|
||||
@ -146,7 +149,7 @@ export const DisabledWithVariable: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const variableChip = await canvas.findByText('c');
|
||||
const variableChip = await canvas.findByText('Creation date');
|
||||
expect(variableChip).toBeVisible();
|
||||
|
||||
await userEvent.click(variableChip);
|
||||
|
||||
@ -8,6 +8,8 @@ import {
|
||||
within,
|
||||
} from '@storybook/test';
|
||||
import { getUserDevice } from 'twenty-ui';
|
||||
import { WorkflowStepDecorator } from '~/testing/decorators/WorkflowStepDecorator';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormTextFieldInput } from '../FormTextFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormTextFieldInput> = {
|
||||
@ -15,6 +17,7 @@ const meta: Meta<typeof FormTextFieldInput> = {
|
||||
component: FormTextFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [WorkflowStepDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@ -78,7 +81,7 @@ export const WithVariable: Story = {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.name}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -96,11 +99,11 @@ export const WithVariable: Story = {
|
||||
|
||||
await userEvent.click(addVariableButton);
|
||||
|
||||
const variable = await canvas.findByText('test');
|
||||
const variable = await canvas.findByText('Name');
|
||||
expect(variable).toBeVisible();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(args.onPersist).toHaveBeenCalledWith('{{test}}');
|
||||
expect(args.onPersist).toHaveBeenCalledWith(`{{${MOCKED_STEP_ID}.name}}`);
|
||||
});
|
||||
expect(args.onPersist).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
@ -110,7 +113,7 @@ export const WithDeletableVariable: Story = {
|
||||
args: {
|
||||
label: 'Text',
|
||||
placeholder: 'Text field...',
|
||||
defaultValue: 'test {{a.b.variable}} test',
|
||||
defaultValue: `test {{${MOCKED_STEP_ID}.name}} test`,
|
||||
onPersist: fn(),
|
||||
},
|
||||
play: async ({ canvasElement, args }) => {
|
||||
@ -119,7 +122,7 @@ export const WithDeletableVariable: Story = {
|
||||
const editor = canvasElement.querySelector('.ProseMirror > p');
|
||||
expect(editor).toBeVisible();
|
||||
|
||||
const variable = await canvas.findByText('variable');
|
||||
const variable = await canvas.findByText('Name');
|
||||
expect(variable).toBeVisible();
|
||||
|
||||
const deleteVariableButton = await canvas.findByRole('button', {
|
||||
@ -173,7 +176,7 @@ export const Disabled: Story = {
|
||||
export const DisabledWithVariable: Story = {
|
||||
args: {
|
||||
label: 'Text',
|
||||
defaultValue: 'test {{a.b.variable}} test',
|
||||
defaultValue: `test {{${MOCKED_STEP_ID}.name}} test`,
|
||||
readonly: true,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
@ -182,7 +185,7 @@ export const DisabledWithVariable: Story = {
|
||||
expect(editor).toBeVisible();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(editor).toHaveTextContent('test variable test');
|
||||
expect(editor).toHaveTextContent('test Name test');
|
||||
});
|
||||
|
||||
const deleteVariableButton = within(editor as HTMLElement).queryByRole(
|
||||
@ -200,7 +203,7 @@ export const HasHistory: Story = {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.name}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
@ -225,7 +228,9 @@ export const HasHistory: Story = {
|
||||
|
||||
await userEvent.click(addVariableButton);
|
||||
|
||||
expect(args.onPersist).toHaveBeenLastCalledWith('Hello World {{test}}');
|
||||
expect(args.onPersist).toHaveBeenLastCalledWith(
|
||||
`Hello World {{${MOCKED_STEP_ID}.name}}`,
|
||||
);
|
||||
|
||||
await userEvent.type(editor, `{${controlKey}>}z{/${controlKey}}`);
|
||||
|
||||
@ -237,7 +242,9 @@ export const HasHistory: Story = {
|
||||
`{Shift>}{${controlKey}>}z{/${controlKey}}{/Shift}`,
|
||||
);
|
||||
|
||||
expect(editor).toHaveTextContent('Hello World test');
|
||||
expect(args.onPersist).toHaveBeenLastCalledWith('Hello World {{test}}');
|
||||
expect(editor).toHaveTextContent(`Hello World Name`);
|
||||
expect(args.onPersist).toHaveBeenLastCalledWith(
|
||||
`Hello World {{${MOCKED_STEP_ID}.name}}`,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,12 +1,8 @@
|
||||
import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext';
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
fn,
|
||||
userEvent,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
within,
|
||||
} from '@storybook/test';
|
||||
import { fn, userEvent, waitFor, within } from '@storybook/test';
|
||||
import { MOCKED_STEP_ID } from '~/testing/mock-data/workflow';
|
||||
import { FormUuidFieldInput } from '../FormUuidFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormUuidFieldInput> = {
|
||||
@ -14,8 +10,16 @@ const meta: Meta<typeof FormUuidFieldInput> = {
|
||||
component: FormUuidFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<WorkflowVersionComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'workflow-version-id' }}
|
||||
>
|
||||
<Story />
|
||||
</WorkflowVersionComponentInstanceContext.Provider>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof FormUuidFieldInput>;
|
||||
@ -150,69 +154,6 @@ export const ClearField: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const ReplaceStaticValueWithVariable: Story = {
|
||||
args: {
|
||||
label: 'UUID field',
|
||||
placeholder: 'Enter UUID',
|
||||
onPersist: fn(),
|
||||
VariablePicker: ({ onVariableSelect }) => {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
</button>
|
||||
);
|
||||
},
|
||||
},
|
||||
play: async ({ canvasElement, args }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const input = await canvas.findByPlaceholderText('Enter UUID');
|
||||
|
||||
expect(input).toBeVisible();
|
||||
expect(input).toHaveDisplayValue('');
|
||||
|
||||
const addVariableButton = await canvas.findByRole('button', {
|
||||
name: 'Add variable',
|
||||
});
|
||||
|
||||
const [, , variableTag] = await Promise.all([
|
||||
userEvent.click(addVariableButton),
|
||||
|
||||
waitForElementToBeRemoved(input),
|
||||
waitFor(() => {
|
||||
const variableTag = canvas.getByText('test');
|
||||
expect(variableTag).toBeVisible();
|
||||
|
||||
return variableTag;
|
||||
}),
|
||||
waitFor(() => {
|
||||
expect(args.onPersist).toHaveBeenCalledWith('{{test}}');
|
||||
}),
|
||||
]);
|
||||
|
||||
const removeVariableButton = canvasElement.querySelector(
|
||||
'button .tabler-icon-x',
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
userEvent.click(removeVariableButton),
|
||||
|
||||
waitForElementToBeRemoved(variableTag),
|
||||
waitFor(() => {
|
||||
const input = canvas.getByPlaceholderText('Enter UUID');
|
||||
expect(input).toBeVisible();
|
||||
}),
|
||||
waitFor(() => {
|
||||
expect(args.onPersist).toHaveBeenCalledWith(null);
|
||||
}),
|
||||
]);
|
||||
},
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
label: 'UUID field',
|
||||
@ -222,7 +163,7 @@ export const Disabled: Story = {
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
onVariableSelect('{{test}}');
|
||||
onVariableSelect(`{{${MOCKED_STEP_ID}.name}}`);
|
||||
}}
|
||||
>
|
||||
Add variable
|
||||
|
||||
Reference in New Issue
Block a user