Skip to content

fix: use path utilities for file references stored to version-controlled config#7895

Open
prateek-bruno wants to merge 10 commits intousebruno:mainfrom
prateek-bruno:bugfix/path-normalization
Open

fix: use path utilities for file references stored to version-controlled config#7895
prateek-bruno wants to merge 10 commits intousebruno:mainfrom
prateek-bruno:bugfix/path-normalization

Conversation

@prateek-bruno
Copy link
Copy Markdown
Collaborator

@prateek-bruno prateek-bruno commented Apr 30, 2026

Description

Jira

Fixes #7858

Replace ad-hoc path.relative() and startsWith-based containment in file picker flows with centralized utilities that handle cross-platform paths.

  • Add getRelativePathWithinBasePath with path.relative-based containment
    guard and optional posixify support
  • OAuth1 / ClientCertSettings → getRelativePath (posixified, safe for
    git-collaborated .bru/bruno.json)
  • FilePickerEditor / MultipartFormParams / ResponseExampleMultipartFormParams
    getRelativePathWithinBasePath (backwards-compat default) replacing
    fragile startsWith containment (false-positives on sibling dirs,
    case-sensitive on Windows)
  • Mixed-separator containment tests + e2e test for multipart file persistence

Contribution Checklist:

  • I've used AI significantly to create this pull request
  • The pull request only addresses one issue or adds one feature.
  • The pull request does not introduce any breaking changes
  • I have added screenshots or gifs to help explain the change if applicable.
  • I have read the contribution guidelines.
  • Create an issue and link to the pull request.

Summary by CodeRabbit

  • Refactor

    • Introduced a shared helper to derive stored/display file paths; collection settings, file picker, auth private-key selection, multipart form UI, and response preview now use it for consistent in-collection path handling.
  • Tests

    • Added unit tests (including Windows cases) for the new helper, an end-to-end test verifying multipart file path persistence across restarts, and test helpers to mock file selection and manage multipart entries.

… file

Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Replaces ad-hoc relative-path logic with a new exported helper getStoredFilePath(collectionPath, filePath); updates multiple components to use it; adds unit tests (including Windows), an Electron E2E test, and test helpers for multipart file handling.

Changes

Cohort / File(s) Summary
Path Utility & Tests
packages/bruno-app/src/utils/common/path.js, packages/bruno-app/src/utils/common/path.spec.js, packages/bruno-app/src/utils/common/path.windows.spec.js
Adds getStoredFilePath(collectionPath, filePath) to compute safe stored-relative paths; expands tests for canonicalization, containment, edge cases, and Windows behavior.
Component Refactorings
packages/bruno-app/src/components/CollectionSettings/ClientCertSettings/index.js, packages/bruno-app/src/components/FilePickerEditor/index.js, packages/bruno-app/src/components/RequestPane/Auth/OAuth1/index.js, packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js, packages/bruno-app/src/components/ResponseExample/.../ResponseExampleMultipartFormParams/index.js
Replaces local path.relative logic with getStoredFilePath(...); updates imports and removes now-unused relative-path code.
Test Infrastructure & E2E Tests
tests/collection/opencollection/multipart-file-path.spec.ts, tests/utils/page/actions.ts
Adds Electron/Playwright E2E test verifying multipart file paths are stored relative to collections and remain so across edits/restarts; adds helpers to mock file dialogs, set request body mode, and add/remove multipart file rows in tests.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as Renderer (Component)
    participant Dialog as Filesystem / Electron Dialog
    participant Utils as getStoredFilePath
    participant Store as Persistence (YAML)

    User->>UI: Click "Browse" for file
    UI->>Dialog: showOpenDialog()
    Dialog-->>UI: absolute filePath
    UI->>Utils: getStoredFilePath(collectionPath, filePath)
    Utils-->>UI: storedPath (relative or original)
    UI->>Store: save request YAML with storedPath
    Store-->>UI: saved
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

size/M

Suggested reviewers

  • helloanoop
  • lohit-bruno
  • naman-bruno
  • bijin-bruno

Poem

🗂️ A file was found, a path made neat,

checked and trimmed so things don't repeat.
Helpers sing and tests agree,
relative roots stay tidy and free. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR directly addresses issue #7858 by implementing a robust getStoredFilePath helper that properly normalizes and validates relative paths across platforms, preventing incorrect conversion to absolute paths.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the relative-path handling issue: new getStoredFilePath utility, refactored components to use it consistently, comprehensive test coverage, and end-to-end validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title accurately reflects the main change: introducing a centralized path utility function to standardize how file references are stored in version-controlled configuration, replacing inconsistent path handling across multiple components.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/collection/opencollection/multipart-file-path.spec.ts`:
- Around line 66-70: In expectRequestFileToContainRelativePayload, the negative
assertion only checks payloadPath using the native separator and can miss
absolute paths stored with the other separator; update the test to assert the
file does not contain payloadPath in either separator form by importing node's
path and checking both payloadPath and an alternate-separator variant (e.g.,
payloadPath.replace(path.sep, path.sep === '/' ? '\\' : '/')) or by normalizing
both file content and payloadPath to a consistent separator before asserting;
reference the function expectRequestFileToContainRelativePayload and the
variables requestFilePath, payloadPath, and relativePayloadPath when making the
change.

In `@tests/utils/page/actions.ts`:
- Around line 880-886: In addMultipartFileToLastRow, the assertion checks the
first row's file cell instead of the row we interacted with; update the test to
assert against the targeted lastRow by replacing
table.allRows().locator('.file-value-cell').first() with
lastRow.locator('.file-value-cell') (and keep the expect
toContainText(path.basename(filePath))) so the helper validates the uploaded
file in the correct row.
- Around line 867-874: The mockBrowseFiles helper currently overwrites
dialog.showOpenDialog permanently; change it so it saves the original
dialog.showOpenDialog inside the electron evaluate context, replaces it with the
stub that returns the provided filePaths, then restores the original handler
before the evaluate callback finishes (or after a single invocation). In other
words, inside mockBrowseFiles' call to electronApp.evaluate, capture const
original = dialog.showOpenDialog, set dialog.showOpenDialog = async () => ({
canceled: false, filePaths: selectedPaths }), and then reassign
dialog.showOpenDialog = original (or implement a one-time stub) so
mockBrowseFiles leaves dialog.showOpenDialog unchanged for subsequent tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 855c9613-bbd8-4e40-90ed-81aea013493c

📥 Commits

Reviewing files that changed from the base of the PR and between 8269d51 and cd41cf8.

📒 Files selected for processing (10)
  • packages/bruno-app/src/components/CollectionSettings/ClientCertSettings/index.js
  • packages/bruno-app/src/components/FilePickerEditor/index.js
  • packages/bruno-app/src/components/RequestPane/Auth/OAuth1/index.js
  • packages/bruno-app/src/components/RequestPane/MultipartFormParams/index.js
  • packages/bruno-app/src/components/ResponseExample/ResponseExampleRequestPane/ResponseExampleMultipartFormParams/index.js
  • packages/bruno-app/src/utils/common/path.js
  • packages/bruno-app/src/utils/common/path.spec.js
  • packages/bruno-app/src/utils/common/path.windows.spec.js
  • tests/collection/opencollection/multipart-file-path.spec.ts
  • tests/utils/page/actions.ts

Comment thread tests/collection/opencollection/multipart-file-path.spec.ts
Comment thread tests/utils/page/actions.ts
Comment thread tests/utils/page/actions.ts
prateek-bruno and others added 3 commits April 30, 2026 17:07
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/collection/opencollection/multipart-file-path.spec.ts (1)

131-133: ⚡ Quick win

Assert the remove step before re-adding the multipart file.

Right now the test can still pass even if removal silently fails, because only the post re-add state is asserted. Add a direct assertion after save on remove.

Suggested fix
     await removeFirstMultipartFile(page);
     await saveRequest(page);
+    await expect.poll(async () => fs.promises.readFile(requestFilePath, 'utf-8')).not.toContain(relativePayloadPath);

     await addMultipartFileToLastRow(page, electronApp, payloadPath);

As per coding guidelines: “Cover both the ‘happy path’ and the realistically problematic paths… tests should fail usefully.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/collection/opencollection/multipart-file-path.spec.ts` around lines 131
- 133, The test currently calls removeFirstMultipartFile(page) and then
saveRequest(page) but never asserts that the removal succeeded; add an immediate
assertion after saveRequest (or directly after removeFirstMultipartFile if save
persists state) that verifies the multipart file was actually removed—e.g.,
assert the absence of the removed file element or that the multipart file list
length decreased—by using the same page selectors/helpers used elsewhere in the
spec so the failure is detected before re-adding the file; reference
removeFirstMultipartFile and saveRequest to locate where to add this assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/collection/opencollection/multipart-file-path.spec.ts`:
- Line 15: Replace the hardcoded separator in the relativePayloadPath constant
with an OS-native join: import or require the path module and set
relativePayloadPath using path.join('files', 'payload.json') so tests run on
Windows and POSIX; update any dependent assertions that expect a string to use
the new constant.

---

Nitpick comments:
In `@tests/collection/opencollection/multipart-file-path.spec.ts`:
- Around line 131-133: The test currently calls removeFirstMultipartFile(page)
and then saveRequest(page) but never asserts that the removal succeeded; add an
immediate assertion after saveRequest (or directly after
removeFirstMultipartFile if save persists state) that verifies the multipart
file was actually removed—e.g., assert the absence of the removed file element
or that the multipart file list length decreased—by using the same page
selectors/helpers used elsewhere in the spec so the failure is detected before
re-adding the file; reference removeFirstMultipartFile and saveRequest to locate
where to add this assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2099949c-9bb1-422c-b37e-43bbe65c55a3

📥 Commits

Reviewing files that changed from the base of the PR and between 1d8aab1 and 4848656.

📒 Files selected for processing (1)
  • tests/collection/opencollection/multipart-file-path.spec.ts

Comment thread tests/collection/opencollection/multipart-file-path.spec.ts Outdated
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/collection/opencollection/multipart-file-path.spec.ts`:
- Around line 124-139: The relaunched Electron instance started via
launchElectronApp is never closed, leaking processes; after the final assertion
(expectRequestFileToContainRelativePayload) ensure you close the electronApp by
awaiting its close() (i.e., await electronApp.close()), or if you kept the
original instance in a separate variable, await close() on both—place the await
electronApp.close() call after expectRequestFileToContainRelativePayload to
guarantee the second app is shut down.
- Around line 131-135: Add an explicit assertion after calling
removeFirstMultipartFile(page) to verify the file was actually removed before
proceeding to re-add; update the test to check the UI/state (via existing
helpers or new assertion) that confirms the multipart item is absent (e.g.,
verify row count or that the removed filename is not present) after
removeFirstMultipartFile(page) and before addMultipartFileToLastRow(page,
electronApp, payloadPath), keeping the subsequent saveRequest(page) calls
unchanged and referencing removeFirstMultipartFile, addMultipartFileToLastRow
and saveRequest to locate where to insert the check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c4f21b94-4792-4126-8ac1-7ac538059c8a

📥 Commits

Reviewing files that changed from the base of the PR and between 4848656 and 5907558.

📒 Files selected for processing (1)
  • tests/collection/opencollection/multipart-file-path.spec.ts

Comment thread tests/collection/opencollection/multipart-file-path.spec.ts
Comment thread tests/collection/opencollection/multipart-file-path.spec.ts
prateek-bruno and others added 4 commits April 30, 2026 19:35
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
@prateek-bruno prateek-bruno force-pushed the bugfix/path-normalization branch from b1a37ba to 4506b42 Compare May 6, 2026 16:23
Co-authored-by: Prateek Sunal <prtksunal@gmail.com>
@prateek-bruno prateek-bruno changed the title fix: correctly check for relative path between the collection and file fix: use path utilities for file references stored to version-controlled config May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Relative paths break when opencollection.yml edited manually

1 participant