fix(workflow): keep Limit and Offset when changing the Search Records object (#23423)
Fixes the second bug reported in #23387. ## Problem In the Search Records action, changing the Object silently reset `Limit` to `1`. A user who had set `Limit = 100` and then switched object (or switched away and back) ended up with a step that returns exactly one arbitrary record, with no indication beyond a small `1` in the side panel. Reproduced on `main` against a local instance, checking the persisted draft version: ```json { "limit": 1, "offset": 0, "objectName": "person" } ``` `handleOptionClick` rebuilt the entire form as `{ objectNameSingular, limit: 1, offset: 0 }`, discarding whatever the user had entered. `1` is the server-side default for a newly created `FIND_RECORDS` step, so this was effectively a revert-to-creation-default on every object change. ## Change Carry `limit` and `offset` over instead of hardcoding them. `filter` and `orderBy` are still dropped by omission, which is correct: they reference fields of the previous object. ## Test Added `KeepsLimitAndOffsetWhenObjectChanges` to the existing story file. It switches the object and asserts `onActionUpdate` receives `{ objectName: 'company', limit: 100, offset: 20 }`. Confirmed the test is not vacuous: reverting the fix makes it fail with exactly the reported symptom (`limit: 100 -> 1`, `offset: 20 -> 0`). ## Not addressed here The headline bug in #23387 (filters made only of value-less operators never persisting) does not reproduce on `main`. I ran the reporter's steps with `Is in past` OR `Is today (UTC)` and both rules plus the `OR` group were written to the draft version correctly. Persistence hangs off `useUpsertRecordFilter`, which fires the advanced-filter `onUpdate` on every upsert, so operand changes save just as value changes do. The reporter is on ~v2.18.x and did not re-test on a recent release. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/23423?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+53
-1
@@ -1,7 +1,7 @@
|
||||
import { type WorkflowFindRecordsAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowEditActionFindRecords } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords';
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { expect, fn, userEvent, within } from 'storybook/test';
|
||||
import { expect, fn, screen, userEvent, waitFor, within } from 'storybook/test';
|
||||
import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
|
||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
@@ -65,6 +65,58 @@ export const Default: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
const onActionUpdateMock = fn();
|
||||
|
||||
export const KeepsLimitAndOffsetWhenObjectChanges: Story = {
|
||||
args: {
|
||||
action: {
|
||||
...DEFAULT_ACTION,
|
||||
settings: {
|
||||
...DEFAULT_ACTION.settings,
|
||||
input: {
|
||||
objectName: 'person',
|
||||
limit: 100,
|
||||
offset: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
actionOptions: {
|
||||
onActionUpdate: onActionUpdateMock,
|
||||
},
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
onActionUpdateMock.mockClear();
|
||||
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
await userEvent.click(await canvas.findByText('People'));
|
||||
|
||||
await userEvent.type(
|
||||
await screen.findByPlaceholderText('Search'),
|
||||
'Companies',
|
||||
);
|
||||
|
||||
await userEvent.click(await screen.findByText('Companies'));
|
||||
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(onActionUpdateMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
settings: expect.objectContaining({
|
||||
input: expect.objectContaining({
|
||||
objectName: 'company',
|
||||
limit: 100,
|
||||
offset: 20,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
);
|
||||
},
|
||||
{ timeout: 3000 },
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const DisabledWithEmptyValues: Story = {
|
||||
args: {
|
||||
actionOptions: {
|
||||
|
||||
+2
-2
@@ -178,8 +178,8 @@ export const WorkflowEditActionFindRecords = ({
|
||||
|
||||
const newFormData: FindRecordsFormData = {
|
||||
objectNameSingular: value,
|
||||
limit: 1,
|
||||
offset: 0,
|
||||
limit: formData.limit,
|
||||
offset: formData.offset,
|
||||
};
|
||||
|
||||
setFormData(newFormData);
|
||||
|
||||
Reference in New Issue
Block a user