Skip to content

fix: tab type resolution for non request types#8097

Merged
bijin-bruno merged 3 commits into
usebruno:mainfrom
sid-bruno:fix/folder-setting-tab-state
May 26, 2026
Merged

fix: tab type resolution for non request types#8097
bijin-bruno merged 3 commits into
usebruno:mainfrom
sid-bruno:fix/folder-setting-tab-state

Conversation

@sid-bruno
Copy link
Copy Markdown
Collaborator

@sid-bruno sid-bruno commented May 25, 2026

Description

  • folder-settings tab type isn't deserialized properly because the request type takes over.

JIRA

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.

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

  • Bug Fixes

    • Folder settings now default to the Headers pane and correctly restore the last selected pane (auth, headers, docs, script, vars) when switching workspaces or restarting the app.
    • Restored folder-settings tabs preserve folder association even when resolved items aren’t request types.
  • Tests

    • Added end-to-end snapshot tests verifying folder settings persistence across workspace switches and app restarts.
    • Added test helpers and locators to support folder settings interactions.

Review Change Stack

@sid-bruno sid-bruno marked this pull request as ready for review May 25, 2026 16:44
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Walkthrough

This PR extends snapshot deserialization to special-case folder-settings (defaulting its request pane tab to headers), restricts type-adoption to request tabs, adds unit tests, test locators/helpers, and Playwright/Electron end-to-end tests that validate folder-settings pane persistence across workspace switches and app restarts.

Changes

Folder Settings Tab Persistence

Layer / File(s) Summary
Core snapshot logic for folder-settings
packages/bruno-app/src/utils/snapshot/index.js
getDefaultRequestPaneTabForType defaults folder-settings to headers. deserializeTab only uses a found collection item's type when that type is a request tab; otherwise it keeps the snapshot type.
Unit tests for deserializeTab
packages/bruno-app/src/utils/snapshot/index.spec.js
Adds tests verifying requestPaneTab defaults to 'headers' when missing, restores requestPaneTab from snapshotTab.request.tab when present, and retains type: 'folder-settings' when the resolved pathname points to a non-request item while deriving folderUid.
Test locators and helpers
tests/utils/page/locators.ts, tests/utils/page/actions.ts
Adds tabs.folderTab locator and openfolder / selectfolderPaneTab helpers and exports to support folder-settings E2E flows.
End-to-end snapshot tests
tests/snapshots/folder.spec.ts
Playwright/Electron tests that exercise folder settings pane tab selection, assert ui-state-snapshot.json contains folder-settings entries with permanent: true, and confirm restoration after app restart.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • usebruno/bruno#7794: Earlier changes to snapshot tab serialization/deserialization logic this PR builds upon.
  • usebruno/bruno#7994: Modifies the same deserializeTab logic for request-pane tab defaults and type resolution.
  • usebruno/bruno#7942: Related changes to snapshot restoration logic for tabs and singleton/global UI state.

Suggested reviewers

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

Poem

📁✨ Folders wake and fold their state anew,
Tabs remembered after shutdowns too,
Headers chosen when a folder finds no cue,
Tests and helpers guard the snapshot view —
A tiny restart, and the panes return true.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the core fix: correcting tab type resolution for non-request types, specifically addressing the folder-settings tab deserialization issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
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

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: 1

🧹 Nitpick comments (5)
packages/bruno-app/src/utils/snapshot/index.spec.js (1)

289-312: ⚡ Quick win

Add a regression test for non-request type preservation when pathname resolves to an item.

These tests cover request-pane defaults, but not the new Line 565 guard that preserves folder-settings type when the resolved item is non-request.

Suggested test addition
+  it('keeps folder-settings type when pathname resolves to a non-request item', () => {
+    const collectionWithFolderItem = {
+      ...collection,
+      items: [
+        {
+          uid: 'folder-1',
+          pathname: '/collections/a/folder',
+          type: 'folder'
+        }
+      ]
+    };
+
+    const snapshotTab = {
+      type: 'folder-settings',
+      accessor: 'pathname',
+      pathname: '/collections/a/folder',
+      permanent: true
+    };
+
+    const tab = deserializeTab(snapshotTab, collectionWithFolderItem);
+    expect(tab.type).toBe('folder-settings');
+    expect(tab.folderUid).toBe('folder-1');
+    expect(tab.requestPaneTab).toBe('headers');
+  });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/bruno-app/src/utils/snapshot/index.spec.js` around lines 289 - 312,
Add a regression test to ensure deserializeTab preserves a tab with type
'folder-settings' when the provided pathname resolves to a non-request item:
construct a snapshotTab with type 'folder-settings', accessor 'pathname', and a
pathname that matches a non-request item in the test collection, call
deserializeTab(snapshotTab, collection), and assert that the returned tab.type
is still 'folder-settings' (and that requestPaneTab is preserved or defaults as
appropriate). Target the deserializeTab behavior around the new guard (the logic
introduced near Line 565) so the test fails if the resolver incorrectly converts
folder-settings into a request tab.
tests/utils/page/actions.ts (2)

807-807: ⚡ Quick win

Rename to camelCase for consistency.

The function name selectfolderPaneTab should be selectFolderPaneTab to match the naming convention used by selectRequestPaneTab and selectResponsePaneTab.

♻️ Suggested rename
-const selectfolderPaneTab = async (page: Page, tabName: string) => {
+const selectFolderPaneTab = async (page: Page, tabName: string) => {

Don't forget to update the export and the test file import/usage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/utils/page/actions.ts` at line 807, Rename the function
selectfolderPaneTab to camelCase selectFolderPaneTab everywhere: update the
function declaration in tests/utils/page/actions.ts, adjust its export, and
update all imports/usages (e.g., where selectfolderPaneTab is imported or called
in tests) to use selectFolderPaneTab so it matches
selectRequestPaneTab/selectResponsePaneTab naming. Ensure any references in test
suites or index/export files are updated to the new identifier to avoid
unresolved symbol errors.

787-787: ⚡ Quick win

Rename to camelCase for consistency.

The function name openfolder should be openFolder to match the naming convention used by other helpers in this file (openRequest, openFolderRequest, createFolder, etc.).

♻️ Suggested rename
-const openfolder = async (page: Page, collectionName: string, folderName: string, { persist = false } = {}) => {
+const openFolder = async (page: Page, collectionName: string, folderName: string, { persist = false } = {}) => {

Don't forget to update the export and the test file import/usage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/utils/page/actions.ts` at line 787, Rename the helper function
identifier openfolder to camelCase openFolder wherever it is declared and
referenced (including its export and all imports/usages in tests) so it matches
the existing helpers like openRequest/openFolderRequest; update the function
declaration (openfolder), any export named openfolder, and all call sites in
tests and other modules to openFolder to avoid breaking imports.
tests/snapshots/folder.spec.ts (2)

49-49: ⚡ Quick win

Replace magic timeout with event-driven wait.

Per coding guidelines, avoid page.waitForTimeout() unless absolutely necessary. If this timeout is needed for snapshot persistence, consider using expect.poll() or another event-driven approach instead.

As per coding guidelines: "Try to reduce usage of page.waitForTimeout(); in code unless absolutely necessary and the locator cannot be found using existing expect() playwright calls. Replace magic timeouts with event-driven waits in E2E tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/snapshots/folder.spec.ts` at line 49, Replace the magic sleep call
await page.waitForTimeout(1000); with an event-driven wait: identify the element
or event you actually need to be stable (e.g., a snapshot container locator or
network response) and replace the call to page.waitForTimeout with a targeted
waiter such as await
expect(page.locator('SELECTOR_FOR_SNAPSHOT')).toBeVisible(), await
page.waitForSelector('SELECTOR_FOR_SNAPSHOT'), await expect.poll(() => /* check
snapshot saved state */).toEqual(true), or await page.waitForResponse(resp =>
resp.url().includes('snapshot') && resp.status() === 200); update the selector
or response predicate to match the snapshot persistence logic in
tests/snapshots/folder.spec.ts and remove the page.waitForTimeout usage.

88-88: ⚡ Quick win

Replace magic timeout with event-driven wait.

Same issue as in the first test: avoid page.waitForTimeout() unless absolutely necessary. Consider using expect.poll() or another event-driven approach to verify snapshot persistence.

As per coding guidelines: "Try to reduce usage of page.waitForTimeout(); in code unless absolutely necessary and the locator cannot be found using existing expect() playwright calls. Replace magic timeouts with event-driven waits in E2E tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/snapshots/folder.spec.ts` at line 88, Replace the magic sleep call
await page.waitForTimeout(2000); in tests/snapshots/folder.spec.ts with an
event-driven wait: use Playwright's expect/expect.poll or a specific wait method
(e.g., await expect(locator).toHaveText(...), await
expect(locator).toBeVisible(), await page.waitForResponse(...), or await
expect.poll(() => /* check snapshot persisted */).toBeTruthy()) that asserts the
snapshot persisted instead of sleeping; locate the test that contains await
page.waitForTimeout and update it to wait on the appropriate locator or response
that demonstrates snapshot persistence.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/snapshots/folder.spec.ts`:
- Line 96: Remove the debug console.log call in the test file: delete the
console.log({ tab }); statement found in tests/snapshots/folder.spec.ts (inside
the snapshot test where the variable tab is logged) so tests don't emit spurious
debug output before merging.

---

Nitpick comments:
In `@packages/bruno-app/src/utils/snapshot/index.spec.js`:
- Around line 289-312: Add a regression test to ensure deserializeTab preserves
a tab with type 'folder-settings' when the provided pathname resolves to a
non-request item: construct a snapshotTab with type 'folder-settings', accessor
'pathname', and a pathname that matches a non-request item in the test
collection, call deserializeTab(snapshotTab, collection), and assert that the
returned tab.type is still 'folder-settings' (and that requestPaneTab is
preserved or defaults as appropriate). Target the deserializeTab behavior around
the new guard (the logic introduced near Line 565) so the test fails if the
resolver incorrectly converts folder-settings into a request tab.

In `@tests/snapshots/folder.spec.ts`:
- Line 49: Replace the magic sleep call await page.waitForTimeout(1000); with an
event-driven wait: identify the element or event you actually need to be stable
(e.g., a snapshot container locator or network response) and replace the call to
page.waitForTimeout with a targeted waiter such as await
expect(page.locator('SELECTOR_FOR_SNAPSHOT')).toBeVisible(), await
page.waitForSelector('SELECTOR_FOR_SNAPSHOT'), await expect.poll(() => /* check
snapshot saved state */).toEqual(true), or await page.waitForResponse(resp =>
resp.url().includes('snapshot') && resp.status() === 200); update the selector
or response predicate to match the snapshot persistence logic in
tests/snapshots/folder.spec.ts and remove the page.waitForTimeout usage.
- Line 88: Replace the magic sleep call await page.waitForTimeout(2000); in
tests/snapshots/folder.spec.ts with an event-driven wait: use Playwright's
expect/expect.poll or a specific wait method (e.g., await
expect(locator).toHaveText(...), await expect(locator).toBeVisible(), await
page.waitForResponse(...), or await expect.poll(() => /* check snapshot
persisted */).toBeTruthy()) that asserts the snapshot persisted instead of
sleeping; locate the test that contains await page.waitForTimeout and update it
to wait on the appropriate locator or response that demonstrates snapshot
persistence.

In `@tests/utils/page/actions.ts`:
- Line 807: Rename the function selectfolderPaneTab to camelCase
selectFolderPaneTab everywhere: update the function declaration in
tests/utils/page/actions.ts, adjust its export, and update all imports/usages
(e.g., where selectfolderPaneTab is imported or called in tests) to use
selectFolderPaneTab so it matches selectRequestPaneTab/selectResponsePaneTab
naming. Ensure any references in test suites or index/export files are updated
to the new identifier to avoid unresolved symbol errors.
- Line 787: Rename the helper function identifier openfolder to camelCase
openFolder wherever it is declared and referenced (including its export and all
imports/usages in tests) so it matches the existing helpers like
openRequest/openFolderRequest; update the function declaration (openfolder), any
export named openfolder, and all call sites in tests and other modules to
openFolder to avoid breaking imports.
🪄 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: e7431aa0-593e-4a8e-a4ae-8cb3d2c303d5

📥 Commits

Reviewing files that changed from the base of the PR and between a3e3199 and 231e538.

📒 Files selected for processing (5)
  • packages/bruno-app/src/utils/snapshot/index.js
  • packages/bruno-app/src/utils/snapshot/index.spec.js
  • tests/snapshots/folder.spec.ts
  • tests/utils/page/actions.ts
  • tests/utils/page/locators.ts

Comment thread tests/snapshots/folder.spec.ts Outdated
@bijin-bruno bijin-bruno merged commit 809f951 into usebruno:main May 26, 2026
20 of 22 checks passed
lohit-bruno pushed a commit that referenced this pull request May 26, 2026
* fix: tab type resolution for non request types

* Remove console log from snapshot test

Removed console log statement from folder.spec.ts

* test(snapshot): deserializeTab test addition for the removed guard
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.

2 participants