Skip to content

open-collection testcases#8381

Open
aman-bruno wants to merge 4 commits into
usebruno:mainfrom
aman-bruno:testcase/3577AddAndOpenCollection
Open

open-collection testcases#8381
aman-bruno wants to merge 4 commits into
usebruno:mainfrom
aman-bruno:testcase/3577AddAndOpenCollection

Conversation

@aman-bruno

@aman-bruno aman-bruno commented Jun 26, 2026

Copy link
Copy Markdown

Description

Added testcase for open collection and refactored a file into one folder

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

  • Tests
    • Added Playwright coverage for removing a sidebar collection end-to-end, including the Remove menu item, confirmation modal (with optional “discard all and remove”), success toast, and verification the collection no longer appears.
    • Renamed and retagged the “open multiple collections” sanity scenario and expanded UI assertions and step structure.
  • Refactor
    • Improved collection-related test helpers and locator scoping to more reliably target the correct collection entries and modal/toast elements.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds a new collection removal Playwright spec, updates shared collection test helpers and locators, and expands the multiple-collection opening test assertions.

Changes

Collection test support updates

Layer / File(s) Summary
Shared collection locators
tests/utils/page/locators.ts
buildCommonLocators is restructured around an explicit return object, and collection-scoped selectors now use toCollectionSlug through collectionScope(name).
Collection removal helpers
tests/utils/page/collection.ts, tests/utils/page/index.ts
New collection test helpers build remove-modal locators, open a collection actions menu, trigger the remove item, and confirm removal with discard-aware button handling; the barrel file re-exports the module.
Remove collection spec
tests/collection/open/open-collection.spec.ts
A new Playwright spec creates a temporary collection, opens its actions menu, verifies the remove modal, confirms removal, and checks the success toast and sidebar state.
Open multiple collections spec
tests/collection/open/open-multiple-collections.spec.ts
The multiple-collection opening test is retitled, tagged, and split into steps with broader visibility and interaction assertions after launch.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

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

Poem

A sidebar hums, a modal gleams,
Two tests march on in careful streams.
Slugs align and buttons sing,
While removals and openings do their thing.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is clearly related to the main change: adding open-collection test cases.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch testcase/3577AddAndOpenCollection

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.

await removeModal.removeButton().click();
}

await removeModal.modal().waitFor({ state: 'hidden', timeout: 5000 });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need this timeout if not remove it

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Not really required. Added just for time when application might be slow. Removed.

Comment thread tests/utils/page/actions.ts Outdated
* secrets live on separate tabs, so a secret is routed to the Secrets tab and a
* plain variable to the Variables tab before the row is added.
* @param page - The page object
* @param page - The page object

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

add the space again

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

added

Comment thread tests/utils/page/actions.ts Outdated
await expect(locators.sidebar.folderRequest(parentName, requestName)).toBeVisible();
} else {
await expect(locators.sidebar.request(requestName)).toBeVisible();
await expect(locators.sidebar.scopedRequest(parentName, requestName)).toBeVisible();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please revert this line back to locators.sidebar.request(requestName).
Changing the post-create assertion to scopedRequest(parentName, requestName) breaks existing tests

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Reverted.
This was added to make the assertion more robust.
Incase we have multiple collection expanded and all collection have same request name then the "await expect(locators.sidebar.request(requestName)).toBeVisible();" will fail. Tried making it more robust.

* @param page - The page object
* @returns void
*/
const closeAllCollections = async (page) => {

@pooja-bruno pooja-bruno Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

revert back changes done in closeAllCollections. don't touch old actions do changes if necessary.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Reverted.
This change was made because I have added few locator in locator.ts and wanted to reuse it here also, to avoid any duplicate locators.I will not make any changes on current methods moving forward

Comment thread tests/utils/page/locators.ts Outdated
folder: (name: string) => page.locator('.collection-item-name').filter({ hasText: name }),
request: (name: string) => page.locator('.collection-item-name').filter({ hasText: name }),
folderRequest: (folderName: string, requestName: string) => {
const toCollectionSlug = (name: string) => name.replace(/\s+/g, '-').toLowerCase();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need this we are just using it one time right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Reverted.
This can be used in multiple places. for now just one usecase.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

added this inside cons collectionscope

Comment thread tests/utils/page/locators.ts Outdated
Comment on lines +78 to +87
removeCollection: {
modal: removeCollectionModal,
path: () => removeCollectionModal().locator('.collection-path'),
removeButton: () => removeCollectionModal().getByRole('button', { name: 'Remove', exact: true }),
cancelButton: () => removeCollectionModal().getByRole('button', { name: 'Cancel', exact: true }),
discardAllAndRemoveButton: () => page.getByRole('button', { name: 'Discard All and Remove' })
}
},
toast: {
collectionRemovedFromWorkspace: () => page.getByText('Collection removed from workspace')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These items (remove collections) should not be part of generic modal element locators or toast locators.
Can be moved to own page.

Comment thread tests/utils/page/locators.ts Outdated
// The sidebar tree wraps each collection in `#collection-<slug>`; scope queries
// to it to disambiguate items that share names across collections.
collectionScope,
scopedRequest: (collectionName: string, requestName: string) =>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

unused locator added?

Comment on lines +6 to +20
const openCollectionActionsMenu = async (page: Page, collectionName: string) => {
await test.step(`Open actions menu for collection "${collectionName}"`, async () => {
const locators = buildCommonLocators(page);
await locators.sidebar.collectionRow(collectionName).hover();
await locators.actions.collectionActions(collectionName).click();
});
};

const clickRemoveInCollectionMenu = async (page: Page) => {
const locators = buildCommonLocators(page);
await locators.dropdown.item('Remove').click();
await locators.modal.removeCollection.modal().waitFor({ state: 'visible', timeout: 5000 });
};

const confirmRemoveCollection = async (page: Page) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Above actions are generic enough to be moved to pages/<component>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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/collection/open/open-multiple-collections.spec.ts`:
- Around line 77-80: The open-multiple-collections test step only clicks
collection locators without proving either collection became active. Update the
test around the collection1Element and collection2Element clicks to add a
user-visible assertion after each click, such as verifying the selected sidebar
state or the active collection pane/header, so the test checks behavior not just
clickability. Keep the assertions in the same test.step and use multiple
assertions to confirm both opened collections are visibly active.
- Around line 34-43: The open-multiple-collections spec is using hardcoded
collection names that can collide with persisted sidebar state across runs.
Update the test setup in open-multiple-collections.spec.ts so the collection
names created in the collection1Config and collection2Config blocks are derived
from each test’s isolated temp directory or another per-test unique value, and
make the same change for the additional collection name usage referenced later
in the spec. Keep the identifiers stable within a single test but unique per
test to ensure the locators in this scenario bind to the correct collections.
- Around line 64-75: The open-multiple-collections test is missing a pre-open
visibility check for collection2Element, so leaked state can slip through
unnoticed. In open-multiple-collections.spec.ts, update the test step around the
open action to assert both collection1Element and collection2Element are not
visible before clicking the Open collection flow, using the existing
collection1Element and collection2Element locators. Keep the post-action
visibility assertions, but make sure the test proves the command surfaced both
collections from a clean state.

In `@tests/utils/page/collection.ts`:
- Around line 48-60: The Confirm Remove Collection helper is checking for
discard-first instead of triggering the initial remove action, so the
draft-confirmation flow is never reached. Update buildCollectionLocators usage
in Confirm Remove Collection to click removeButton() first, then detect and
handle discardAllAndRemoveButton() if it appears, using options.forceDiscard
only for that follow-up click before waiting on removeModal().hide.
🪄 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: d6e7517d-bc67-4773-9835-f2b292634407

📥 Commits

Reviewing files that changed from the base of the PR and between e38f9eb and dc99351.

📒 Files selected for processing (5)
  • tests/collection/open/open-collection.spec.ts
  • tests/collection/open/open-multiple-collections.spec.ts
  • tests/utils/page/collection.ts
  • tests/utils/page/index.ts
  • tests/utils/page/locators.ts
✅ Files skipped from review due to trivial changes (1)
  • tests/utils/page/index.ts

Comment on lines +34 to +43
const collection1Config = {
version: '1',
name: 'Test Collection 1',
type: 'collection'
};
// Create bruno.json for second collection
const collection2Config = {
version: '1',
name: 'Test Collection 2',
type: 'collection'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use per-test collection names here.

These fixed names make the text locators vulnerable to persisted/sidebar state from another test run, so this spec can bind to the wrong collection and pass for the wrong reason. Derive the names from the isolated temp dirs instead.

Minimal change
+      const collection1Name = path.basename(collection1Dir);
+      const collection2Name = path.basename(collection2Dir);
       const collection1Config = {
         version: '1',
-        name: 'Test Collection 1',
+        name: collection1Name,
         type: 'collection'
       };
       const collection2Config = {
         version: '1',
-        name: 'Test Collection 2',
+        name: collection2Name,
         type: 'collection'
       };
@@
-    const collection1Element = page.locator('`#sidebar-collection-name`').getByText('Test Collection 1');
-    const collection2Element = page.locator('`#sidebar-collection-name`').getByText('Test Collection 2');
+    const collection1Element = page.locator('`#sidebar-collection-name`').getByText(collection1Name);
+    const collection2Element = page.locator('`#sidebar-collection-name`').getByText(collection2Name);

As per coding guidelines, "E2E tests must be parallel-safe... Each test gets isolated temp paths and unique workspace/project names." As per path instructions, "Each test gets isolated temp paths and unique workspace/project names."

Also applies to: 61-62

🤖 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/collection/open/open-multiple-collections.spec.ts` around lines 34 -
43, The open-multiple-collections spec is using hardcoded collection names that
can collide with persisted sidebar state across runs. Update the test setup in
open-multiple-collections.spec.ts so the collection names created in the
collection1Config and collection2Config blocks are derived from each test’s
isolated temp directory or another per-test unique value, and make the same
change for the additional collection name usage referenced later in the spec.
Keep the identifiers stable within a single test but unique per test to ensure
the locators in this scenario bind to the correct collections.

Sources: Coding guidelines, Path instructions

Comment on lines +64 to +75
await test.step('Initiate the simultaneous opening command', async () => {
await expect(collection1Element).not.toBeVisible();

// Click on plus icon button and then "Open collection" in the dropdown
await page.getByTestId('collections-header-add-menu').click();
await page.locator('.tippy-box .dropdown-item').filter({ hasText: 'Open collection' }).click();
});

await test.step('Verify the launch status of both collections', async () => {
await expect(collection1Element).toBeVisible();
await expect(collection2Element).toBeVisible();
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Re-add the pre-open check for the second collection.

Right now leaked state for collection2Element goes unnoticed, and the later visibility assertion can still pass without proving the open action surfaced both collections.

As per coding guidelines, "Cover both the happy path and the realistically problematic paths." As per path instructions, "E2E tests must be parallel-safe. No shared user data directories... or global app state."

🤖 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/collection/open/open-multiple-collections.spec.ts` around lines 64 -
75, The open-multiple-collections test is missing a pre-open visibility check
for collection2Element, so leaked state can slip through unnoticed. In
open-multiple-collections.spec.ts, update the test step around the open action
to assert both collection1Element and collection2Element are not visible before
clicking the Open collection flow, using the existing collection1Element and
collection2Element locators. Keep the post-action visibility assertions, but
make sure the test proves the command surfaced both collections from a clean
state.

Sources: Coding guidelines, Path instructions

Comment on lines +77 to +80
await test.step('Check the functionality and accessibility of each opened collection', async () => {
await collection1Element.click();
await collection2Element.click();
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Assert a user-visible outcome after each click.

This step only proves the locators are clickable. It does not verify that either collection actually became active/opened. Please add an observable assertion after each click (for example, selected sidebar state or the active collection pane/header).

As per coding guidelines, "Tests must verify user-visible behaviour, not implementation details." As per path instructions, "Use multiple assertions."

🤖 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/collection/open/open-multiple-collections.spec.ts` around lines 77 -
80, The open-multiple-collections test step only clicks collection locators
without proving either collection became active. Update the test around the
collection1Element and collection2Element clicks to add a user-visible assertion
after each click, such as verifying the selected sidebar state or the active
collection pane/header, so the test checks behavior not just clickability. Keep
the assertions in the same test.step and use multiple assertions to confirm both
opened collections are visibly active.

Sources: Coding guidelines, Path instructions

Comment on lines +48 to +60
await test.step('Confirm Remove Collection', async () => {
const collectionLocators = buildCollectionLocators(page);
const hasDiscardButton = await collectionLocators.discardAllAndRemoveButton().isVisible().catch(() => false);

if (hasDiscardButton) {
await collectionLocators.discardAllAndRemoveButton().click(
options.forceDiscard ? { force: true } : undefined
);
} else {
await collectionLocators.removeButton().click();
}

await collectionLocators.removeModal().waitFor({ state: 'hidden', timeout: 5000 });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Click Remove before probing for the discard dialog.

Discard All and Remove is a follow-up confirmation, so checking for it before removeButton().click() means dirty collections still fall through the normal branch and never complete the discard step. This helper therefore does not actually handle the draft-confirmation flow it advertises.

Proposed fix
 export const confirmRemoveCollection = async (
   page: Page,
   options: { forceDiscard?: boolean } = {}
 ) => {
   await test.step('Confirm Remove Collection', async () => {
     const collectionLocators = buildCollectionLocators(page);
-    const hasDiscardButton = await collectionLocators.discardAllAndRemoveButton().isVisible().catch(() => false);
-
-    if (hasDiscardButton) {
-      await collectionLocators.discardAllAndRemoveButton().click(
-        options.forceDiscard ? { force: true } : undefined
-      );
-    } else {
-      await collectionLocators.removeButton().click();
-    }
+    await collectionLocators.removeButton().click();
+
+    const discardButton = collectionLocators.discardAllAndRemoveButton();
+    const needsDiscardConfirm = await discardButton
+      .waitFor({ state: 'visible', timeout: 1000 })
+      .then(() => true)
+      .catch(() => false);
+
+    if (needsDiscardConfirm) {
+      await discardButton.click(options.forceDiscard ? { force: true } : undefined);
+    }
 
     await collectionLocators.removeModal().waitFor({ state: 'hidden', timeout: 5000 });
   });
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await test.step('Confirm Remove Collection', async () => {
const collectionLocators = buildCollectionLocators(page);
const hasDiscardButton = await collectionLocators.discardAllAndRemoveButton().isVisible().catch(() => false);
if (hasDiscardButton) {
await collectionLocators.discardAllAndRemoveButton().click(
options.forceDiscard ? { force: true } : undefined
);
} else {
await collectionLocators.removeButton().click();
}
await collectionLocators.removeModal().waitFor({ state: 'hidden', timeout: 5000 });
await test.step('Confirm Remove Collection', async () => {
const collectionLocators = buildCollectionLocators(page);
await collectionLocators.removeButton().click();
const discardButton = collectionLocators.discardAllAndRemoveButton();
const needsDiscardConfirm = await discardButton
.waitFor({ state: 'visible', timeout: 1000 })
.then(() => true)
.catch(() => false);
if (needsDiscardConfirm) {
await discardButton.click(options.forceDiscard ? { force: true } : undefined);
}
await collectionLocators.removeModal().waitFor({ state: 'hidden', timeout: 5000 });
🤖 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/collection.ts` around lines 48 - 60, The Confirm Remove
Collection helper is checking for discard-first instead of triggering the
initial remove action, so the draft-confirmation flow is never reached. Update
buildCollectionLocators usage in Confirm Remove Collection to click
removeButton() first, then detect and handle discardAllAndRemoveButton() if it
appears, using options.forceDiscard only for that follow-up click before waiting
on removeModal().hide.

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.

3 participants