Conversation
WalkthroughAdds a reusable EditableTable component and migrates many header/param/var/assertion/multipart UIs to it; introduces bulk-set Redux actions and UID-preserving logic; updates styling and tests to match trailing-empty-row behavior. (47 words) Changes
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser UI
participant EditableTable as EditableTable component
participant Redux as Redux store (collections slice)
participant FS as File system (file picker)
Browser->>EditableTable: render(columns, rows, defaultRow, getRowError)
Browser->>EditableTable: user edits cell / bulk edit / delete / reorder
EditableTable->>Redux: onChange(updatedRows) or onReorder(updatedUids)
Redux-->>EditableTable: updated state (rows with preserved uid)
EditableTable-->>Browser: re-render rows
Note right of EditableTable: multipart file flow
EditableTable->>Browser: request file browse
Browser->>FS: open file picker
FS-->>Browser: selected file paths
Browser->>EditableTable: provide file paths
EditableTable->>Redux: setMultipartFormParams(updatedRowsWithFiles)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (12)
packages/bruno-app/src/components/EditableTable/StyledWrapper.js (1)
22-44: Excessive!importantdeclarations.Multiple
!importantrules in thead styling (lines 23, 25, 26, 31, 35, 36) suggest possible specificity conflicts. Consider reviewing CSS cascade to reduce reliance on!important, which can make future maintenance harder.packages/bruno-app/src/components/CollectionSettings/Vars/VarsTable/index.js (1)
32-60: Consider memoizing the columns array.The
columnsarray contains render functions that depend onstoredTheme,onSave,collection, andvarType. It's recreated each render. Wrapping withuseMemowould prevent unnecessary re-renders in EditableTable.- const columns = [ + const columns = useMemo(() => [ { key: 'name', ... }, { key: 'value', ... } - ]; + ], [storedTheme, onSave, collection, varType]);packages/bruno-app/src/components/RequestPane/RequestHeaders/index.js (1)
45-84: Consider memoizing columns.Similar to VarsTable, the
columnsarray with render functions is recreated each render. Memoizing withuseMemowould optimize re-renders.packages/bruno-app/src/components/CollectionSettings/Headers/index.js (2)
34-69: Consider memoizing columns.Same optimization opportunity as other EditableTable usages in this PR.
98-103: Consider adding reorderable support for consistency.
RequestHeaderscomponent includesreorderable={true}with drag support, but this collection-level Headers component doesn't. If header ordering matters at the collection level, consider adding the same capability.<EditableTable columns={columns} rows={headers} onChange={handleHeadersChange} defaultRow={defaultRow} + reorderable={true} + onReorder={handleHeaderDrag} />packages/bruno-app/src/components/RequestPane/Assertions/index.js (1)
86-108: Unused parameters in render function.The
valueandisLastEmptyRowparameters are destructured but never used in the operator column's render function.- render: ({ row, value, onChange, isLastEmptyRow }) => { + render: ({ row, onChange }) => {packages/bruno-app/src/components/RequestPane/QueryParams/index.js (1)
167-179: No-oponChangefor path params is intentional but worth documenting.The
onChange={() => {}}is correct here since path param value changes are handled viahandlePathParamChangein the column render function, and the table doesn't allow adding/deleting rows. Consider adding a brief comment to clarify this isn't an oversight.{pathParams && pathParams.length > 0 ? ( <EditableTable columns={pathColumns} rows={pathParams} - onChange={() => {}} + onChange={() => {}} // Path param changes handled via render callback defaultRow={{}} showCheckbox={false} showDelete={false} showAddRow={false} />packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js (1)
76-84: UnusedonChangeparameter inhandleValueChange.The
onChangeparameter is passed but never used since the function dispatches directly viahandleParamsChange.- const handleValueChange = useCallback((row, newValue, onChange) => { + const handleValueChange = useCallback((row, newValue) => {Also update the call site at line 144:
- onChange={(newValue) => handleValueChange(row, newValue, onChange)} + onChange={(newValue) => handleValueChange(row, newValue)}packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.js (1)
66-70: Missingenabledfield indefaultRow.The
EditableTablecomponent defaultscheckboxKeyto'enabled', butdefaultRowdoesn't include it. This could cause inconsistent state when new rows are created. The Redux reducersetFormUrlEncodedParamsdefaultsenabledtotrue, so it works, but adding it here improves clarity.const defaultRow = { name: '', value: '', - description: '' + description: '', + enabled: true };packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js (1)
79-83: Missingenabledfield indefaultRow.Same issue as FormUrlEncodedParams -
defaultRowshould includeenabled: truefor consistency with theEditableTablecheckbox behavior.const defaultRow = { name: '', value: '', + enabled: true, ...(varType === 'response' ? { local: false } : {}) };packages/bruno-app/src/components/EditableTable/index.js (2)
108-116: Filter logic could exclude valid rows with falsy key values.The condition
keyVal && (typeof keyVal !== 'string' || keyVal.trim() !== '')filters out rows wherekeyValis any falsy value (0, false, empty string). If a numeric key field could legitimately be0, this would incorrectly filter it out.Given the current usage context (string-based keys like "name"), this is unlikely to cause issues, but worth noting for future use cases.
-const result = updatedRows.filter((row, i) => { - if (showAddRow && i === updatedRows.length - 1) return false; - if (!showAddRow) return true; - const keyVal = keyColumn ? (keyColumn.getValue ? keyColumn.getValue(row) : row[keyColumn.key]) : ''; - return keyVal && (typeof keyVal !== 'string' || keyVal.trim() !== ''); -}); +const result = updatedRows.filter((row, i) => { + if (showAddRow && i === updatedRows.length - 1) return false; + if (!showAddRow) return true; + const keyVal = keyColumn ? (keyColumn.getValue ? keyColumn.getValue(row) : row[keyColumn.key]) : ''; + if (keyVal === null || keyVal === undefined) return false; + if (typeof keyVal === 'string') return keyVal.trim() !== ''; + return true; +});
26-34:createEmptyRowspreadsdefaultRowafter settingcheckboxKey.If
defaultRowcontains a property matchingcheckboxKey(typicallyenabled), it will override the[checkboxKey]: trueset on line 31. This is likely fine ifdefaultRowalways setsenabled: true, but could cause unexpected behavior if a consumer passesenabled: falseindefaultRow.Consider spreading
defaultRowfirst to allow explicit override:const createEmptyRow = useCallback(() => { const newUid = uuid(); emptyRowUidRef.current = newUid; return { + ...defaultRow, uid: newUid, - [checkboxKey]: true, - ...defaultRow + [checkboxKey]: true }; }, [defaultRow, checkboxKey]);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
packages/bruno-app/src/components/CollectionSettings/Headers/index.js(4 hunks)packages/bruno-app/src/components/CollectionSettings/Vars/VarsTable/index.js(1 hunks)packages/bruno-app/src/components/EditableTable/StyledWrapper.js(1 hunks)packages/bruno-app/src/components/EditableTable/index.js(1 hunks)packages/bruno-app/src/components/FolderSettings/Headers/index.js(4 hunks)packages/bruno-app/src/components/FolderSettings/Vars/VarsTable/index.js(1 hunks)packages/bruno-app/src/components/RequestPane/Assertions/index.js(1 hunks)packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.js(1 hunks)packages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.js(1 hunks)packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js(1 hunks)packages/bruno-app/src/components/RequestPane/QueryParams/index.js(4 hunks)packages/bruno-app/src/components/RequestPane/RequestHeaders/index.js(3 hunks)packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js(1 hunks)packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js(13 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (CODING_STANDARDS.md)
**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions.() => {}is good
No space between function name and parentheses.func()notfunc ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly
Files:
packages/bruno-app/src/components/EditableTable/StyledWrapper.jspackages/bruno-app/src/components/EditableTable/index.jspackages/bruno-app/src/components/RequestPane/RequestHeaders/index.jspackages/bruno-app/src/components/CollectionSettings/Headers/index.jspackages/bruno-app/src/components/RequestPane/MultipartFormParams/index.jspackages/bruno-app/src/components/RequestPane/Assertions/index.jspackages/bruno-app/src/components/RequestPane/QueryParams/index.jspackages/bruno-app/src/providers/ReduxStore/slices/collections/index.jspackages/bruno-app/src/components/FolderSettings/Headers/index.jspackages/bruno-app/src/components/CollectionSettings/Vars/VarsTable/index.jspackages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.jspackages/bruno-app/src/components/FolderSettings/Vars/VarsTable/index.jspackages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.jspackages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js
🧠 Learnings (3)
📚 Learning: 2025-12-05T20:31:32.975Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:32.975Z
Learning: Applies to **/*.{jsx,tsx} : Styled Components are used as wrappers to define both self and children components style; Tailwind classes are used specifically for layout based styles
Applied to files:
packages/bruno-app/src/components/EditableTable/StyledWrapper.jspackages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.js
📚 Learning: 2025-12-05T20:31:32.975Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:32.975Z
Learning: Applies to **/*.{jsx,tsx} : Styled Component CSS might also change layout but Tailwind classes shouldn't define colors
Applied to files:
packages/bruno-app/src/components/EditableTable/StyledWrapper.jspackages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.js
📚 Learning: 2025-12-05T20:31:32.975Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:32.975Z
Learning: Applies to **/*.{jsx,tsx} : Use styled component's theme prop to manage CSS colors and not CSS variables when in the context of a styled component or any React component using the styled component
Applied to files:
packages/bruno-app/src/components/EditableTable/StyledWrapper.js
🧬 Code graph analysis (6)
packages/bruno-app/src/components/EditableTable/index.js (1)
packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js (3)
defaultRow(79-83)columns(47-77)getRowError(38-45)
packages/bruno-app/src/components/RequestPane/RequestHeaders/index.js (5)
packages/bruno-app/src/components/RequestPane/QueryParams/index.js (2)
dispatch(18-18)onSave(26-26)packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js (4)
dispatch(14-14)columns(47-77)onSave(17-17)defaultRow(79-83)packages/bruno-app/src/components/EditableTable/index.js (2)
isLastEmptyRow(76-79)EditableTable(7-304)packages/bruno-app/src/utils/codemirror/autocompleteConstants.js (2)
MimeTypes(1-56)MimeTypes(1-56)packages/bruno-app/src/components/BulkEditor/index.js (1)
BulkEditor(7-38)
packages/bruno-app/src/components/CollectionSettings/Headers/index.js (3)
packages/bruno-app/src/components/FolderSettings/Headers/index.js (8)
headerAutoCompleteList(14-14)Headers(16-121)dispatch(17-17)headers(19-21)handleHeadersChange(28-34)handleSave(36-36)columns(38-74)defaultRow(76-80)packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js (2)
saveCollectionSettings(2203-2242)saveCollectionSettings(2203-2242)packages/bruno-app/src/components/EditableTable/index.js (1)
EditableTable(7-304)
packages/bruno-app/src/components/CollectionSettings/Vars/VarsTable/index.js (5)
packages/bruno-app/src/components/FolderSettings/Vars/VarsTable/index.js (8)
VarsTable(13-85)dispatch(14-14)useTheme(15-15)onSave(17-17)handleVarsChange(19-26)getRowError(28-35)columns(37-66)defaultRow(68-72)packages/bruno-app/src/components/CollectionSettings/Headers/index.js (4)
dispatch(17-17)useTheme(18-18)columns(34-69)defaultRow(71-75)packages/bruno-js/src/bru.js (1)
variableNameRegex(7-7)packages/bruno-app/src/components/EditableTable/index.js (1)
EditableTable(7-304)packages/bruno-app/src/components/EditableTable/StyledWrapper.js (1)
StyledWrapper(3-137)
packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.js (2)
packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js (5)
dispatch(14-14)onSave(17-17)handleRun(18-18)columns(47-77)defaultRow(79-83)packages/bruno-app/src/components/EditableTable/index.js (2)
isLastEmptyRow(76-79)EditableTable(7-304)
packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js (2)
packages/bruno-js/src/bru.js (1)
variableNameRegex(7-7)packages/bruno-app/src/components/EditableTable/index.js (2)
isLastEmptyRow(76-79)EditableTable(7-304)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Playwright E2E Tests
- GitHub Check: SSL Tests - Windows
- GitHub Check: Unit Tests
- GitHub Check: CLI Tests
- GitHub Check: SSL Tests - Linux
- GitHub Check: SSL Tests - macOS
🔇 Additional comments (22)
packages/bruno-app/src/components/CollectionSettings/Vars/VarsTable/index.js (2)
62-66: Clean conditional property spread.Good use of the spread operator for conditionally adding
localproperty based onvarType.
68-78: LGTM - Clean EditableTable integration.Proper wiring of
columns,rows,onChange,defaultRow, andgetRowErrorto the EditableTable component. Aligns well with the pattern used in related files.packages/bruno-app/src/components/RequestPane/RequestHeaders/index.js (3)
25-39: Well-structured memoized handlers.Both
handleHeadersChangeandhandleHeaderDragare properly memoized with correct dependency arrays. Clean separation of concerns between bulk updates and reordering.
106-121: LGTM - Clean EditableTable with reorder support.Proper integration of EditableTable with
reorderable={true}andonReorderhandler. The defensiveheaders || []fallback is a good safeguard.
86-90: Verifydescriptionfield usage in headers data model.The
defaultRowincludes adescriptionfield, but confirm whether thecolumnsarray defines a column for it. If not displayed in the UI, verify this field is intentionally preserved for API data consistency or backend persistence, and check if it's included in header payloads sent to the server.packages/bruno-app/src/components/CollectionSettings/Headers/index.js (2)
19-21: LGTM - Clean conditional header retrieval.Proper use of optional chaining with
collection.draft?.rootto determine the correct headers source.
28-30: Well-memoized change handler.Proper use of
useCallbackwith correct dependencies forhandleHeadersChange.packages/bruno-app/src/components/RequestPane/Assertions/index.js (2)
110-134: LGTM on value column rendering logic.The conditional rendering for unary operators (disabled input) vs binary operators (SingleLineEditor) is clean and handles the operator parsing correctly.
137-141:operatorkey indefaultRowmay be unused.The
defaultRowincludes anoperatorkey, butcolumnsonly definesnameandvalueas column keys. IfEditableTableonly processes columns by theirkey, this property won't be set on new rows. Verify whetheroperatoris needed here or if it's vestigial from a prior implementation.packages/bruno-app/src/components/FolderSettings/Vars/VarsTable/index.js (2)
28-35: Validation only checksnamefield, as expected.The
getRowErrorproperly validates only the name field and allows empty names (for new rows). Clean implementation.
37-66: LGTM on columns configuration.The conditional column header with InfoTip for non-request var types is a nice UX touch. The MultiLineEditor integration looks correct.
packages/bruno-app/src/components/FolderSettings/Headers/index.js (3)
76-80:descriptionfield indefaultRowhas no corresponding column.The
defaultRowincludes adescriptionkey, but there's no column defined for it. Verify ifEditableTablepreserves extra properties fromdefaultRowwhen creating new rows, or if this is dead configuration.
45-55: Good: Header name sanitization.Stripping
\r\nfrom header names (line 50) prevents invalid multi-line header names. Solid defensive coding.
103-108: LGTM on EditableTable integration.The component correctly passes headers as rows and uses the centralized
handleHeadersChangefor updates.packages/bruno-app/src/components/RequestPane/QueryParams/index.js (2)
101-112: Path param value changes bypass the genericonChangeprop.The
handlePathParamChangeis called directly in the render function (line 106). This works but creates a subtle inconsistency with how query params are handled. The current approach is acceptable since path params are read-only except for values.
29-36: LGTM on query params handler.Correctly adds
type: 'query'to all params before dispatching. This ensures the type is preserved through bulk updates.packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js (2)
86-99: LGTM ongetFileNamehelper.Good handling of null/empty arrays, platform-specific path separators, and multiple file count display.
114-163: Well-structured conditional rendering for file vs text values.The value cell properly handles file display with clear button, text editing with MultiLineEditor, and conditionally shows the upload button. Clean separation of concerns.
packages/bruno-app/src/components/RequestPane/FormUrlEncodedParams/index.js (1)
1-84: LGTM overall - clean migration to EditableTable.The migration from legacy table components to the unified
EditableTableis well-structured. TheuseCallbackhooks properly stabilize dependencies, and the Redux integration viasetFormUrlEncodedParamsandmoveFormUrlEncodedParamis correct.packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js (1)
38-45: Validation callback is well implemented.The
getRowErrorcallback correctly validates variable names usingvariableNameRegex, returnsnullfor empty names (allowing placeholder rows), and provides a clear error message. Good use ofuseCallbackwith empty deps since no external state is referenced.packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js (1)
1297-1315: New bulk set actions are well-structured.The
setFormUrlEncodedParams,setRequestAssertions,setRequestVars,setFolderVars, andsetCollectionVarsreducers follow a consistent pattern: validate inputs, create draft if needed, and map with UID preservation. Good defensive defaults throughout.Also applies to: 1749-1767, 1883-1907, 2214-2236, 2448-2471
packages/bruno-app/src/components/EditableTable/index.js (1)
1-304: Well-designed reusable component.The
EditableTablecomponent provides good encapsulation of common table behaviors: row management, checkbox toggling, drag-and-drop reordering, and cell rendering. The use ofuseMemoanduseCallbackoptimizes re-renders appropriately. The empty row management logic handles edge cases like stale UIDs.
packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js
Outdated
Show resolved
Hide resolved
packages/bruno-app/src/components/RequestPane/MultipartFormParams/StyledWrapper.js
Show resolved
Hide resolved
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js (1)
1401-1420:setMultipartFormParamsmissingdescriptionfield in mapping.This was flagged in a previous review and appears unaddressed. Other form param actions (e.g.,
setFormUrlEncodedParamsat line 1311) includedescription. This could cause data loss:-item.draft.request.body.multipartForm = map(params, ({ uid, name = '', value = '', contentType = '', type = 'text', enabled = true }) => ({ +item.draft.request.body.multipartForm = map(params, ({ uid, name = '', value = '', contentType = '', type = 'text', description = '', enabled = true }) => ({ uid: uid || uuid(), name, value, contentType, type, + description, enabled }));
🧹 Nitpick comments (3)
packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js (2)
69-77: Potential stale closure onparamsinhandleClearFile.Same pattern as the fixed
handleBrowseFiles- if the user makes changes before this callback runs,paramscould be outdated. Consider reading fresh state fromitem:const handleClearFile = useCallback((row) => { + const currentParams = item.draft + ? get(item, 'draft.request.body.multipartForm') + : get(item, 'request.body.multipartForm'); - const updatedParams = params.map((p) => { + const updatedParams = (currentParams || []).map((p) => { if (p.uid === row.uid) { return { ...p, type: 'text', value: '' }; } return p; }); handleParamsChange(updatedParams); -}, [params, handleParamsChange]); +}, [item, handleParamsChange]);
79-87: Same stale closure concern and unusedonChangeparameter.The
paramsclosure risk applies here too. Additionally,onChangeis passed but never used - remove it to avoid confusion:-const handleValueChange = useCallback((row, newValue, onChange) => { - const updatedParams = params.map((p) => { +const handleValueChange = useCallback((row, newValue) => { + const currentParams = item.draft + ? get(item, 'draft.request.body.multipartForm') + : get(item, 'request.body.multipartForm'); + const updatedParams = (currentParams || []).map((p) => { if (p.uid === row.uid) { return { ...p, type: 'text', value: newValue }; } return p; }); handleParamsChange(updatedParams); -}, [params, handleParamsChange]); +}, [item, handleParamsChange]);Update the caller at line 147 accordingly:
-onChange={(newValue) => handleValueChange(row, newValue, onChange)} +onChange={(newValue) => handleValueChange(row, newValue)}packages/bruno-app/src/components/EditableTable/index.js (1)
81-116: Consider simplifying the filter logic.The filtering at lines 108-113 is complex. It filters out empty rows to pass to
onChange, but the conditions are hard to follow. Consider extracting to a named function for clarity:const filterEmptyTrailingRows = (rows) => { const keyColumn = columns.find((col) => col.isKeyField); return rows.filter((row, i) => { if (showAddRow && i === rows.length - 1) return false; if (!keyColumn) return true; const keyVal = keyColumn.getValue ? keyColumn.getValue(row) : row[keyColumn.key]; return keyVal && (typeof keyVal !== 'string' || keyVal.trim() !== ''); }); };
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/bruno-app/src/components/EditableTable/index.js(1 hunks)packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js(1 hunks)packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js(13 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (CODING_STANDARDS.md)
**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions.() => {}is good
No space between function name and parentheses.func()notfunc ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly
Files:
packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.jspackages/bruno-app/src/providers/ReduxStore/slices/collections/index.jspackages/bruno-app/src/components/EditableTable/index.js
🧬 Code graph analysis (2)
packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js (2)
packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js (2)
browseFiles(2195-2201)browseFiles(2195-2201)packages/bruno-app/src/utils/common/platform.js (2)
isWindowsOS(22-27)isWindowsOS(22-27)
packages/bruno-app/src/components/EditableTable/index.js (1)
packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js (2)
columns(47-77)getRowError(38-45)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Playwright E2E Tests
- GitHub Check: CLI Tests
- GitHub Check: Unit Tests
- GitHub Check: SSL Tests - Windows
- GitHub Check: SSL Tests - macOS
- GitHub Check: SSL Tests - Linux
🔇 Additional comments (14)
packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js (2)
89-102: LGTM!
getFileNamehandles both single and multiple files correctly, with proper Windows/Unix path separator detection. Edge cases (null, empty array, empty strings) are well covered.
104-185: Clean column configuration and EditableTable integration.The columns setup with custom render functions for file handling is well-structured. The conditional rendering for file display vs. text editor is clear.
Also applies to: 187-206
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js (6)
1300-1318: LGTM!
setFormUrlEncodedParamscorrectly maps all fields includingdescriptionand preserves UIDs when provided.
1752-1770: LGTM!
setRequestAssertionscorrectly includes theoperatorfield and follows the established pattern.
1886-1910: LGTM!
setRequestVarscorrectly handles the conditionallocalfield for response-type variables.
2217-2239: LGTM!
setFolderVarsproperly initializesfolder.draftfromfolder.rootand handles both request/response types.
2451-2474: LGTM!
setCollectionVarsfollows the same consistent pattern as other bulk-set actions.
1231-1240: LGTM!
setFolderHeadersnow correctly initializesfolder.draftbefore modifying headers, addressing the previous review concern about bypassing the draft workflow.packages/bruno-app/src/components/EditableTable/index.js (6)
7-20: Well-designed prop interface.Good defaults and clear prop names. The flexibility to customize checkbox behavior, deletion, and reordering makes this component reusable across the codebase.
36-66: Solid trailing empty row management.The logic correctly handles edge cases: empty initial state, preventing duplicate empty rows, and maintaining UID stability. The check at line 57 prevents UID collisions if a row somehow matches the empty row UID.
144-156: Drag-drop reorder excludes trailing empty row correctly.Good handling at line 148 to slice off the empty row before reordering. The
updateReorderedItemcallback shape aligns with the Redux actions expecting UID arrays.
193-208: Error tooltip implementation looks correct.Using
data-tooltip-idon the anchor andidon theTooltipfollows react-tooltip v5+ API. The error is only shown for non-empty rows.
251-280: Drag handle visibility tied to hover state.The conditional rendering based on
hoveredRow === rowIndexmeans the grip icon only appears on hover. This is good UX but note: if users need visual affordance that rows are reorderable, consider showing a subtle indicator always.
236-298: Solid row rendering with conditional drag behavior.The
canDragcheck properly prevents dragging empty rows and respects thereorderableprop. Event handlers are correctly conditionally applied.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (9)
packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js (1)
60-64: Checkbox alignment tweak is a solid simplificationCentering via
vertical-align: middleand resettingmarginis cleaner and more predictable than positional nudging; this should align with the new table styling well.If you later see browser-specific misalignment, consider also normalizing
line-heighton the checkbox container rather than the input itself, but it’s not necessary for this PR.packages/bruno-app/src/components/WorkspaceHome/StyledWrapper.js (1)
99-99: Consider refactoring CSS variable to theme prop for consistency.Line 99 uses a CSS variable for color, while the rest of the file uses theme props. Based on learnings, styled components should use theme props for colors.
Apply this diff for consistency:
- color: var(--color-tab-inactive); + color: ${(props) => props.theme.tabs.inactive.color};Note: Verify the correct theme path exists for inactive tab color.
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/StyledWrapper.js (1)
1-133: Theme usage and layout in StyledWrapper look solid.The wrapper correctly uses
props.themefor all colors/typography and mirrors the workspace rename/error patterns, so it should integrate cleanly with the existing UI. There is some duplication withWorkspaceHome/StyledWrapper(e.g.,.inline-actions,.inline-action-btn, error tooltip), which could be factored into a shared helper later if this pattern spreads further.packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js (1)
21-27: Environment variables table styling aligns with EditableTable patterns.Updating
tdpadding/vertical-align, header color/font-size, and input/checkbox alignment makes this table visually consistent with the newEditableTablestyles and keeps colors theme-driven. If more tables converge on this look, consider sharing more of this styling with the genericEditableTableStyledWrapperto avoid drift.Also applies to: 41-45, 103-109, 119-126
packages/bruno-app/src/components/RequestPane/Assertions/index.js (2)
12-52: Consolidate assertion operator helpers to avoid duplication.
unaryOperators, the full operators list insideparseAssertionOperator, and the operator options inAssertionOperatorall encode essentially the same sets. Keeping these in one shared module (e.g.,assertionOperators.js) would reduce drift when adding/removing operators and make tests easier to maintain.
142-147: EditableTable wiring for assertions looks appropriate; consider cleaning up the extraoperatorfield.Passing
columns,rows={assertions || []},defaultRow(withvalue: 'eq '), andreorderable/onReorderintoEditableTablematches the intended API and should work well with drag-reorder and empty-row handling. The persisted operator is now encoded insidevalue("operator value"), so the separateoperator: 'eq'field indefaultRowappears unused; you might be able to drop or repurpose it to avoid confusion about the source of truth.Also applies to: 150-157
packages/bruno-app/src/components/EditableTable/index.js (3)
36-79: Clarify or enforce the requirement for anisKeyFieldcolumn.
rowsWithEmpty,isEmptyRow,isLastEmptyRow, and the finalresultfilter all assume there is a column withisKeyField: true. If no such column exists,keyColumnisundefined, and the filter will effectively drop all rows whenshowAddRowis true. At minimum, it’s worth documenting thatEditableTablerequires exactly one key column; alternatively, you could add a runtime guard (e.g.,console.warnor throwing in dev) when!columns.some(c => c.isKeyField).
81-116: Last empty row drops non-key edits; consider whether that UX is acceptable.
handleValueChangeonly promotes the last row into a “real” row when the key field changes from empty to non-empty. Edits to other columns on the last row are applied toupdatedRowsbut then filtered out (the last row is removed fromresultand recreated fromdefaultRowon the next render). That means typing into a non-key field of the add-row is effectively discarded.If you want to allow users to fill non-key fields first, you could:
- Treat a row as “non-empty” when any of a configurable set of columns has data, or
- Skip the
i === updatedRows.length - 1filter when!isEmptyRow(row)so partial edits on the last row are preserved.As-is, it’s a reasonable tradeoff if the intended flow is “enter key column first,” but it’s worth confirming this matches UX expectations.
24-25: Remove unuseddragStartstate to reduce noise.
dragStartis set inhandleDragStartand cleared inhandleDragEnd, but never read. You can safely drop this state (and its setter) to avoid unnecessary state updates during drag-and-drop.Also applies to: 132-136, 158-161
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
packages/bruno-app/src/components/EditableTable/StyledWrapper.js(1 hunks)packages/bruno-app/src/components/EditableTable/index.js(1 hunks)packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js(2 hunks)packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js(2 hunks)packages/bruno-app/src/components/RequestPane/Assertions/index.js(1 hunks)packages/bruno-app/src/components/WorkspaceHome/StyledWrapper.js(1 hunks)packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js(4 hunks)packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js(1 hunks)packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/StyledWrapper.js(1 hunks)packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/index.js(1 hunks)packages/bruno-app/src/components/WorkspaceHome/index.js(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/bruno-app/src/components/EditableTable/StyledWrapper.js
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (CODING_STANDARDS.md)
**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions.() => {}is good
No space between function name and parentheses.func()notfunc ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly
Files:
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/index.jspackages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/index.jspackages/bruno-app/src/components/EditableTable/index.jspackages/bruno-app/src/components/RequestPane/Assertions/index.jspackages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.jspackages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js
🧠 Learnings (3)
📚 Learning: 2025-12-05T20:31:33.005Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:33.005Z
Learning: Applies to **/*.{jsx,tsx} : Styled Components are used as wrappers to define both self and children components style; Tailwind classes are used specifically for layout based styles
Applied to files:
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/index.jspackages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.jspackages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js
📚 Learning: 2025-12-05T20:31:33.005Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:33.005Z
Learning: Applies to **/*.{jsx,tsx} : Styled Component CSS might also change layout but Tailwind classes shouldn't define colors
Applied to files:
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/index.jspackages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js
📚 Learning: 2025-12-05T20:31:33.005Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:33.005Z
Learning: Applies to **/*.{jsx,tsx} : Use styled component's theme prop to manage CSS colors and not CSS variables when in the context of a styled component or any React component using the styled component
Applied to files:
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/StyledWrapper.jspackages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/index.jspackages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.jspackages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js
🧬 Code graph analysis (3)
packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/StyledWrapper.js (1)
packages/bruno-app/src/components/WorkspaceHome/StyledWrapper.js (1)
StyledWrapper(3-133)
packages/bruno-app/src/components/EditableTable/index.js (3)
packages/bruno-app/src/components/FolderSettings/Headers/index.js (2)
defaultRow(76-80)columns(38-74)packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js (3)
defaultRow(79-83)columns(47-77)getRowError(38-45)packages/bruno-app/src/components/EditableTable/StyledWrapper.js (1)
StyledWrapper(3-144)
packages/bruno-app/src/components/RequestPane/Assertions/index.js (3)
packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js (8)
unaryOperators(78-91)unaryOperators(117-130)parseAssertionOperator(39-114)parseAssertionOperator(146-146)operators(47-76)operator(93-93)value(94-94)isUnaryOperator(116-133)packages/bruno-app/src/components/RequestPane/Assertions/AssertionOperator/index.js (1)
AssertionOperator(36-92)packages/bruno-app/src/components/EditableTable/index.js (2)
isLastEmptyRow(76-79)EditableTable(7-304)
🔇 Additional comments (7)
packages/bruno-app/src/components/WorkspaceHome/index.js (2)
222-223: LGTM! Header sizing refinement.The reduction in text size (
text-xl→text-sm) and icon size (24 → 18) creates a more compact workspace header, consistent with the broader UI modernization described in the PR summary.
305-305: LGTM! Tab padding refinement.The vertical padding adjustment (
py-2→pt-2 pb-1.5) subtly reduces tab height while maintaining consistent spacing with the updated header styling.packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js (1)
10-15: Table cell vertical alignment change looks goodUsing
vertical-align: middleontdwill help keep text and controls visually centered in rows and is consistent with the broader table cleanup. No issues.packages/bruno-app/src/components/WorkspaceHome/StyledWrapper.js (1)
111-111: LGTM! Clean styling improvement.Adding medium font-weight to active tabs improves visual hierarchy and user feedback.
packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js (2)
10-27: Vertical centering for table cells is a good improvementAdding
vertical-align: middleto the table cell rule will help keep header and body content visually aligned when rows get taller, without affecting logic or theming. Looks good as part of the broader table standardization.
60-64: Checkbox alignment tweak is appropriate and non-breakingCentering the checkbox vertically and resetting its margin to
0should remove the previous “off by a pixel” feel and align it better with adjacent text/controls inside the table cells. This is a safe, localized styling improvement.packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/index.js (1)
10-10: StyledWrapper import looks correct and consistent.Import path and usage of the extracted
StyledWrappermatch the local file structure; no behavior concerns here.
| key: 'operator', | ||
| name: 'Operator', | ||
| width: '120px', | ||
| render: ({ row, rowIndex, isLastEmptyRow }) => { | ||
| const { operator } = parseAssertionOperator(row.value); | ||
| const assertionValue = parseAssertionOperator(row.value).value; | ||
|
|
||
| const handleOperatorChange = (newOperator) => { | ||
| const updatedAssertions = assertions.map((assertion, idx) => { | ||
| if (idx === rowIndex) { | ||
| return { | ||
| ...assertion, | ||
| value: isUnaryOperator(newOperator) ? newOperator : `${newOperator} ${assertionValue}` | ||
| }; | ||
| } | ||
| return assertion; | ||
| }); | ||
| handleAssertionsChange(updatedAssertions); | ||
| }; | ||
|
|
||
| return ( | ||
| <AssertionOperator | ||
| operator={operator} | ||
| onChange={handleOperatorChange} | ||
| /> | ||
| ); | ||
| } |
There was a problem hiding this comment.
Use EditableTable’s onChange for operator updates and avoid indexing into assertions.
Right now, the Operator column:
- Parses
row.valuetwice - Rebuilds
updatedAssertionsfrom the externalassertionsarray usingrowIndex - Dispatches
setRequestAssertionsdirectly
This has a couple of downsides:
- Changing the operator on the trailing “empty” row is effectively a no-op (there’s no corresponding entry in
assertions), so the select will snap back to the default and the choice is lost. - It bypasses
EditableTable’sonChange/handleValueChangemachinery, which is what manages the empty row lifecycle and any future validation.
You can simplify and make this more robust by using the value and onChange provided by the column render, and parsing only once, e.g.:
- render: ({ row, rowIndex, isLastEmptyRow }) => {
- const { operator } = parseAssertionOperator(row.value);
- const assertionValue = parseAssertionOperator(row.value).value;
-
- const handleOperatorChange = (newOperator) => {
- const updatedAssertions = assertions.map((assertion, idx) => {
- if (idx === rowIndex) {
- return {
- ...assertion,
- value: isUnaryOperator(newOperator) ? newOperator : `${newOperator} ${assertionValue}`
- };
- }
- return assertion;
- });
- handleAssertionsChange(updatedAssertions);
- };
+ render: ({ value, onChange }) => {
+ const { operator, value: assertionValue } = parseAssertionOperator(value);
+
+ const handleOperatorChange = (newOperator) => {
+ const nextValue = isUnaryOperator(newOperator)
+ ? newOperator
+ : `${newOperator} ${assertionValue}`;
+
+ onChange(nextValue);
+ };- return (
- <AssertionOperator
- operator={operator}
- onChange={handleOperatorChange}
- />
- );
+ return (
+ <AssertionOperator
+ operator={operator}
+ onChange={handleOperatorChange}
+ />
+ );This keeps all row mutation logic inside EditableTable, avoids relying on rowIndex/assertions, and fixes the “last empty row operator change is ignored” behavior.
Also applies to: 116-137
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js (1)
1404-1423:setMultipartFormParamsmissingdescriptionfield in mapping.Other form param actions (e.g.,
setFormUrlEncodedParamsat line 1314) includedescriptionin the mapping. This omission causes data loss when updating multipart form params.-item.draft.request.body.multipartForm = map(params, ({ uid, name = '', value = '', contentType = '', type = 'text', enabled = true }) => ({ +item.draft.request.body.multipartForm = map(params, ({ uid, name = '', value = '', contentType = '', type = 'text', description = '', enabled = true }) => ({ uid: uid || uuid(), name, value, contentType, type, + description, enabled }));packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js (1)
64-66: Silent failure on file browse error.When
browseFiles()fails, the error is only logged to console. Users won't know the operation failed.Consider adding a toast notification:
.catch((error) => { console.error(error); + // Add user-facing feedback, e.g.: + // toast.error('Failed to select files'); });
🧹 Nitpick comments (5)
packages/bruno-app/src/components/RequestPane/Assertions/index.js (2)
91-93: Redundant parsing ofrow.value.
parseAssertionOperator(row.value)is called twice in succession (lines 92 and 93). Destructure both values in one call:- const { operator } = parseAssertionOperator(row.value); - const assertionValue = parseAssertionOperator(row.value).value; + const { operator, value: assertionValue } = parseAssertionOperator(row.value);
151-155:operatorfield indefaultRowappears unused.The assertion data model stores the operator as a prefix in the
valuefield (e.g.,"eq someValue"). The standaloneoperatorproperty indefaultRowisn't persisted and may cause confusion.const defaultRow = { name: '', - value: 'eq ', - operator: 'eq' + value: 'eq ' };packages/bruno-app/src/components/EditableTable/index.js (2)
109-118:hasAnyValuemay incorrectly filter rows with intentional default values.If
defaultRowcontains meaningful defaults (e.g.,type: 'text'), comparingval !== defaultValwill treat rows with those defaults as "having a value" and persist them prematurely.Consider checking only the key field or columns explicitly marked as significant:
const hasAnyValue = (row) => { - for (const col of columns) { - const val = col.getValue ? col.getValue(row) : row[col.key]; - const defaultVal = defaultRow[col.key]; - if (val && val !== defaultVal && (typeof val !== 'string' || val.trim() !== '')) { - return true; - } - } - return false; + const keyColumn = columns.find((col) => col.isKeyField); + if (!keyColumn) return false; + const val = keyColumn.getValue ? keyColumn.getValue(row) : row[keyColumn.key]; + return val && (typeof val !== 'string' || val.trim() !== ''); };
265-282: Drag handle lacks keyboard accessibility.Drag-and-drop reordering is mouse-only. For accessibility, consider adding keyboard-based reorder (e.g., up/down arrow keys on focused rows). This is a nice-to-have for future improvement.
packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js (1)
194-199:defaultRowmissingdescriptionfield.For consistency with the data model and other form param components, include
description:const defaultRow = { name: '', value: '', contentType: '', - type: 'text' + type: 'text', + description: '' };
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
packages/bruno-app/src/components/EditableTable/StyledWrapper.js(1 hunks)packages/bruno-app/src/components/EditableTable/index.js(1 hunks)packages/bruno-app/src/components/RequestPane/Assertions/index.js(1 hunks)packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js(1 hunks)packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js(4 hunks)packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js(13 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/bruno-app/src/components/EditableTable/StyledWrapper.js
- packages/bruno-app/src/components/WorkspaceHome/WorkspaceEnvironments/EnvironmentList/EnvironmentDetails/EnvironmentVariables/StyledWrapper.js
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (CODING_STANDARDS.md)
**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions.() => {}is good
No space between function name and parentheses.func()notfunc ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly
Files:
packages/bruno-app/src/components/RequestPane/Assertions/index.jspackages/bruno-app/src/providers/ReduxStore/slices/collections/index.jspackages/bruno-app/src/components/EditableTable/index.jspackages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js
🧬 Code graph analysis (2)
packages/bruno-app/src/components/RequestPane/Assertions/index.js (2)
packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js (9)
unaryOperators(78-91)unaryOperators(117-130)parseAssertionOperator(39-114)parseAssertionOperator(146-146)operators(47-76)operator(93-93)value(94-94)isUnaryOperator(116-133)useTheme(144-144)packages/bruno-app/src/components/RequestPane/Assertions/AssertionOperator/index.js (1)
AssertionOperator(36-92)
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js (4)
packages/bruno-app/src/utils/collections/index.js (13)
item(1037-1037)item(1261-1261)collection(582-582)collection(1160-1160)collection(1162-1162)collection(1590-1590)collection(1600-1600)findCollectionByUid(80-82)findCollectionByUid(80-82)findItemInCollection(117-121)findItemInCollection(117-121)isItemARequest(827-829)isItemARequest(827-829)packages/bruno-app/src/utils/common/index.js (2)
uuid(15-21)uuid(15-21)packages/bruno-cli/src/utils/collection.js (2)
findItemInCollection(336-340)type(544-544)packages/bruno-app/src/utils/tabs/index.js (2)
isItemARequest(3-5)isItemARequest(3-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Playwright E2E Tests
- GitHub Check: SSL Tests - Linux
- GitHub Check: Unit Tests
- GitHub Check: CLI Tests
- GitHub Check: SSL Tests - Windows
- GitHub Check: SSL Tests - macOS
🔇 Additional comments (7)
packages/bruno-app/src/components/RequestPane/Assertions/index.js (1)
128-147: LGTM!Value column correctly handles unary operators with a disabled input and binary operators with the SingleLineEditor, reconstructing the prefixed value on change.
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js (2)
1755-1773:operatorfield insetRequestAssertionsmay be inconsistent with data model.The assertion parsing logic in
Assertions/index.jsextracts the operator from thevaluefield prefix (e.g.,"eq someValue"). Storingoperatoras a separate field here could cause schema drift if not used consistently.Verify if assertions should store
operatorseparately or if this field should be removed from the mapping.
1231-1243: LGTM!
setFolderHeadersnow correctly initializesfolder.draftandfolder.draft.requestbefore assignment, addressing the previous draft/save workflow issue.packages/bruno-app/src/components/EditableTable/index.js (2)
156-168: LGTM!Drag-drop logic correctly excludes the trailing empty row from reordering and emits the updated UID order.
206-217: LGTM!
react-tooltipv5 API correctly used withdata-tooltip-idon the anchor andidon theTooltip.packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js (2)
96-109: LGTM!
getFileNamehandles edge cases well—null values, empty arrays, single vs. multiple files, and OS-specific path separators.
124-173: LGTM!Value column handles file vs. text mode elegantly, with appropriate UI affordances for each state. The upload button visibility logic prevents accidental overwrites.
| const mappedVars = map(vars, ({ uid, name = '', value = '', enabled = true, local = false }) => ({ | ||
| uid: uid || uuid(), | ||
| name, | ||
| value, | ||
| enabled, | ||
| ...(type === 'response' ? { local } : {}) | ||
| })); |
There was a problem hiding this comment.
local field excluded for request vars, inconsistent with addVar.
addVar (lines 1809-1815) includes local: varData.local === true for request-type vars, but setRequestVars conditionally omits it. This could cause data loss.
const mappedVars = map(vars, ({ uid, name = '', value = '', enabled = true, local = false }) => ({
uid: uid || uuid(),
name,
value,
enabled,
- ...(type === 'response' ? { local } : {})
+ local
}));Alternatively, verify if local should indeed be excluded for request vars.
🤖 Prompt for AI Agents
In packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
around lines 1901-1907, the mappedVars creation omits the local field for
request-type vars causing inconsistency with addVar; change the mapping to
always include local (e.g. local: local === true) instead of conditionally only
for type === 'response' so request vars preserve the local flag just like addVar
does.
| const mappedVars = map(vars, ({ uid, name = '', value = '', enabled = true, local = false }) => ({ | ||
| uid: uid || uuid(), | ||
| name, | ||
| value, | ||
| enabled, | ||
| ...(type === 'response' ? { local } : {}) | ||
| })); |
There was a problem hiding this comment.
Same local field inconsistency in setFolderVars.
Same pattern as setRequestVars—verify if local should be included for all var types consistently.
🤖 Prompt for AI Agents
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js around
lines 2230-2236: the mappedVars construction conditionally adds the local field
only when type === 'response', causing an inconsistency with other var setters;
make it consistent by always including the local property (defaulting to false)
for every var entry (remove the conditional spread) or alternatively mirror the
exact behavior used in setRequestVars—ensure the chosen behavior is applied to
setFolderVars so local is handled consistently across setters.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/request/newlines/newlines-persistence.spec.ts (1)
32-51: Add assertions to verify rows exist before interaction.The test now uses
.first()to select pre-existing rows for params, headers, and vars without verifying they exist. This could lead to test failures if the tables don't have default rows.Consider adding visibility assertions before interaction:
await page.getByRole('tab', { name: 'Params' }).click(); const paramRow = page.locator('table tbody tr').first(); + await expect(paramRow).toBeVisible(); await getTableCell(paramRow, 0).locator('input[type="text"]').fill('queryParamKey'); await page.getByRole('tab', { name: 'Headers' }).click(); const headerRow = page.locator('table tbody tr').first(); + await expect(headerRow).toBeVisible(); await getTableCell(headerRow, 0).locator('.CodeMirror').click();tests/variable-tooltip/variable-tooltip.spec.ts (1)
70-77: Improved selector scoping.The new pattern using
headerTable -> headerRow -> editoris cleaner and more specific than selecting table rows globally. This reduces the risk of selecting unintended elements if multiple tables are present.However, the same concern applies here: the test assumes the first row exists in the header table. Consider adding:
await expect(headerRow).toBeVisible();before interacting with its editors.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js(13 hunks)tests/collection/draft/draft-indicator.spec.ts(2 hunks)tests/collection/draft/draft-values-in-requests.spec.ts(1 hunks)tests/request/newlines/newlines-persistence.spec.ts(1 hunks)tests/variable-tooltip/variable-tooltip.spec.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (CODING_STANDARDS.md)
**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions.() => {}is good
No space between function name and parentheses.func()notfunc ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly
Files:
tests/collection/draft/draft-values-in-requests.spec.tstests/collection/draft/draft-indicator.spec.tstests/request/newlines/newlines-persistence.spec.tstests/variable-tooltip/variable-tooltip.spec.ts
tests/**/**.*
⚙️ CodeRabbit configuration file
tests/**/**.*: Review the following e2e test code written using the Playwright test library. Ensure that:
Follow best practices for Playwright code and e2e automation
Try to reduce usage of
page.waitForTimeout();in code unless absolutely necessary and the locator cannot be found using existingexpect()playwright callsAvoid using
page.pause()in codeUse locator variables for locators
Avoid using test.only
Use multiple assertions
Promote the use of
test.stepas much as possible so the generated reports are easier to readEnsure that the
fixtureslike the collections are nested inside thefixturesfolderFixture Example*: Here's an example of possible fixture and test pair
. ├── fixtures │ └── collection │ ├── base.bru │ ├── bruno.json │ ├── collection.bru │ ├── ws-test-request-with-headers.bru │ ├── ws-test-request-with-subproto.bru │ └── ws-test-request.bru ├── connection.spec.ts # <- Depends on the collection in ./fixtures/collection ├── headers.spec.ts ├── persistence.spec.ts ├── variable-interpolation │ ├── fixtures │ │ └── collection │ │ ├── environments │ │ ├── bruno.json │ │ └── ws-interpolation-test.bru │ ├── init-user-data │ └── variable-interpolation.spec.ts # <- Depends on the collection in ./variable-interpolation/fixtures/collection └── subproto.spec.ts
Files:
tests/collection/draft/draft-values-in-requests.spec.tstests/collection/draft/draft-indicator.spec.tstests/request/newlines/newlines-persistence.spec.tstests/variable-tooltip/variable-tooltip.spec.ts
🧠 Learnings (1)
📚 Learning: 2025-12-05T20:31:33.005Z
Learnt from: CR
Repo: usebruno/bruno PR: 0
File: CODING_STANDARDS.md:0-0
Timestamp: 2025-12-05T20:31:33.005Z
Learning: Applies to **/*.test.{js,jsx,ts,tsx} : Add tests for any new functionality or meaningful changes. If code is added, removed, or significantly modified, corresponding tests should be updated or created
Applied to files:
tests/collection/draft/draft-indicator.spec.ts
🧬 Code graph analysis (1)
tests/request/newlines/newlines-persistence.spec.ts (1)
tests/utils/page/locators.ts (1)
getTableCell(126-126)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: SSL Tests - Windows
- GitHub Check: SSL Tests - macOS
- GitHub Check: SSL Tests - Linux
- GitHub Check: Unit Tests
- GitHub Check: Playwright E2E Tests
- GitHub Check: CLI Tests
🔇 Additional comments (3)
tests/collection/draft/draft-indicator.spec.ts (2)
200-202: LGTM!The simplified selector
varRow.locator('.CodeMirror')is appropriate here since the var value cell should contain only one CodeMirror editor. The variable naming is also more descriptive.
314-316: LGTM!Consistent selector pattern with the collection vars test above. The naming clearly distinguishes this as the folder-level var value editor.
tests/collection/draft/draft-values-in-requests.spec.ts (1)
50-59: Verify that EditableTable pre-populates an editable row.The test assumes a first row exists in the folder header table without explicitly creating it (lines 50-51). If the EditableTable component doesn't pre-populate an empty row on initialization, this test will fail when attempting to interact with
folderHeaderRow. Confirm that the FolderSettings/Headers component's EditableTable initializes with at least one empty row, or add explicit row creation before these interactions.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
tests/collection/create/create-collection.spec.ts (1)
32-32: Good locator scoping; factor out a reusable locator variableScoping the textarea under
#request-urlis a solid improvement and should be more robust than the old generictextareaselector. To cut duplication and better follow the “use locator variables” guideline, consider extracting this into a local locator:// Set the URL - await page.locator('#request-url .CodeMirror').click(); - await page.locator('#request-url').locator('textarea').fill('http://localhost:8081'); + const requestUrlTextarea = page.locator('#request-url textarea'); + await page.locator('#request-url .CodeMirror').click(); + await requestUrlTextarea.fill('http://localhost:8081'); @@ // Send a request - await page.locator('#request-url .CodeMirror').click(); - await page.locator('#request-url').locator('textarea').fill('/ping'); + await page.locator('#request-url .CodeMirror').click(); + await requestUrlTextarea.fill('/ping');If you want to double‑check best practices for locator reuse in Playwright 1.51.x, please confirm against the current Playwright docs.
Also applies to: 37-37
tests/collection/moving-requests/cross-collection-drag-drop-request.spec.ts (1)
17-21: Scoped URL textarea locator is solid; consider DRYing via a locator variableThe new
page.locator('#request-url').locator('textarea')is a clear improvement over a generictextareaand should be more stable. To better follow the guideline of using locator variables and to avoid repeating the#request-urlselector, consider extracting a locator per test and reusing it for both click and fill:@@ - // Set the URL - await page.locator('#request-url .CodeMirror').click(); - await page.locator('#request-url').locator('textarea').fill('https://echo.usebruno.com'); + // Set the URL + const requestUrl = page.locator('#request-url'); + await requestUrl.locator('.CodeMirror').click(); + await requestUrl.locator('textarea').fill('https://echo.usebruno.com'); @@ - // Set the URL - await page.locator('#request-url .CodeMirror').click(); - await page.locator('#request-url').locator('textarea').fill('https://echo.usebruno.com'); + // Set the URL + const sourceRequestUrl = page.locator('#request-url'); + await sourceRequestUrl.locator('.CodeMirror').click(); + await sourceRequestUrl.locator('textarea').fill('https://echo.usebruno.com'); @@ - // Set the URL - await page.locator('#request-url .CodeMirror').click(); - await page.locator('#request-url').locator('textarea').fill('https://echo.usebruno.com'); + // Set the URL + const targetRequestUrl = page.locator('#request-url'); + await targetRequestUrl.locator('.CodeMirror').click(); + await targetRequestUrl.locator('textarea').fill('https://echo.usebruno.com');Also applies to: 74-78, 88-92
tests/collection/moving-tabs/move-tabs.spec.ts (1)
53-55: Selector refinement looks good; consider using a locator variable for reuseScoping the textarea fill to
#request-urlis an improvement over a broad textarea selector. To align with the Playwright guideline of using locator variables and to avoid duplicating the selector across both tests, you could capture the locator once in each test and reuse it:@@ - await page.locator('#request-url').locator('textarea').fill('https://echo.usebruno.com'); + const requestUrlTextarea = page.locator('#request-url textarea'); + await requestUrlTextarea.fill('https://echo.usebruno.com'); @@ - await page.locator('#request-url').locator('textarea').fill('https://echo.usebruno.com'); + const requestUrlTextarea = page.locator('#request-url textarea'); + await requestUrlTextarea.fill('https://echo.usebruno.com');This keeps the selector DRY and makes future selector changes easier in both tests.
Also applies to: 143-146
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
tests/collection/create/create-collection.spec.ts(1 hunks)tests/collection/moving-requests/cross-collection-drag-drop-request.spec.ts(3 hunks)tests/collection/moving-tabs/move-tabs.spec.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (CODING_STANDARDS.md)
**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions.() => {}is good
No space between function name and parentheses.func()notfunc ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly
Files:
tests/collection/moving-tabs/move-tabs.spec.tstests/collection/moving-requests/cross-collection-drag-drop-request.spec.tstests/collection/create/create-collection.spec.ts
tests/**/**.*
⚙️ CodeRabbit configuration file
tests/**/**.*: Review the following e2e test code written using the Playwright test library. Ensure that:
Follow best practices for Playwright code and e2e automation
Try to reduce usage of
page.waitForTimeout();in code unless absolutely necessary and the locator cannot be found using existingexpect()playwright callsAvoid using
page.pause()in codeUse locator variables for locators
Avoid using test.only
Use multiple assertions
Promote the use of
test.stepas much as possible so the generated reports are easier to readEnsure that the
fixtureslike the collections are nested inside thefixturesfolderFixture Example*: Here's an example of possible fixture and test pair
. ├── fixtures │ └── collection │ ├── base.bru │ ├── bruno.json │ ├── collection.bru │ ├── ws-test-request-with-headers.bru │ ├── ws-test-request-with-subproto.bru │ └── ws-test-request.bru ├── connection.spec.ts # <- Depends on the collection in ./fixtures/collection ├── headers.spec.ts ├── persistence.spec.ts ├── variable-interpolation │ ├── fixtures │ │ └── collection │ │ ├── environments │ │ ├── bruno.json │ │ └── ws-interpolation-test.bru │ ├── init-user-data │ └── variable-interpolation.spec.ts # <- Depends on the collection in ./variable-interpolation/fixtures/collection └── subproto.spec.ts
Files:
tests/collection/moving-tabs/move-tabs.spec.tstests/collection/moving-requests/cross-collection-drag-drop-request.spec.tstests/collection/create/create-collection.spec.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Unit Tests
- GitHub Check: CLI Tests
- GitHub Check: Playwright E2E Tests
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
tests/utils/page/locators.ts (1)
126-126: Add type annotations for parameters.The
rowandindexparameters lack type annotations. Consider adding them for better type safety:-export const getTableCell = (row, index) => row.locator('td').nth(index + 1); +export const getTableCell = (row: any, index: number) => row.locator('td').nth(index + 1);(Replace
anywith the appropriate Playwright Locator type if available in your imports.)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
tests/collection/moving-tabs/move-tabs.spec.ts(2 hunks)tests/request/newlines/newlines-persistence.spec.ts(2 hunks)tests/utils/page/locators.ts(1 hunks)tests/variable-tooltip/variable-tooltip.spec.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- tests/collection/moving-tabs/move-tabs.spec.ts
- tests/request/newlines/newlines-persistence.spec.ts
- tests/variable-tooltip/variable-tooltip.spec.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (CODING_STANDARDS.md)
**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings. For JSX/TSX attributes, use double quotes (e.g., )
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single params
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses
Space before and after the arrow in arrow functions.() => {}is good
No space between function name and parentheses.func()notfunc ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Add in meaningful comments instead of obvious ones where complex code flow is explained properly
Files:
tests/utils/page/locators.ts
tests/**/**.*
⚙️ CodeRabbit configuration file
tests/**/**.*: Review the following e2e test code written using the Playwright test library. Ensure that:
Follow best practices for Playwright code and e2e automation
Try to reduce usage of
page.waitForTimeout();in code unless absolutely necessary and the locator cannot be found using existingexpect()playwright callsAvoid using
page.pause()in codeUse locator variables for locators
Avoid using test.only
Use multiple assertions
Promote the use of
test.stepas much as possible so the generated reports are easier to readEnsure that the
fixtureslike the collections are nested inside thefixturesfolderFixture Example*: Here's an example of possible fixture and test pair
. ├── fixtures │ └── collection │ ├── base.bru │ ├── bruno.json │ ├── collection.bru │ ├── ws-test-request-with-headers.bru │ ├── ws-test-request-with-subproto.bru │ └── ws-test-request.bru ├── connection.spec.ts # <- Depends on the collection in ./fixtures/collection ├── headers.spec.ts ├── persistence.spec.ts ├── variable-interpolation │ ├── fixtures │ │ └── collection │ │ ├── environments │ │ ├── bruno.json │ │ └── ws-interpolation-test.bru │ ├── init-user-data │ └── variable-interpolation.spec.ts # <- Depends on the collection in ./variable-interpolation/fixtures/collection └── subproto.spec.ts
Files:
tests/utils/page/locators.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Playwright E2E Tests
- GitHub Check: Unit Tests
- GitHub Check: CLI Tests
- GitHub Check: SSL Tests - macOS
- GitHub Check: SSL Tests - Linux
- GitHub Check: SSL Tests - Windows
🔇 Additional comments (1)
tests/utils/page/locators.ts (1)
126-126: Document the offset and verify all call sites.The
+1offset changes this helper's behavior—getTableCell(row, 0)now returns the second cell instead of the first. While this may align with an EditableTable component refactor, the offset needs clear documentation (JSDoc or inline comment explaining why the leading column is skipped).Additionally, add type annotations to the
rowandindexparameters in this TypeScript file for consistency with type safety guidelines.Verify all call sites of
getTableCellacross the test suite handle the new offset correctly.
Description
Contribution Checklist:
Note: Keeping the PR small and focused helps make it easier to review and merge. If you have multiple changes you want to make, please consider submitting them as separate pull requests.
Publishing to New Package Managers
Please see here for more information.
Summary by CodeRabbit
New Features
Improvements
Tests
✏️ Tip: You can customize this high-level summary in your review settings.