Skip to content

45154 frontend [ Outputs ] Instead of the performer, a group with the same ID is selected#168

Open
Maria-Lordwill wants to merge 1 commit intomasterfrom
frontend/outputs/45154__instead_of_the_performer_a_group_with_the_same_id_is_selected
Open

45154 frontend [ Outputs ] Instead of the performer, a group with the same ID is selected#168
Maria-Lordwill wants to merge 1 commit intomasterfrom
frontend/outputs/45154__instead_of_the_performer_a_group_with_the_same_id_is_selected

Conversation

@Maria-Lordwill
Copy link
Collaborator

@Maria-Lordwill Maria-Lordwill commented Mar 12, 2026

1. Release notes

Fixed a bug in the user field dropdown on process run steps: when a user and a group had the same numeric ID, the dropdown would display the wrong entity (e.g., showing the group instead of the selected user). The selected value is now correctly preserved and displayed regardless of ID collisions.


2. Description (Problem)

When running a process (Process Run), a step with a «User» type field shows a dropdown to select a user or group. Internally, each dropdown option stored value as String(item.id) — just the numeric ID as a string.

If a user (id: 5) and a group (id: 5) both existed, their value entries were identical ("5"), and the .find() method used to locate the selected value would always return the first match — the group (since groups were placed first in the [...groupsDropdownOption, ...usersDropdownOption] array). As a result:

  • User selected an employee → the dropdown displayed the group with the same ID.
  • Visually, this looked like the selection was being replaced.

Location: Process Run screen → «User» type field (performer selection dropdown).


3. Context

  • Task: #45154 — «Instead of the performer, a group with the same ID is selected».
  • Component: ExtraFieldUser — user/group selection field in kickoff forms and process run steps.
  • Location in the app: everywhere the «User» type field with a dropdown is used:
    • Running a workflow (WorkflowEditPopup)
    • Task execution (TaskCard)
    • Public form (PublicForm)
    • Kickoff editing (KickoffEdit)

4. Solution

Key idea: replace the numeric value with a composite key in the format "type-id", which uniquely identifies an option even when numeric IDs collide between entities of different types.


5. Implementation details

Option value generation

  • Before: value: String(item.id) → user with id=5 and group with id=5 both got value: "5".
  • After:
    • User: value: "${EOptionTypes.User}-${item.id}""user-5"
    • Group: value: "${EOptionTypes.Group}-${item.id}""user-group-5"

Finding the selected value (value prop for UsersDropdown)

  • Before: item.value === String(field.userId) || item.value === String(field.groupId) — both conditions compared against the raw ID; collisions were unresolvable.
  • After: item.value === "${EOptionTypes.User}-${field.userId}" || item.value === "${EOptionTypes.Group}-${field.groupId}" — comparison uses the composite key, eliminating collisions.

Moving useSelector out of renderSelectableView

  • Before: useSelector(getUsers) and useSelector(state => state.groups.list) were called inside renderSelectableView() — a nested function (not a React component), violating the Rules of Hooks.
  • After: both useSelector calls are at the top level of the ExtraFieldUser component. For groups, a typed getGroupsList selector is used instead of an inline state.groups.list access.

6. What to test

6.1 Preconditions

  • Dev branch with these changes.
  • The account has at least one user and one group with the same numeric ID (typically id=1 — the first user and the first group).
  • A template with a «User» type field on the kickoff form and on one of the steps.
  • Browser for manual/AI testing: Desktop Chromium. Verification in other browsers and engines (Firefox, Safari, Mobile) is handed over to the QA engineer for automated testing.

6.2 Positive scenarios / Testing Report

When running a workflow (Run):

Scenario Description (What to do and what to expect) AI Agent Checked Developer Checked (mobile layout visually, Chrome)
Selecting a user Run a process → in the kickoff form with a «User» field → open the dropdown → select a user → verify the dropdown displays the selected user (name and email), not a group. ✅ Yes (Desktop Chromium)
Screenshot
✅ Yes
Selecting a group Same flow → select a group → verify the dropdown displays the selected group (name), not a user. ✅ Yes (Desktop Chromium) ✅ Yes
Switching Select a user → then switch to a group → verify the display updates correctly. And vice versa. ✅ Yes (Desktop Chromium) ✅ Yes
Empty state If nothing is selected yet, the dropdown shows the placeholder, not any value. ✅ Yes (Desktop Chromium)
Screenshot
✅ Yes

When executing a task (Task):

Scenario Description (What to do and what to expect) AI Agent Checked Developer Checked (mobile layout visually, Chrome)
Selecting a user in a task Open a task with a «User» field → open the dropdown → select a user → verify the correct user is displayed. ✅ Yes (Desktop Chromium) ✅ Yes
Selecting a group in a task Same flow → select a group → verify the correct group is displayed. ✅ Yes (Desktop Chromium)
Screenshot
✅ Yes

6.3 Negative scenarios and edge cases

Scenario Description (What to do and what to expect) AI Agent Checked Developer Checked (mobile layout visually, Chrome)
ID collision Create a situation where a user and a group share the same numeric ID. Select the user — verify the group is not displayed. Select the group — verify the user is not displayed. ✅ Yes (Desktop Chromium) ✅ Yes

6.4 Verification points

  • In the UI (the «User» field dropdown on a process step): the displayed name matches the selected user or group.
  • On form submission: the request payload should contain the correct userId/groupId (one of them being null).

6.5 What was NOT tested

  • Locales were not checked (changes don't affect text strings).

7. Testing affected shared parts

Moving useSelector from the nested renderSelectableView function to the top level of the component affects all modes of ExtraFieldUser. Previously, useSelector(getUsers) and useSelector(state => state.groups.list) were only called in ProcessRun mode; now they are called in all modes, including Kickoff. Additionally, the inline selector state => state.groups.list was replaced with the typed getGroupsList selector.

Verify:

Location (Scenario) Description (What to do and what to expect) AI Agent Checked Developer Checked (mobile layout visually, Chrome)
Kickoff form in template editor open the template editor → add a «User» type field to the kickoff → verify the field renders correctly with no console errors. ✅ Yes (Desktop Chromium) ✅ Yes
Running a workflow (Run) «User» field in the kickoff form when launching a process — dropdown works correctly, users and groups load. ✅ Yes (Desktop Chromium) ✅ Yes
Task execution (Task) «User» field on a task step — dropdown works correctly. ✅ Yes (Desktop Chromium) ✅ Yes
Public form if available — «User» field displays and functions correctly. [ ] (Not available in environment / form not configured) [ ]

8. Unit tests

Added tests in ExtraFieldUser.test.tsx:

  • Selecting a user when a group with the same ID exists → passes value: "user-1".
  • Selecting a group when a user with the same ID exists → passes value: "user-group-1".
  • Empty state (neither is set) → value = undefined.
  • Triggering editField on selection: nullifying the opposite field (userId: null when groupId is selected and vice versa).

10. Commits

  • 146f4817 — 45154 Fix performer selection bug, add frontend unit tests, and pass agentic QA defined in PR description

Note

Low Risk
Low risk UI logic change that only affects how user/group options are keyed and selected in the User extra field dropdown; main risk is unexpected mismatches if any downstream code relied on raw numeric value strings.

Overview
Fixes a Process Run bug where the User extra field dropdown could display the wrong entity when a user and a group shared the same numeric ID.

Dropdown option values are now type-prefixed (e.g., user-<id> vs user-group-<id>) and the selected option lookup uses these composite keys, eliminating ID collisions. The component also moves useSelector calls to the component top-level and switches group selection to the shared getGroupsList selector.

Adds unit tests covering collision-safe selection, empty-state behavior, and ensuring selecting a user clears groupId (and vice versa). Also updates .gitignore to ignore Cursor/agent artifacts and treats .antigravity as a directory.

Written by Cursor Bugbot for commit 307b906. This will update automatically on new commits. Configure here.

Note

Fix performer vs group misselection in ExtraFieldUser outputs dropdown when IDs collide

  • User and group options in ExtraFieldUser.tsx previously used plain numeric IDs as option values, causing a group to be selected instead of a performer when both share the same ID.
  • Options now use type-prefixed values (user-{id} / group-{id}) and the selected value resolution checks the prefix to correctly distinguish between users and groups.
  • A new Jest test suite in ExtraFieldUser.test.tsx covers disambiguation, correct preselection for userId/groupId, and onChange handling.

Macroscope summarized 307b906.

@Maria-Lordwill Maria-Lordwill added bug Something isn't working Frontend Web client changes request labels Mar 12, 2026
@Maria-Lordwill Maria-Lordwill force-pushed the frontend/outputs/45154__instead_of_the_performer_a_group_with_the_same_id_is_selected branch from 4ebcd90 to 307b906 Compare March 12, 2026 12:01
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.


jest.mock('../../../../UI/form/UsersDropdown', () => ({
UsersDropdown: jest.fn(() => null),
EOptionTypes: { User: 'user', Group: 'user-group' },
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test mock uses wrong value for EOptionTypes.Group

Low Severity

The test mock sets EOptionTypes.Group to 'user-group', but the real value is 'group' (from ETaskPerformerType.UserGroup = 'group'). In production, group option values are formatted as "group-5", while the test asserts they are "user-group-5". Because both option generation and value matching in the component use the same mocked EOptionTypes, the test is internally consistent and passes, but it validates against incorrect expected values, weakening its ability to catch regressions.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working Frontend Web client changes request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants