Skip to content

TIDY-432#520

Merged
thyaravind merged 5 commits intodevfrom
TIDY-432
Mar 14, 2026
Merged

TIDY-432#520
thyaravind merged 5 commits intodevfrom
TIDY-432

Conversation

@Sriya-Mukkawar
Copy link
Contributor

@Sriya-Mukkawar Sriya-Mukkawar commented Mar 10, 2026

Summary by Sourcery

Add end-to-end coverage for bulk editing across library entities and expose test-friendly hooks on bulk edit UI components.

New Features:

  • Introduce shared Playwright helpers to open library tabs, create sample nodes, collections, goals, and tasks, and interact with bulk selection UIs.

Enhancements:

  • Add data-testid and aria-label support to the generic Button component and mark the bulk edit bar and thumbnail context menu trigger with stable test identifiers for accessibility-aware e2e targeting.

Tests:

  • Replace placeholder bulk editor specs for goals, tasks, and nodes with concrete regression tests for selection, bulk actions, and selection state, and add a new regression suite for collection bulk editing including star, archive, delete, and filter verification.

Summary by cubic

Adds Playwright E2E coverage for the bulk editor across Collections, Goals, Tasks, and Nodes. Tests cover context-menu selection, Select all, bulk actions with success toasts, and clearing selection; adds stable test hooks, small accessibility tweaks, and allows local.nucleus.to in dev. Addresses TIDY-432.

  • New Features

    • Regression suites: Collections (Star, Archive, Delete with counts and filtered views), Goals (Star), Tasks (Mark as completed), Nodes (Star); verifies Select all and Clear selection.
    • Shared helpers to open Library tabs via LibraryTab, create sample data (including nodes via Capture), select the first two via context menu or drag, and target the bulk edit bar.
  • Refactors

    • Exposed data-testid="bulk-edit-bar" and data-testid="thumbnail-context-menu-trigger". Button now supports ariaLabel/testId; BulkEditBar sets aria-labels on icon-only actions; Capture save uses testId="capture-save-button" with ariaLabel="Save".
    • Allowed host local.nucleus.to in apps/nucleus dev server.

Written for commit c8b0b40. Summary will update on new commits.

Summary by CodeRabbit

  • Tests

    • Added extensive end-to-end Playwright suites for the bulk editor (Collections, Goals, Tasks, Nodes) covering multi-select, select-all, and bulk actions (star, archive, delete, mark complete) with success toasts and UI state checks; introduced reusable test helpers for creating items, navigating library tabs, selecting items, and locating the bulk edit bar.
  • Accessibility / UI

    • Added test IDs and aria-labels to bulk controls, thumbnail context-menu trigger, buttons, and save action for improved accessibility and testability.

@vercel
Copy link

vercel bot commented Mar 10, 2026

Deployment failed with the following error:

You don't have permission to create a Preview Deployment for this Vercel project: nucleus.

View Documentation: https://vercel.com/docs/accounts/team-members-and-roles

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Mar 10, 2026

Reviewer's Guide

Adds shared Playwright helpers and data setup utilities for bulk editing, wires new test IDs into Svelte components for reliable selection, and implements comprehensive bulk editor E2E regression suites for nodes, goals, tasks, and collections.

Sequence diagram for Playwright bulk editor tests using test IDs

sequenceDiagram
  actor Tester
  participant PlaywrightTest
  participant TestHelpers
  participant BrowserPage
  participant BulkEditBar
  participant Button

  Tester->>PlaywrightTest: run bulk editor regression suite
  PlaywrightTest->>TestHelpers: openBulkEditorForEntityType(entityType)
  TestHelpers->>BrowserPage: navigateToListView(entityType)
  BrowserPage-->>TestHelpers: list view loaded
  TestHelpers->>BrowserPage: selectMultipleRows()
  TestHelpers->>BrowserPage: getByTestId(bulk-edit-bar)
  BrowserPage-->>BulkEditBar: resolve element with data-testid=bulk-edit-bar
  TestHelpers->>BulkEditBar: click()

  PlaywrightTest->>TestHelpers: performBulkAction(action)
  TestHelpers->>BrowserPage: getByRole(button, name=actionLabel)
  BrowserPage-->>Button: match aria-label for icon-only action
  TestHelpers->>Button: click()
  Button-->>BrowserPage: apply bulk edit action
  BrowserPage-->>PlaywrightTest: UI updated
  PlaywrightTest-->>Tester: assertions passed
Loading

Class diagram for updated Svelte button and bulk edit components

classDiagram
  class Button {
    +boolean isUnderlined
    +string id
    +string testId
    +string ariaLabel
    +boolean isHovering
    +string shortcut
  }

  class BulkEditBar {
    +boolean isExpandedMode
    +string dataTestId_bulk_edit_bar
    +Button[] leftActionsButtons
    +Button[] rightActionsButtons
  }

  class ResourceThumbnailContextMenu {
    +string dataTestId_thumbnail_context_menu_trigger
  }

  BulkEditBar "1" o-- "many" Button : uses
  ResourceThumbnailContextMenu "1" o-- "1" Button : trigger_uses

  Button : +render(id)
  Button : +renderWithTestId(testId)
  Button : +renderWithAriaLabel(ariaLabel)

  BulkEditBar : +renderBulkEditBar()
  BulkEditBar : +renderActionButtons(isExpandedMode)

  ResourceThumbnailContextMenu : +renderTriggerButton()
Loading

File-Level Changes

Change Details Files
Introduce reusable Playwright helpers for Library navigation, data setup, and bulk-selection interactions used across bulk editor tests.
  • Add regex-based LibraryTab mapping for tab buttons with optional item counts.
  • Add openLibraryAndTab helper to open Library and switch tabs while asserting URL.
  • Add factory helpers to create two collections, goals, tasks, and nodes via command bar/Capture for test data setup.
  • Add dragSelectFirstTwoThumbnails to simulate drag-selection of thumbnails matching app behavior.
  • Add selectFirstTwoViaContextMenu to select items via each thumbnail’s 3-dot context menu and expose getBulkEditBar locator for scoped bulk bar interactions.
apps/e2e-playwright/tests/utils/helpers.ts
Replace skipped stub bulk editor specs for goals, tasks, and nodes with concrete regression tests that exercise selection, bulk actions, and bar visibility using shared helpers.
  • Import expect and shared helpers into bulk-editor.spec files for goals, tasks, and nodes.
  • Add tests asserting bulk edit bar appears and shows correct selection count after multi-select.
  • Add tests that Clear selection hides the bulk edit bar.
  • Add tests that Star/Mark as completed actions show success toasts and clear selection.
  • Add tests that Select all keeps bar visible and maintains/updates selection count.
apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts
apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts
apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts
Add a new bulk editor E2E suite for collections, including verification that star/archive/delete truly affect underlying data.
  • Create collection bulk-editor.spec with shared helper imports and env-based skip guard.
  • Add tests for multi-select bringing up the bulk edit bar and verifying Star/Archive/Delete buttons are present.
  • Add tests that Clear selection hides the bar and that Star/Archive show success toasts and clear selection.
  • Use URL query params to filter for starred/archived collections to assert state changes persist after navigation.
  • Add delete test that asserts thumbnails count decreases by two after bulk delete completes.
apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts
Expose test hooks and accessibility props in shared Svelte components to support the new E2E flows and icon-only buttons in the bulk edit bar.
  • Extend Button.svelte to accept optional testId and ariaLabel props, wiring them to data-testid and aria-label attributes on the button element.
  • Mark BulkEditBar container with data-testid for easier Playwright scoping and pass ariaLabel to icon-only action buttons when labels are hidden in compact mode.
  • Tag the resource thumbnail context menu trigger button with a test ID for reliable selection in tests.
client/elements/button/Button.svelte
client/components/record/BulkEditBar.svelte
client/components/record/thumbnail/ResourceThumbnailContextMenu.svelte

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@qodo-code-review
Copy link

Review Summary by Qodo

Comprehensive E2E tests for bulk editors with accessibility improvements

🧪 Tests ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add comprehensive E2E tests for bulk editor across collections, goals, tasks, and nodes
• Implement test helper functions for creating test data and selecting items
• Add accessibility attributes (aria-label, data-testid) to Button and UI components
• Replace placeholder tests with full functional test coverage
Diagram
flowchart LR
  A["Button Component"] -->|Add aria-label & testId| B["Accessibility Attributes"]
  C["BulkEditBar Component"] -->|Add data-testid| B
  D["ContextMenu Component"] -->|Add data-testid| B
  E["Test Helpers"] -->|Create test data & selection| F["E2E Test Suites"]
  G["Collection Tests"] -->|Implement full coverage| F
  H["Goal Tests"] -->|Implement full coverage| F
  I["Task Tests"] -->|Implement full coverage| F
  J["Node Tests"] -->|Implement full coverage| F
Loading

Grey Divider

File Changes

1. client/elements/button/Button.svelte ✨ Enhancement +6/-0

Add accessibility and test ID attributes to Button

• Add testId export prop for E2E test identification
• Add ariaLabel export prop for accessible button naming
• Apply aria-label and data-testid attributes to button element
• Support icon-only buttons with accessible labels

client/elements/button/Button.svelte


2. client/components/record/BulkEditBar.svelte ✨ Enhancement +3/-0

Add test ID and aria-label to bulk edit bar

• Add data-testid="bulk-edit-bar" to main container for E2E test targeting
• Add ariaLabel prop to action buttons for icon-only accessibility
• Pass ariaLabel to Button components in both left and right action sections

client/components/record/BulkEditBar.svelte


3. client/components/record/thumbnail/ResourceThumbnailContextMenu.svelte ✨ Enhancement +1/-0

Add test ID to context menu trigger button

• Add data-testid="thumbnail-context-menu-trigger" to context menu button
• Enable E2E tests to reliably locate and interact with thumbnail context menus

client/components/record/thumbnail/ResourceThumbnailContextMenu.svelte


View more (5)
4. apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts 🧪 Tests +197/-0

Implement full collection bulk editor test suite

• Create comprehensive test suite for collection bulk editor functionality
• Test selection display, clearing selection, starring, archiving, and deletion
• Verify success toasts and UI state changes after bulk actions
• Validate that bulk operations persist (e.g., starred/archived collections appear in filtered
 views)

apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts


5. apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts 🧪 Tests +87/-4

Implement full goal bulk editor test suite

• Replace placeholder test with four comprehensive test cases
• Test bulk selection display, clearing selection, starring, and select-all functionality
• Verify success toasts and selection state management
• Import and use new test helper functions

apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts


6. apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts 🧪 Tests +87/-4

Implement full task bulk editor test suite

• Replace placeholder test with four comprehensive test cases
• Test bulk selection display, clearing selection, mark-as-completed, and select-all
• Verify success toasts and selection state management
• Import and use new test helper functions

apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts


7. apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts 🧪 Tests +87/-4

Implement full node bulk editor test suite

• Replace placeholder test with four comprehensive test cases
• Test bulk selection display, clearing selection, starring, and select-all functionality
• Verify success toasts and selection state management
• Import and use new test helper functions

apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts


8. apps/e2e-playwright/tests/utils/helpers.ts 🧪 Tests +193/-0

Add comprehensive bulk editor test helper functions

• Add LibraryTab constant with regex patterns for tab navigation
• Implement openLibraryAndTab() to navigate to library and switch tabs
• Add data creation helpers: createTwoCollections(), createTwoGoals(), createTwoTasks(),
 createTwoNodesViaCapture()
• Implement dragSelectFirstTwoThumbnails() for drag-based selection
• Implement selectFirstTwoViaContextMenu() for context menu-based selection
• Add getBulkEditBar() locator helper for targeting bulk edit bar in tests

apps/e2e-playwright/tests/utils/helpers.ts


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Mar 10, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Button.svelte adds comments📘 Rule violation ✓ Correctness
Description
New inline documentation comments were added to Button.svelte, violating the no-inline-comments
policy. This can cause compliance enforcement failures.
Code

client/elements/button/Button.svelte[R41-44]

+  /** Optional test id for e2e (e.g. data-testid) */
+  export let testId: string | undefined = undefined;
+  /** Accessible name when button is icon-only (e.g. for screen readers and e2e) */
+  export let ariaLabel: string | undefined = undefined;
Evidence
PR Compliance ID 7 prohibits inline comments in code changes. The PR adds new /** ... */ comments
immediately above newly introduced props.

AGENTS.md
client/elements/button/Button.svelte[41-44]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Button.svelte` introduces new inline documentation comments, which are disallowed in modified/new code.
## Issue Context
Repository policy requires code changes to be comment-free.
## Fix Focus Areas
- client/elements/button/Button.svelte[41-44]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Non-ASCII in test names📘 Rule violation ✓ Correctness
Description
New test titles introduce non-ASCII characters (e.g., , ), violating the ASCII-only edits
policy for files that previously contained only ASCII. This can cause tooling/encoding diffs and
inconsistent text conventions.
Code

apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[20]

+test.describe("collection – bulk editor @regression", () => {
Evidence
PR Compliance ID 9 requires ASCII-only edits unless the file already contained extended characters;
this newly added file includes extended characters in strings. The added test suite name contains an
en-dash and multiple test titles use the right-arrow character.

AGENTS.md
apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[20-20]
apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[29-29]
apps/e2e-playwright/tests/utils/helpers.ts[288-290]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Non-ASCII characters (such as `–` and `→`) were introduced in new/modified test content.
## Issue Context
Compliance requires ASCII-only edits unless the file already contains extended characters; newly added files should remain ASCII-only.
## Fix Focus Areas
- apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[20-20]
- apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[29-29]
- apps/e2e-playwright/tests/utils/helpers.ts[288-290]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Brittle filtered count asserts🐞 Bug ⛯ Reliability
Description
Collection bulk-editor tests assert the starred/archived filtered views contain exactly 2 items,
which will fail when the test user already has other starred/archived collections. This is
especially likely when Playwright runs with a saved auth storageState against persistent user data.
Code

apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[R95-103]

+    // Verify collections are actually starred: enable starred filter via URL (toggle has no accessible name)
+    const url = new URL(page.url());
+    url.searchParams.set("starred", "1");
+    await page.goto(url.toString(), { waitUntil: "domcontentloaded" });
+    await page.waitForTimeout(1_500);
+    const thumbnails = page.locator("#records-container div[id^='thumbnail-']");
+    await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
+    await expect(thumbnails).toHaveCount(2, { timeout: 5_000 });
+
Evidence
The tests explicitly set filter query params and then assert an absolute count of 2, but the
Playwright project configuration can load a persistent storageState (auth) which implies prior user
data may exist and match those filters, increasing the count and failing the assertion.

apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[95-103]
apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[155-163]
apps/e2e-playwright/playwright.config.ts[48-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The collection bulk-editor E2E tests assume the starred/archived filtered views contain exactly 2 items after starring/archiving the two newly created collections. When tests run with saved auth state (persistent user data), those filtered views can contain additional previously starred/archived collections, causing `toHaveCount(2)` to fail.
### Issue Context
Playwright projects can load `storageState` from `.auth/*`, meaning the same user account (and its data) can be reused across runs.
### Fix Focus Areas
- apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[95-108]
- apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[155-163]
- apps/e2e-playwright/playwright.config.ts[48-60]
### Suggested fix approach
- Before applying the bulk action, navigate to the filter view and record `countBefore` (or return baseline by querying the filtered list).
- After the action, navigate to the same filter view and assert the count is `countBefore + 2`.
- Optionally, additionally assert that the two created collections are present by matching their generated names (store the names when creating them).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Fixed sleeps in E2E🐞 Bug ⛯ Reliability
Description
The new E2E helpers/tests use hard-coded waitForTimeout(1_500) delays instead of waiting for
specific UI conditions, making test behavior timing-dependent. On slower environments, this can
cause element lookups and count assertions to run before the UI updates, producing flaky failures.
Code

apps/e2e-playwright/tests/utils/helpers.ts[R154-160]

+  await page.getByRole("button", { name: /^Library$/i }).click({ timeout: 5_000 });
+  await page.waitForURL(
+    (u) => /^\/library(\/.*)?$/.test(new URL(u).pathname),
+    { timeout: 10_000 }
+  );
+  await page.getByRole("button", { name: tabName }).first().click({ timeout: 5_000 });
+  await page.waitForTimeout(1_500);
Evidence
openLibraryAndTab always sleeps for 1.5s after clicking a tab and returns without confirming the
tab contents are ready; the collection tests also sleep for 1.5s after navigation before asserting
counts. These fixed delays can be insufficient (or wasteful) depending on runtime performance.

apps/e2e-playwright/tests/utils/helpers.ts[150-161]
apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[98-103]
apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[192-195]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
E2E helpers/tests rely on fixed `waitForTimeout(1_500)` delays for tab switching, filtering, and post-action updates. This makes tests timing-dependent and can cause flaky failures when the UI updates slower than the hard-coded delay.
### Issue Context
These tests already use Playwright expect-based waits elsewhere; replacing sleeps with condition-based waits improves determinism and typically reduces overall runtime.
### Fix Focus Areas
- apps/e2e-playwright/tests/utils/helpers.ts[154-161]
- apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[98-103]
- apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[158-163]
- apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts[192-195]
### Suggested fix approach
- In `openLibraryAndTab`, wait for the relevant container for that tab (e.g. `#records-container` / `#task-library`) and/or the first `div[id^='thumbnail-']` to be visible instead of sleeping.
- After `page.goto()` with filters, wait for a stable condition (e.g., `await expect(thumbnails.first()).toBeVisible()` is already there—remove the sleep and rely on that).
- After delete/archive/star, wait for the toast and then poll the thumbnail count (or specific item presence) rather than sleeping.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 10, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 25a925b8-12ca-499b-9981-8e8cb6a8a940

📥 Commits

Reviewing files that changed from the base of the PR and between 8b2a8ce and c8b0b40.

📒 Files selected for processing (1)
  • client/elements/button/Button.svelte

📝 Walkthrough

Walkthrough

Adds and enables Playwright E2E tests for bulk-editor flows (collections, goals, tasks, nodes), introduces reusable test helpers for library/selection interactions, and adds data-testid/aria-label hooks to UI buttons and context-menu elements for test targeting.

Changes

Cohort / File(s) Summary
Bulk Editor E2E Tests
apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts, apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts, apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts, apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts
Adds/activates Playwright suites validating multi-select (context-menu/drag), bulk actions (Star, Archive, Delete, Mark Complete), Clear selection, Select all, toasts, and filtered-view assertions.
Test Helpers & Utilities
apps/e2e-playwright/tests/utils/helpers.ts
Adds LibraryTab regex constants and exported helpers: openLibraryAndTab, createTwoCollections, createTwoGoals, createTwoTasks, createTwoNodesViaCapture, dragSelectFirstTwoThumbnails, selectFirstTwoViaContextMenu, and getBulkEditBar.
Button & Component Test Hooks
client/elements/button/Button.svelte, client/components/record/BulkEditBar.svelte, client/components/record/thumbnail/ResourceThumbnailContextMenu.svelte, client/products/memotron/capture/CaptureTopBar.svelte
Introduces ariaLabel prop on Button.svelte; adds data-testid="bulk-edit-bar", data-testid="thumbnail-context-menu-trigger", testId="capture-save-button", and uses aria-label where appropriate for test targeting/accessibility.
Dev Server Hosts
apps/nucleus/vite.config.ts
Adds local.nucleus.to to the Vite dev-server allowed hosts list.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • nucleum#518 — Overlapping changes to e2e Playwright tests, shared helpers, and UI test hooks (same test suites and selectors).
  • nucleum#519 — Related updates to test helpers and addition of aria/testId attributes on UI buttons used by E2E tests.

Suggested reviewers

  • thyaravind

Poem

🐇 I hopped through tests with nimble paws,
Clicking thumbnails, opening drawers,
Helpers placed each little chore,
Bulk bar gleams and toasts encore,
Hooray — the checks all pass once more!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The pull request title 'TIDY-432' is only a ticket identifier and does not clearly summarize the main change; it is vague and does not convey meaningful information about the changeset. Use a descriptive title like 'Add Playwright e2e tests for bulk editor across collections, goals, tasks, and nodes' or 'Add bulk editor e2e test coverage and UI test hooks' to clearly communicate the primary purpose of the changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch TIDY-432
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

CodeRabbit can use Trivy to scan for security misconfigurations and secrets in Infrastructure as Code files.

Add a .trivyignore file to your project to customize which findings Trivy reports.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • The test names that say "via drag" are using selectFirstTwoViaContextMenu under the hood; consider updating these descriptions or wiring in the dragSelectFirstTwoThumbnails helper so the behavior matches the name.
  • The createTwoCollections/Goals/Tasks/Nodes helpers share a lot of repetitive structure (command, wait for input, fill with Date.now(), confirm); consider extracting a small shared utility to reduce duplication and make future changes to this flow easier.
  • Instead of passing an arbitrary RegExp into openLibraryAndTab, you could narrow this to keyof typeof LibraryTab and resolve the regex inside the function, which would prevent callers from accidentally using a pattern that doesn't match a real tab.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The test names that say "via drag" are using `selectFirstTwoViaContextMenu` under the hood; consider updating these descriptions or wiring in the `dragSelectFirstTwoThumbnails` helper so the behavior matches the name.
- The `createTwoCollections/Goals/Tasks/Nodes` helpers share a lot of repetitive structure (command, wait for input, fill with `Date.now()`, confirm); consider extracting a small shared utility to reduce duplication and make future changes to this flow easier.
- Instead of passing an arbitrary `RegExp` into `openLibraryAndTab`, you could narrow this to `keyof typeof LibraryTab` and resolve the regex inside the function, which would prevent callers from accidentally using a pattern that doesn't match a real tab.

## Individual Comments

### Comment 1
<location path="apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts" line_range="29" />
<code_context>
   });

-  test.skip("bulk edit goals (select multiple, apply action)", async ({ page }) => {
+  test("select multiple goals via drag → bulk edit bar appears and shows count", async ({
+    page
+  }) => {
</code_context>
<issue_to_address>
**issue (testing):** Test name mentions drag selection but uses context-menu selection, which is misleading

The implementation uses `selectFirstTwoViaContextMenu`, so this test doesn’t actually exercise drag selection despite the name. The same mismatch appears in the analogous task/node/collection specs. Please either update these tests to use `dragSelectFirstTwoThumbnails` so they truly cover drag, or rename them to reflect context-menu selection and add separate tests for the drag flow.
</issue_to_address>

### Comment 2
<location path="apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts" line_range="57" />
<code_context>
+      page.getByText(/Selected: 2 collections?/i)
+    ).toBeVisible({ timeout: 10_000 });
+
+    await getBulkEditBar(page)
+      .getByRole("button", { name: /Clear selection/i })
+      .click({ timeout: 5_000 });
</code_context>
<issue_to_address>
**issue (testing):** Select-all test asserts a fixed count of 2 after selecting all, which may not reflect the real behaviour

In the `"select multiple nodes → Select all updates count to all items"` test, the final assertion still hardcodes `"Selected: 2 nodes"` after clicking "Select all". If there are more than two nodes, this no longer proves that "Select all" updated the count. Please assert on a dynamic value instead (e.g. a regex like `Selected: \d+ nodes?` and verify the count increased, or compute the expected total from the DOM and assert that exact value).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

});

test.skip("bulk edit goals (select multiple, apply action)", async ({ page }) => {
test("select multiple goals via drag → bulk edit bar appears and shows count", async ({
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (testing): Test name mentions drag selection but uses context-menu selection, which is misleading

The implementation uses selectFirstTwoViaContextMenu, so this test doesn’t actually exercise drag selection despite the name. The same mismatch appears in the analogous task/node/collection specs. Please either update these tests to use dragSelectFirstTwoThumbnails so they truly cover drag, or rename them to reflect context-menu selection and add separate tests for the drag flow.

page.getByText(/Selected: 2 nodes?/i)
).toBeVisible({ timeout: 10_000 });

await getBulkEditBar(page)
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (testing): Select-all test asserts a fixed count of 2 after selecting all, which may not reflect the real behaviour

In the "select multiple nodes → Select all updates count to all items" test, the final assertion still hardcodes "Selected: 2 nodes" after clicking "Select all". If there are more than two nodes, this no longer proves that "Select all" updated the count. Please assert on a dynamic value instead (e.g. a regex like Selected: \d+ nodes? and verify the count increased, or compute the expected total from the DOM and assert that exact value).

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

7 issues found across 8 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts">

<violation number="1" location="apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts:40">
P2: This test claims to verify that "Select all updates count to all items," but since exactly 2 nodes are created and both are already selected before clicking "Select all," the assertion `Selected: 2 nodes` is identical before and after the click. The test doesn't actually prove "Select all" changed anything. Assert a dynamic total (e.g., count all thumbnails in the container) or create more than 2 nodes so the count visibly changes after "Select all."</violation>

<violation number="2" location="apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts:102">
P2: The starred/archived checks use global `toHaveCount(2)` assertions, which makes the test brittle when the account already contains matching collections. Verify the two newly created collections specifically (or assert a count delta) instead of absolute totals.</violation>
</file>

<file name="apps/e2e-playwright/tests/utils/helpers.ts">

<violation number="1" location="apps/e2e-playwright/tests/utils/helpers.ts:256">
P2: Scope thumbnail lookup to the provided container; the current global locator can target the wrong thumbnails when multiple lists exist.</violation>
</file>

<file name="apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts">

<violation number="1" location="apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts:40">
P2: The Select all test does not validate Select all behavior: it checks `Selected: 2` both before and after clicking, so regressions in the button logic can slip through.</violation>
</file>

<file name="apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts">

<violation number="1" location="apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts:37">
P2: This test title says it verifies drag selection, but the implementation uses context-menu selection. That leaves drag behavior untested while reporting it as covered.</violation>

<violation number="2" location="apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts:105">
P2: After `Select all`, asserting exactly `Selected: 2 tasks` is brittle. Verify that a selection count is shown (or that count increases) instead of hard-coding 2.</violation>
</file>

<file name="apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts">

<violation number="1" location="apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts:29">
P2: Test name says "via drag" but the implementation uses `selectFirstTwoViaContextMenu`, so drag selection is never actually exercised. Either rename the test to reflect context-menu selection or switch to `dragSelectFirstTwoThumbnails`. The same mismatch exists in the analogous collection, task, and node specs.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
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: 5

🧹 Nitpick comments (1)
apps/e2e-playwright/tests/utils/helpers.ts (1)

146-161: Consider replacing hardcoded delay with a condition-based wait.

The waitForTimeout(1_500) on line 160 is a hardcoded delay that can lead to flaky tests or unnecessarily slow execution. Consider waiting for a specific condition instead, such as the tab content becoming visible or a loading indicator disappearing.

Example improvement
   await page.getByRole("button", { name: tabName }).first().click({ timeout: 5_000 });
-  await page.waitForTimeout(1_500);
+  // Wait for tab content to stabilize (e.g., first thumbnail or empty state)
+  await page.locator('div[id^="thumbnail-"], [data-testid="empty-state"]')
+    .first()
+    .waitFor({ state: "visible", timeout: 10_000 })
+    .catch(() => null);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e-playwright/tests/utils/helpers.ts` around lines 146 - 161, The
hardcoded wait in openLibraryAndTab (the final await page.waitForTimeout(1_500))
should be replaced with a condition-based wait: after clicking the tab button
(the page.getByRole(...).first().click call), wait for the tab’s content or a
loading indicator to reach the expected state (e.g., use a locator for the tab
panel or a known element/text in that tab and call .waitFor({ state: "visible"
}) or waitForSelector that it no longer exists). Use the tabName parameter to
derive a stable locator (for example look up a heading,
role="region"/role="tabpanel", or a specific element unique to that tab) and
wait on that locator instead of an arbitrary timeout so tests are deterministic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts`:
- Around line 155-163: Remove the inline comment "// Verify collections are
actually archived: enable archived filter via URL (toggle has no accessible
name)" from the test block; keep the code that constructs URL, sets
searchParams, navigates (url, url.searchParams.set, page.goto,
page.waitForTimeout) and assertions (thumbnails locator and expect calls)
unchanged, and if you need to preserve context, move that explanation into the
test name or a surrounding describe/comment block outside the modified lines.
- Around line 192-196: Remove the inline comment line that starts with "//
Verify the selected collections are removed: count after delete should be
countBefore - 2" in the test around the assertions using recordsContainer,
thumbnailsAfter, and countBefore; leave the await page.waitForTimeout(1_500);
and the expect(thumbnailsAfter).toHaveCount(...) assertion intact and ensure no
new inline comments are added in that block.
- Around line 95-108: Remove the inline explanatory comments in the test block
that begin "// Verify collections are actually starred: enable starred filter
via URL (toggle has no accessible name)" and "// Verify star icon appears on
each of the selected (now starred) collections"; the test code using URL,
url.searchParams, page.goto, thumbnails (locator "#records-container
div[id^='thumbnail-']"), and starIconsInStarredView already expresses the
intent, so delete those two comment lines and leave the code using url,
page.goto(...), thumbnails, and starIconsInStarredView unchanged.
- Around line 39-48: Remove the inline explanatory comments in the test block so
the assertions remain self-documenting: delete the comment lines preceding the
Selected text assertion and the block describing the bar (the lines that start
with "// Only collections are selected; bar shows count" and "// Bar (box in top
nav) has Star, Archive, Delete options") and keep the existing expectations
using page.getByText(/Selected: 2 collections?/i), getBulkEditBar(page), and
bar.getByRole(...) unchanged; this will satisfy the guideline against adding
inline comments while preserving test behavior.

In `@client/elements/button/Button.svelte`:
- Around line 41-44: Remove the inline documentation comments above the exported
props to satisfy coding guidelines: delete the comment lines preceding export
let testId and export let ariaLabel so only the prop declarations remain; ensure
no other inline comments are added around the testId or ariaLabel declarations
and keep their types/initializers unchanged in Button.svelte.

---

Nitpick comments:
In `@apps/e2e-playwright/tests/utils/helpers.ts`:
- Around line 146-161: The hardcoded wait in openLibraryAndTab (the final await
page.waitForTimeout(1_500)) should be replaced with a condition-based wait:
after clicking the tab button (the page.getByRole(...).first().click call), wait
for the tab’s content or a loading indicator to reach the expected state (e.g.,
use a locator for the tab panel or a known element/text in that tab and call
.waitFor({ state: "visible" }) or waitForSelector that it no longer exists). Use
the tabName parameter to derive a stable locator (for example look up a heading,
role="region"/role="tabpanel", or a specific element unique to that tab) and
wait on that locator instead of an arbitrary timeout so tests are deterministic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 16d4fa26-5476-422b-9945-8e570fb4206a

📥 Commits

Reviewing files that changed from the base of the PR and between 583058a and 3320b48.

📒 Files selected for processing (8)
  • apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/utils/helpers.ts
  • client/components/record/BulkEditBar.svelte
  • client/components/record/thumbnail/ResourceThumbnailContextMenu.svelte
  • client/elements/button/Button.svelte

@qodo-code-review
Copy link

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: playwright

Failed stage: Run smoke tests [❌]

Failed test name: [nucleus] › tests/shared/navigation.spec.ts:14:7 › shared - auth and nav @regression › already logged in (Google auth state): handle old page if present, then verify in app @smoke

Failure summary:

The GitHub Action failed because the Playwright smoke test run (playwright test --project=nucleus
--grep @smoke) exited with code 1 after test failures.

Failures:
- Test [nucleus] › tests/shared/navigation.spec.ts:14:7 › shared - auth and nav
@regression › already logged in (Google auth state): handle old page if present, then verify in app
@smoke failed at apps/e2e-playwright/tests/shared/navigation.spec.ts:157:5 because an
expect.poll(...) condition never became true and timed out after 20000ms (Expected: true, Received:
false). This failure persisted on retry.
- Test [nucleus] › tests/smoke/home.spec.ts:8:7 › smoke
@smoke › home page loads without errors failed at apps/e2e-playwright/tests/smoke/home.spec.ts:19:20
because the page emitted a console error; the test expected errors length 0 but received 1 with
message process is not defined.

Note: The [vite-plugin-svelte] unused export and A11y warnings appear in the logs but are not the
direct cause of the CI failure; the run failed due to the Playwright test failures above.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

1555:  9:49:40 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/pointron/analytics/cards/metrics/MetricsCard.svelte:4:11 MetricsCard has unused export property 'goalColors'. If it is for external reference only, please consider using `export const goalColors`
1556:  9:49:40 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/components/nestedList/NestedListItem.svelte:20:11 NestedListItem has unused export property 'style'. If it is for external reference only, please consider using `export const style`
1557:  9:49:40 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/node/content/web/GistPreview.svelte:3:11 GistPreview has unused export property 'accessPoint'. If it is for external reference only, please consider using `export const accessPoint`
1558:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/node/content/web/social/SocialPostContent.svelte:19:11 SocialPostContent has unused export property 'accessPoint'. If it is for external reference only, please consider using `export const accessPoint`
1559:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/node/content/web/social/SocialProfileContent.svelte:189:6 A11y: visible, non-interactive elements with an on:click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as <button type="button"> or <a> might be more appropriate. See https://svelte.dev/docs/accessibility-warnings#a11y-click-events-have-key-events for more details.
1560:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/node/content/web/social/SocialProfileContent.svelte:189:6 A11y: <div> with click handler must have an ARIA role
1561:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/components/CaptureComponent.svelte:110:6 A11y: <div> with click handler must have an ARIA role
1562:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/components/CaptureComponent.svelte:136:2 A11y: <div> with click handler must have an ARIA role
1563:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/pdfAnnotator/TextHiglighter.svelte:31:2 A11y: <div> with click, keydown, mousedown handlers must have an ARIA role
1564:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/pdfAnnotator/toolbar/InlineToolBar.svelte:17:0 A11y: <div> with mousedown handler must have an ARIA role
1565:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/pdfAnnotator/toolbar/InlineToolBar.svelte:8:11 InlineToolBar has unused export property 'selectedColor'. If it is for external reference only, please consider using `export const selectedColor`
1566:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/pdfAnnotator/comment/CommentEditor.svelte:17:0 A11y: <div> with click, mousedown handlers must have an ARIA role
1567:  9:49:41 AM [vite-plugin-svelte] /home/runner/work/nucleum/nucleum/client/products/memotron/node/content/web/social/SocialPostContentFallback.svelte:22:11 SocialPostContentFallback has unused export property 'accessPoint'. If it is for external reference only, please consider using `export const accessPoint`
1568:  ×F×±
1569:  1) [nucleus] › tests/shared/navigation.spec.ts:14:7 › shared - auth and nav @regression › already logged in (Google auth state): handle old page if present, then verify in app @smoke 
1570:  Error: �[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoBe�[2m(�[22m�[32mexpected�[39m�[2m) // Object.is equality�[22m
1571:  Expected: �[32mtrue�[39m
1572:  Received: �[31mfalse�[39m
1573:  Call Log:
1574:  - Timeout 20000ms exceeded while waiting on the predicate
1575:  155 |     const todayButton = page.getByRole("button", { name: "Today" }).first();
1576:  156 |     const allMarkers = [homeNav, ...navMarkers, todayButton];
1577:  > 157 |     await expect
1578:  |     ^
1579:  158 |       .poll(
1580:  159 |         async () => {
1581:  160 |           for (const marker of allMarkers) {
1582:  at /home/runner/work/nucleum/nucleum/apps/e2e-playwright/tests/shared/navigation.spec.ts:157:5
1583:  attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
1584:  test-results/shared-navigation-shared---c0086-nt-then-verify-in-app-smoke-nucleus/test-failed-1.png
1585:  ────────────────────────────────────────────────────────────────────────────────────────────────
1586:  attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
1587:  test-results/shared-navigation-shared---c0086-nt-then-verify-in-app-smoke-nucleus/video.webm
1588:  ────────────────────────────────────────────────────────────────────────────────────────────────
1589:  Retry #1 ───────────────────────────────────────────────────────────────────────────────────────
1590:  Error: �[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoBe�[2m(�[22m�[32mexpected�[39m�[2m) // Object.is equality�[22m
1591:  Expected: �[32mtrue�[39m
1592:  Received: �[31mfalse�[39m
1593:  Call Log:
1594:  - Timeout 20000ms exceeded while waiting on the predicate
1595:  155 |     const todayButton = page.getByRole("button", { name: "Today" }).first();
1596:  156 |     const allMarkers = [homeNav, ...navMarkers, todayButton];
1597:  > 157 |     await expect
1598:  |     ^
1599:  158 |       .poll(
1600:  159 |         async () => {
1601:  160 |           for (const marker of allMarkers) {
1602:  at /home/runner/work/nucleum/nucleum/apps/e2e-playwright/tests/shared/navigation.spec.ts:157:5
1603:  attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
1604:  test-results/shared-navigation-shared---c0086-nt-then-verify-in-app-smoke-nucleus-retry1/test-failed-1.png
1605:  ────────────────────────────────────────────────────────────────────────────────────────────────
1606:  attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
1607:  test-results/shared-navigation-shared---c0086-nt-then-verify-in-app-smoke-nucleus-retry1/video.webm
1608:  ────────────────────────────────────────────────────────────────────────────────────────────────
1609:  attachment #3: trace (application/zip) ─────────────────────────────────────────────────────────
1610:  test-results/shared-navigation-shared---c0086-nt-then-verify-in-app-smoke-nucleus-retry1/trace.zip
1611:  Usage:
1612:  npx playwright show-trace test-results/shared-navigation-shared---c0086-nt-then-verify-in-app-smoke-nucleus-retry1/trace.zip
1613:  ────────────────────────────────────────────────────────────────────────────────────────────────
1614:  2) [nucleus] › tests/smoke/home.spec.ts:8:7 › smoke @smoke › home page loads without errors ──────
1615:  Error: �[2mexpect(�[22m�[31mreceived�[39m�[2m).�[22mtoHaveLength�[2m(�[22m�[32mexpected�[39m�[2m)�[22m
1616:  Expected length: �[32m0�[39m
1617:  Received length: �[31m1�[39m
1618:  Received array:  �[31m["process is not defined"]�[39m
1619:  17 |     expect(response?.status()).toBeLessThan(400);
1620:  18 |     await expect(page).toHaveURL(/\//);
1621:  > 19 |     expect(errors).toHaveLength(0);
1622:  |                    ^
1623:  20 |   });
1624:  21 | });
1625:  22 |
1626:  at /home/runner/work/nucleum/nucleum/apps/e2e-playwright/tests/smoke/home.spec.ts:19:20
1627:  attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
1628:  test-results/smoke-home-smoke-smoke-home-page-loads-without-errors-nucleus/test-failed-1.png
1629:  ────────────────────────────────────────────────────────────────────────────────────────────────
1630:  attachment #2: video (video/webm) ──────────────────────────────────────────────────────────────
1631:  test-results/smoke-home-smoke-smoke-home-page-loads-without-errors-nucleus/video.webm
1632:  ────────────────────────────────────────────────────────────────────────────────────────────────
1633:  1 failed
1634:  [nucleus] › tests/shared/navigation.spec.ts:14:7 › shared - auth and nav @regression › already logged in (Google auth state): handle old page if present, then verify in app @smoke 
1635:  1 flaky
1636:  [nucleus] › tests/smoke/home.spec.ts:8:7 › smoke @smoke › home page loads without errors ───────
1637:  npm error Lifecycle script `test:smoke` failed with error:
1638:  npm error code 1
1639:  npm error path /home/runner/work/nucleum/nucleum/apps/e2e-playwright
1640:  npm error workspace e2e-playwright
1641:  npm error location /home/runner/work/nucleum/nucleum/apps/e2e-playwright
1642:  npm error command failed
1643:  npm error command sh -c playwright test --project=nucleus --grep @smoke
1644:  ##[error]Process completed with exit code 1.
1645:  ##[group]Run actions/upload-artifact@v4

@vercel
Copy link

vercel bot commented Mar 10, 2026

Deployment failed with the following error:

You don't have permission to create a Preview Deployment for this Vercel project: memotron.

View Documentation: https://vercel.com/docs/accounts/team-members-and-roles

@vercel
Copy link

vercel bot commented Mar 10, 2026

Deployment failed with the following error:

You don't have permission to create a Preview Deployment for this Vercel project: pointron.

View Documentation: https://vercel.com/docs/accounts/team-members-and-roles

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 8 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts">

<violation number="1" location="apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts:140">
P2: The post-"Select all" assertion is too permissive and can pass even when the button has no effect, so this test no longer validates the select-all behavior.</violation>
</file>

<file name="apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts">

<violation number="1" location="apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts:106">
P2: This assertion is too broad and can pass without confirming that "Select all" changed the selection count.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
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: 5

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

Inline comments:
In `@apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts`:
- Around line 102-107: The test's assertion using page.getByText(/Selected: \d+
goals?/i) is too permissive; update the post-click check to assert the exact
total selected count (e.g., use expect(page.getByText("Selected: X
goals")).toBeVisible() or toHaveText("Selected: X goals")) after calling
getBulkEditBar(page).getByRole("button", { name: /Select all/i }).click(...),
and adjust the test setup so the dataset yields a total X greater than the
initial 2 (ensure fixtures or seed data used by this spec produce that larger
total) so the assertion will fail if Select all does not increase the count.

In `@apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts`:
- Around line 102-107: The test currently only checks visibility after clicking
the "Select all" button; change it to assert the exact selected count by first
ensuring there are more than the seeded two tasks (seed an extra task or create
one in the test) or programmatically derive the current thumbnail/task count
(using the page locator used for task thumbnails) and then click
getBulkEditBar(page).getByRole("button", { name: /Select all/i }).click(...) and
assert that the bulk bar text equals "Selected: X tasks" (or "task" when X===1)
where X is the derived thumbnail count; reference getBulkEditBar and the page
locator you use to count thumbnails when implementing this assertion.

In `@apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts`:
- Around line 102-107: Before clicking "Select all" capture the number of
visible node thumbnails using a locator (e.g., page.locator(...) or an existing
thumbnail role/selector) and store its count; then click the Select all button
via getBulkEditBar(page).getByRole("button", { name: /Select all/i }).click(...)
and assert the bulk bar text exactly equals the captured count (e.g., "Selected:
X nodes" or singular as appropriate) instead of just asserting some count is
visible; use the same getBulkEditBar(page) helper to read the displayed count
and compare it to the pre-click thumbnail count.

In `@apps/e2e-playwright/tests/utils/helpers.ts`:
- Line 317: Remove the inline comment "// 3-dots trigger: inner button
(ContextMenuAction) opens the menu; outer has data-testid" and fold its content
into the existing block comment above or incorporate it into the helper's
name/JSdoc for the relevant helper that deals with the 3-dots trigger (the
helper referencing ContextMenuAction / data-testid in helpers.ts); ensure no new
inline // comments are added and update the helper's block comment or name to
convey the same information.
- Around line 277-287: The marquee start coordinates can fall inside a thumbnail
when a card is close to the container edge; update the startX/startY logic
(where startX/startY are computed from containerBox, minX, minY) to guarantee
they are strictly outside the thumbnails by checking after the initial clamp
and, if startX >= minX set startX = minX - 5 (and similarly if startY >= minY
set startY = minY - 5), ensuring the starting point is left/above the first card
so the helper performs marquee selection rather than starting a drag/click.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 80f34a30-d545-4783-b6eb-130cb64a5aab

📥 Commits

Reviewing files that changed from the base of the PR and between 3320b48 and 54f2ed5.

📒 Files selected for processing (8)
  • apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/utils/helpers.ts
  • apps/nucleus/vite.config.ts
  • client/elements/button/Button.svelte
  • client/products/memotron/capture/CaptureTopBar.svelte
🚧 Files skipped from review as they are similar to previous changes (2)
  • client/elements/button/Button.svelte
  • apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts

Comment on lines +102 to +107
await getBulkEditBar(page)
.getByRole("button", { name: /Select all/i })
.click({ timeout: 5_000 });
await expect(page.getByText(/Selected: \d+ goals?/i)).toBeVisible({
timeout: 5_000
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make the Select all check prove the count changed.

This matcher is too weak to validate the bulk action. page.getByText(/Selected: \d+ goals?/i) still passes if the selection stays at 2, so the regression suite would miss a broken Select all. Please assert the exact total item count after the click, and make sure the test data guarantees that total is greater than the initial 2.

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

In `@apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts` around lines
102 - 107, The test's assertion using page.getByText(/Selected: \d+ goals?/i) is
too permissive; update the post-click check to assert the exact total selected
count (e.g., use expect(page.getByText("Selected: X goals")).toBeVisible() or
toHaveText("Selected: X goals")) after calling
getBulkEditBar(page).getByRole("button", { name: /Select all/i }).click(...),
and adjust the test setup so the dataset yields a total X greater than the
initial 2 (ensure fixtures or seed data used by this spec produce that larger
total) so the assertion will fail if Select all does not increase the count.

Comment on lines +277 to +287
const minX = Math.min(box1.x, box2.x);
const minY = Math.min(box1.y, box2.y);
const maxRight = Math.max(box1.x + box1.width, box2.x + box2.width);
const maxBottom = Math.max(box1.y + box1.height, box2.y + box2.height);
const startX = Math.max(containerBox.x + 5, minX - 20);
const startY = Math.max(containerBox.y + 5, minY - 10);
const endX = maxRight + 20;
const endY = maxBottom + 15;
await page.mouse.move(startX, startY);
await page.mouse.down();
await page.mouse.move(endX, endY, { steps: 20 });
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Do not let marquee selection start on top of a thumbnail.

When the first card is close to the container edge, these startX / startY calculations can land inside the thumbnail instead of in empty space. In that case the helper stops exercising marquee selection and starts a card drag/click instead.

Suggested fix
-  const startX = Math.max(containerBox.x + 5, minX - 20);
-  const startY = Math.max(containerBox.y + 5, minY - 10);
+  const startX = minX - 20;
+  const startY = minY - 10;
+  if (startX < containerBox.x + 1 || startY < containerBox.y + 1) {
+    throw new Error(
+      `No empty gutter before the first thumbnails in #${containerId}; cannot start marquee selection outside a card`
+    );
+  }
   const endX = maxRight + 20;
   const endY = maxBottom + 15;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e-playwright/tests/utils/helpers.ts` around lines 277 - 287, The
marquee start coordinates can fall inside a thumbnail when a card is close to
the container edge; update the startX/startY logic (where startX/startY are
computed from containerBox, minX, minY) to guarantee they are strictly outside
the thumbnails by checking after the initial clamp and, if startX >= minX set
startX = minX - 5 (and similarly if startY >= minY set startY = minY - 5),
ensuring the starting point is left/above the first card so the helper performs
marquee selection rather than starting a drag/click.

@vercel vercel bot temporarily deployed to Preview – memotron March 11, 2026 06:56 Inactive
@vercel
Copy link

vercel bot commented Mar 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
memotron Ready Ready Preview, Comment Mar 14, 2026 1:50pm
nucleus Ready Ready Preview, Comment Mar 14, 2026 1:50pm
pointron Ready Ready Preview, Comment Mar 14, 2026 1:50pm

Copy link
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: 6

♻️ Duplicate comments (3)
apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts (1)

97-112: ⚠️ Potential issue | 🟡 Minor

Make Select all fail when it does nothing.

In a clean run this view can still contain only the two seeded nodes, which makes totalCount === 2 and turns this into a no-op assertion. Require totalCount > 2 or create another node first, then assert the exact bulk-bar count.

Suggested tightening
     const container = page.locator("#records-container");
     const thumbnails = container.locator('div[id^="thumbnail-"]');
     await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
     const totalCount = await thumbnails.count();
+    expect(totalCount).toBeGreaterThan(2);

     await selectFirstTwoViaContextMenu(page, "records-container");
     await expect(
       page.getByText(/Selected: 2 nodes?/i)
     ).toBeVisible({ timeout: 10_000 });

     await getBulkEditBar(page)
       .getByRole("button", { name: /Select all/i })
       .click({ timeout: 5_000 });
-    await expect(
-      page.getByText(new RegExp(`Selected: ${totalCount} nodes?`, "i"))
-    ).toBeVisible({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toContainText(`Selected: ${totalCount}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts` around
lines 97 - 112, The test's "Select all" assertion can be a no-op when totalCount
=== 2; modify the test around the thumbnails/totalCount logic so it guarantees
more than two nodes before asserting the bulk selection: either assert
totalCount > 2 and fail the test if not, or create an additional node (using the
same page helpers) after computing totalCount and before calling
selectFirstTwoViaContextMenu/getBulkEditBar so the subsequent
expect(page.getByText(new RegExp(`Selected: ${totalCount} nodes?`, "i"))) is
meaningful; update references to totalCount, thumbnails,
selectFirstTwoViaContextMenu, and getBulkEditBar accordingly.
apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts (1)

97-112: ⚠️ Potential issue | 🟡 Minor

Make Select all prove the selection actually grew.

This is still vacuous when the library only contains the two seeded tasks: totalCount stays 2, so the test passes even if Select all is a no-op. Fail fast unless there are more than two tasks, or seed an extra task before clicking, then assert against the bulk bar text directly.

Suggested tightening
     const container = page.locator("#task-library");
     const thumbnails = container.locator('div[id^="thumbnail-"]');
     await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
     const totalCount = await thumbnails.count();
+    expect(totalCount).toBeGreaterThan(2);

     await selectFirstTwoViaContextMenu(page, "task-library");
     await expect(
       page.getByText(/Selected: 2 tasks?/i)
     ).toBeVisible({ timeout: 10_000 });

     await getBulkEditBar(page)
       .getByRole("button", { name: /Select all/i })
       .click({ timeout: 5_000 });
-    await expect(
-      page.getByText(new RegExp(`Selected: ${totalCount} tasks?`, "i"))
-    ).toBeVisible({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toContainText(`Selected: ${totalCount}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts` around lines
97 - 112, The test checks that "Select all" increases the selection but can
falsely pass when the library only has the two seeded tasks; change the test so
it proves selection grew by either (a) asserting totalCount > 2 and failing fast
if not, or (b) seeding an extra task before calling selectFirstTwoViaContextMenu
and clicking the "Select all" button, then asserting the bulk bar text equals
`Selected: ${totalCount} task(s)`; update the block around totalCount,
selectFirstTwoViaContextMenu(page, "task-library"), and
getBulkEditBar(...).getByRole("button", { name: /Select all/i }) to implement
one of these approaches so the assertion verifies an actual increase in
selection.
apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts (1)

97-112: ⚠️ Potential issue | 🟡 Minor

Make Select all prove the selection actually increased.

If this tab only contains the two seeded goals, totalCount is still 2, so the test passes on a no-op. Require more than two goals in the view, or seed another one, and then verify the exact count on the bulk-edit bar.

Suggested tightening
     const container = page.locator("#records-container");
     const thumbnails = container.locator('div[id^="thumbnail-"]');
     await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
     const totalCount = await thumbnails.count();
+    expect(totalCount).toBeGreaterThan(2);

     await selectFirstTwoViaContextMenu(page, "records-container");
     await expect(
       page.getByText(/Selected: 2 goals?/i)
     ).toBeVisible({ timeout: 10_000 });

     await getBulkEditBar(page)
       .getByRole("button", { name: /Select all/i })
       .click({ timeout: 5_000 });
-    await expect(
-      page.getByText(new RegExp(`Selected: ${totalCount} goals?`, "i"))
-    ).toBeVisible({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toContainText(`Selected: ${totalCount}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts` around lines
97 - 112, The test currently can pass when there are only two goals because
totalCount may equal 2; make the test assert that the view contains more than
two items before using "Select all" and verify the bulk-edit bar shows the full
totalCount after clicking it: after computing totalCount from thumbnails
(variable totalCount and locator thumbnails) add an assertion like
expect(totalCount).toBeGreaterThan(2) (or seed one more item if needed), then
click Select all via getBulkEditBar().getByRole("button", { name: /Select all/i
}) and assert the bulk-edit text exactly matches `Selected: ${totalCount}
goals?` to ensure the selection actually increased (use the existing
selectFirstTwoViaContextMenu and getBulkEditBar locators to locate elements).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts`:
- Around line 65-67: The test currently only waits for the old "Selected: 2
collections" label to disappear; update the assertions so they verify the entire
bulk-edit bar is hidden by asserting getBulkEditBar(page) is hidden after each
Clear selection / Star / Archive / Delete action (use
expect(getBulkEditBar(page)).toBeHidden({ timeout: 5_000 }) or similar). Replace
or add to the existing expect(page.getByText(/Selected: 2
collections?/i)).toBeHidden(...) checks (also update the other occurrences
referenced) so the test fails if the bar remains visible with a different
label/state.
- Around line 203-205: The test captures countBefore too early because
Locator.count() doesn't wait; before calling count() wait for thumbnails to be
rendered by awaiting the first thumbnail (e.g., await
thumbnailsBefore.first().waitFor()) or use
page.waitForSelector("#records-container div[id^='thumbnail-']") or an
expect(toHaveCount) for a known minimum, then call countBefore = await
thumbnailsBefore.count(); update the code around recordsContainer /
thumbnailsBefore / countBefore to perform that wait before snapshotting the
baseline.
- Around line 131-146: The test wrongly allows "Select all" to pass when only
the two seeded collections exist; update the test in bulk-editor.spec.ts to
ensure more than two items are present before clicking the "Select all" button
by either creating an additional collection (use existing helper that seeds
collections or call the create function) or asserting totalCount > 2 after
computing const totalCount = await thumbnails.count(); then click
getBulkEditBar(...).getByRole("button", { name: /Select all/i }).click(...) and
assert the bulk-edit bar shows Selected: ${totalCount} collections? exactly;
reference the variables container, thumbnails, totalCount and the helper
selectFirstTwoViaContextMenu/getBulkEditBar to locate where to add the extra
seed or the additional assertion.

In `@apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts`:
- Around line 57-62: After clicking the "Clear selection" button and after the
"Star" action, assert that the bulk-edit bar element itself (obtained via
getBulkEditBar(page)) is hidden, not just that the "Selected: 2 goals" label
disappeared; update the assertions following the click calls to call something
like expect(getBulkEditBar(page)).toBeHidden({ timeout: 5000 }) so the test
verifies the entire bar is gone; do the same change for the second instance
around the Star action (the other assertion block at lines ~84-86) to ensure
getBulkEditBar(page) is hidden after that interaction as well.

In `@apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts`:
- Around line 57-62: After clicking the "Clear selection" button (and similarly
after "Mark as completed"), the test must assert that the entire bulk-edit bar
is hidden, not just that the "Selected: 2 tasks" text disappeared; update the
assertions to call getBulkEditBar(page) and expect(...).toBeHidden({ timeout:
5_000 }) immediately after the click for the Clear selection case and the Mark
as completed case (referencing getBulkEditBar(page) and the role button names
"Clear selection" and "Mark as completed" to locate the two places to change).

In `@apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts`:
- Around line 57-62: After clicking the "Clear selection" button, assert that
the bulk-edit bar element itself is hidden rather than only checking the text;
replace the text-based expectation with an assertion that getBulkEditBar(page)
is hidden (e.g., await expect(getBulkEditBar(page)).toBeHidden({ timeout: 5_000
})). Do the same for the "Star" action: after triggering the Star control where
the test currently checks for text changes (lines corresponding to the second
case), assert that getBulkEditBar(page) is hidden using getBulkEditBar(page) to
ensure the entire bar is gone.

---

Duplicate comments:
In `@apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts`:
- Around line 97-112: The test currently can pass when there are only two goals
because totalCount may equal 2; make the test assert that the view contains more
than two items before using "Select all" and verify the bulk-edit bar shows the
full totalCount after clicking it: after computing totalCount from thumbnails
(variable totalCount and locator thumbnails) add an assertion like
expect(totalCount).toBeGreaterThan(2) (or seed one more item if needed), then
click Select all via getBulkEditBar().getByRole("button", { name: /Select all/i
}) and assert the bulk-edit text exactly matches `Selected: ${totalCount}
goals?` to ensure the selection actually increased (use the existing
selectFirstTwoViaContextMenu and getBulkEditBar locators to locate elements).

In `@apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts`:
- Around line 97-112: The test checks that "Select all" increases the selection
but can falsely pass when the library only has the two seeded tasks; change the
test so it proves selection grew by either (a) asserting totalCount > 2 and
failing fast if not, or (b) seeding an extra task before calling
selectFirstTwoViaContextMenu and clicking the "Select all" button, then
asserting the bulk bar text equals `Selected: ${totalCount} task(s)`; update the
block around totalCount, selectFirstTwoViaContextMenu(page, "task-library"), and
getBulkEditBar(...).getByRole("button", { name: /Select all/i }) to implement
one of these approaches so the assertion verifies an actual increase in
selection.

In `@apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts`:
- Around line 97-112: The test's "Select all" assertion can be a no-op when
totalCount === 2; modify the test around the thumbnails/totalCount logic so it
guarantees more than two nodes before asserting the bulk selection: either
assert totalCount > 2 and fail the test if not, or create an additional node
(using the same page helpers) after computing totalCount and before calling
selectFirstTwoViaContextMenu/getBulkEditBar so the subsequent
expect(page.getByText(new RegExp(`Selected: ${totalCount} nodes?`, "i"))) is
meaningful; update references to totalCount, thumbnails,
selectFirstTwoViaContextMenu, and getBulkEditBar accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b4e1c679-d131-4895-b6b5-4ed1431c0baa

📥 Commits

Reviewing files that changed from the base of the PR and between 54f2ed5 and d2464e9.

📒 Files selected for processing (5)
  • apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts
  • apps/e2e-playwright/tests/utils/helpers.ts

Comment on lines +65 to +67
await expect(
page.getByText(/Selected: 2 collections?/i)
).toBeHidden({ timeout: 5_000 });
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

These tests should assert the bar disappears, not only the old label.

Each of these paths only waits for Selected: 2 collections to disappear. If the bulk-edit bar remains visible with another state, the tests still pass. Assert getBulkEditBar(page) is hidden after Clear selection, Star, Archive, and Delete.

Also applies to: 103-105, 182-184, 218-220

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

In `@apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts` around lines
65 - 67, The test currently only waits for the old "Selected: 2 collections"
label to disappear; update the assertions so they verify the entire bulk-edit
bar is hidden by asserting getBulkEditBar(page) is hidden after each Clear
selection / Star / Archive / Delete action (use
expect(getBulkEditBar(page)).toBeHidden({ timeout: 5_000 }) or similar). Replace
or add to the existing expect(page.getByText(/Selected: 2
collections?/i)).toBeHidden(...) checks (also update the other occurrences
referenced) so the test fails if the bar remains visible with a different
label/state.

Comment on lines +131 to +146
const container = page.locator("#records-container");
const thumbnails = container.locator('div[id^="thumbnail-"]');
await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
const totalCount = await thumbnails.count();

await selectFirstTwoViaContextMenu(page, "records-container");
await expect(
page.getByText(/Selected: 2 collections?/i)
).toBeVisible({ timeout: 10_000 });

await getBulkEditBar(page)
.getByRole("button", { name: /Select all/i })
.click({ timeout: 5_000 });
await expect(
page.getByText(new RegExp(`Selected: ${totalCount} collections?`, "i"))
).toBeVisible({ timeout: 5_000 });
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Select all is still vacuous when only two collections exist.

In a clean library totalCount can still equal the two seeded collections, so this passes even when Select all changes nothing. Require more than two collections in the view, or create one more before the click, then assert the exact count on the bulk-edit bar.

Suggested tightening
     const container = page.locator("#records-container");
     const thumbnails = container.locator('div[id^="thumbnail-"]');
     await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
     const totalCount = await thumbnails.count();
+    expect(totalCount).toBeGreaterThan(2);

     await selectFirstTwoViaContextMenu(page, "records-container");
     await expect(
       page.getByText(/Selected: 2 collections?/i)
     ).toBeVisible({ timeout: 10_000 });

     await getBulkEditBar(page)
       .getByRole("button", { name: /Select all/i })
       .click({ timeout: 5_000 });
-    await expect(
-      page.getByText(new RegExp(`Selected: ${totalCount} collections?`, "i"))
-    ).toBeVisible({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toContainText(`Selected: ${totalCount}`);
📝 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
const container = page.locator("#records-container");
const thumbnails = container.locator('div[id^="thumbnail-"]');
await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
const totalCount = await thumbnails.count();
await selectFirstTwoViaContextMenu(page, "records-container");
await expect(
page.getByText(/Selected: 2 collections?/i)
).toBeVisible({ timeout: 10_000 });
await getBulkEditBar(page)
.getByRole("button", { name: /Select all/i })
.click({ timeout: 5_000 });
await expect(
page.getByText(new RegExp(`Selected: ${totalCount} collections?`, "i"))
).toBeVisible({ timeout: 5_000 });
const container = page.locator("#records-container");
const thumbnails = container.locator('div[id^="thumbnail-"]');
await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
const totalCount = await thumbnails.count();
expect(totalCount).toBeGreaterThan(2);
await selectFirstTwoViaContextMenu(page, "records-container");
await expect(
page.getByText(/Selected: 2 collections?/i)
).toBeVisible({ timeout: 10_000 });
await getBulkEditBar(page)
.getByRole("button", { name: /Select all/i })
.click({ timeout: 5_000 });
await expect(getBulkEditBar(page)).toContainText(`Selected: ${totalCount}`);
🧰 Tools
🪛 ast-grep (0.41.0)

[warning] 144-144: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(Selected: ${totalCount} collections?, "i")
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

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

In `@apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts` around lines
131 - 146, The test wrongly allows "Select all" to pass when only the two seeded
collections exist; update the test in bulk-editor.spec.ts to ensure more than
two items are present before clicking the "Select all" button by either creating
an additional collection (use existing helper that seeds collections or call the
create function) or asserting totalCount > 2 after computing const totalCount =
await thumbnails.count(); then click getBulkEditBar(...).getByRole("button", {
name: /Select all/i }).click(...) and assert the bulk-edit bar shows Selected:
${totalCount} collections? exactly; reference the variables container,
thumbnails, totalCount and the helper
selectFirstTwoViaContextMenu/getBulkEditBar to locate where to add the extra
seed or the additional assertion.

Comment on lines +57 to +62
await getBulkEditBar(page)
.getByRole("button", { name: /Clear selection/i })
.click({ timeout: 5_000 });
await expect(page.getByText(/Selected: 2 goals?/i)).toBeHidden({
timeout: 5_000
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Assert the bulk-edit bar is hidden after the action.

These checks only prove the Selected: 2 goals label went away. If the bar remains visible with another state, the tests still pass. Assert getBulkEditBar(page) is hidden after Clear selection and after Star.

Also applies to: 84-86

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

In `@apps/e2e-playwright/tests/shared/focus/goal/bulk-editor.spec.ts` around lines
57 - 62, After clicking the "Clear selection" button and after the "Star"
action, assert that the bulk-edit bar element itself (obtained via
getBulkEditBar(page)) is hidden, not just that the "Selected: 2 goals" label
disappeared; update the assertions following the click calls to call something
like expect(getBulkEditBar(page)).toBeHidden({ timeout: 5000 }) so the test
verifies the entire bar is gone; do the same change for the second instance
around the Star action (the other assertion block at lines ~84-86) to ensure
getBulkEditBar(page) is hidden after that interaction as well.

Comment on lines +57 to +62
await getBulkEditBar(page)
.getByRole("button", { name: /Clear selection/i })
.click({ timeout: 5_000 });
await expect(page.getByText(/Selected: 2 tasks?/i)).toBeHidden({
timeout: 5_000
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Assert the bulk-edit bar is hidden after the action.

Both paths only verify that Selected: 2 tasks disappeared. If the bar stays visible with a different state, these tests still pass. Assert getBulkEditBar(page) is hidden after Clear selection and after Mark as completed.

Also applies to: 84-86

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

In `@apps/e2e-playwright/tests/shared/focus/task/bulk-editor.spec.ts` around lines
57 - 62, After clicking the "Clear selection" button (and similarly after "Mark
as completed"), the test must assert that the entire bulk-edit bar is hidden,
not just that the "Selected: 2 tasks" text disappeared; update the assertions to
call getBulkEditBar(page) and expect(...).toBeHidden({ timeout: 5_000 })
immediately after the click for the Clear selection case and the Mark as
completed case (referencing getBulkEditBar(page) and the role button names
"Clear selection" and "Mark as completed" to locate the two places to change).

Comment on lines +57 to +62
await getBulkEditBar(page)
.getByRole("button", { name: /Clear selection/i })
.click({ timeout: 5_000 });
await expect(page.getByText(/Selected: 2 nodes?/i)).toBeHidden({
timeout: 5_000
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Assert the bulk-edit bar is hidden after the action.

These assertions only check that Selected: 2 nodes disappeared. If the bar stays visible with a different state, the regression still passes. Assert getBulkEditBar(page) is hidden after Clear selection and after Star.

Also applies to: 84-86

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

In `@apps/e2e-playwright/tests/shared/memory/node/bulk-editor.spec.ts` around
lines 57 - 62, After clicking the "Clear selection" button, assert that the
bulk-edit bar element itself is hidden rather than only checking the text;
replace the text-based expectation with an assertion that getBulkEditBar(page)
is hidden (e.g., await expect(getBulkEditBar(page)).toBeHidden({ timeout: 5_000
})). Do the same for the "Star" action: after triggering the Star control where
the test currently checks for text changes (lines corresponding to the second
case), assert that getBulkEditBar(page) is hidden using getBulkEditBar(page) to
ensure the entire bar is gone.

@vercel vercel bot temporarily deployed to Preview – memotron March 11, 2026 07:45 Inactive
Copy link
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.

♻️ Duplicate comments (2)
apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts (2)

62-67: ⚠️ Potential issue | 🟡 Minor

Assert the bulk-edit bar is hidden, not just the old label.

Lines 65-67, 103-105, 182-184, and 220-222 only wait for Selected: 2 collections to disappear. These paths still pass if the bar remains visible with a different state. Assert getBulkEditBar(page) is hidden after Clear selection, Star, Archive, and Delete.

Suggested tightening
     await getBulkEditBar(page)
       .getByRole("button", { name: /Clear selection/i })
       .click({ timeout: 5_000 });
-    await expect(
-      page.getByText(/Selected: 2 collections?/i)
-    ).toBeHidden({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toBeHidden({ timeout: 5_000 });

@@
     await expect(
       page.getByText(/Starred 2 collections? successfully/i)
     ).toBeVisible({ timeout: 10_000 });
-    await expect(
-      page.getByText(/Selected: 2 collections?/i)
-    ).toBeHidden({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toBeHidden({ timeout: 5_000 });

@@
     await expect(
       page.getByText(/Archived 2 collections? successfully/i)
     ).toBeVisible({ timeout: 10_000 });
-    await expect(
-      page.getByText(/Selected: 2 collections?/i)
-    ).toBeHidden({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toBeHidden({ timeout: 5_000 });

@@
     await expect(
       page.getByText(/Deleted 2 collections? successfully/i)
     ).toBeVisible({ timeout: 10_000 });
-    await expect(
-      page.getByText(/Selected: 2 collections?/i)
-    ).toBeHidden({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toBeHidden({ timeout: 5_000 });

Also applies to: 103-105, 182-184, 220-222

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

In `@apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts` around lines
62 - 67, The tests currently only wait for the old label text to disappear after
actions (Clear selection / Star / Archive / Delete); instead assert the entire
bulk-edit UI is hidden. After invoking
getBulkEditBar(page).getByRole(...).click(...) (or performing
Star/Archive/Delete flows), replace the expect(page.getByText(/Selected: \d+
collections?/i)).toBeHidden(...) checks with
expect(getBulkEditBar(page)).toBeHidden(...), so the assertion targets the
bulk-edit container (getBulkEditBar(page)) being hidden rather than just the
label text.

131-146: ⚠️ Potential issue | 🟡 Minor

Select all is still vacuous when only two collections are present.

Line 134 can still produce totalCount === 2 on a clean library, so this test passes even if Select all is a no-op. Require more than two visible collections before the click, then assert the count from the bulk-edit bar.

Suggested tightening
     const container = page.locator("#records-container");
     const thumbnails = container.locator('div[id^="thumbnail-"]');
     await expect(thumbnails.first()).toBeVisible({ timeout: 10_000 });
     const totalCount = await thumbnails.count();
+    expect(totalCount).toBeGreaterThan(2);

     await selectFirstTwoViaContextMenu(page, "records-container");
     await expect(
       page.getByText(/Selected: 2 collections?/i)
     ).toBeVisible({ timeout: 10_000 });

     await getBulkEditBar(page)
       .getByRole("button", { name: /Select all/i })
       .click({ timeout: 5_000 });
-    await expect(
-      page.getByText(new RegExp(`Selected: ${totalCount} collections?`, "i"))
-    ).toBeVisible({ timeout: 5_000 });
+    await expect(getBulkEditBar(page)).toContainText(`Selected: ${totalCount}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts` around lines
131 - 146, The test currently allows totalCount === 2 which masks a no-op
"Select all"; update the test around the thumbnails/count logic so it requires
more than two visible collections before exercising the Select all flow: after
computing totalCount from container/thumbnails ensure totalCount > 2 (fail or
skip the test if not) then call selectFirstTwoViaContextMenu(page,
"records-container"), click the Select all button obtained via
getBulkEditBar(page).getByRole("button", { name: /Select all/i }), and assert
the bulk-edit bar shows "Selected: {totalCount} collection(s)" (use the existing
RegExp matching) to verify Select all actually selects all items.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts`:
- Around line 62-67: The tests currently only wait for the old label text to
disappear after actions (Clear selection / Star / Archive / Delete); instead
assert the entire bulk-edit UI is hidden. After invoking
getBulkEditBar(page).getByRole(...).click(...) (or performing
Star/Archive/Delete flows), replace the expect(page.getByText(/Selected: \d+
collections?/i)).toBeHidden(...) checks with
expect(getBulkEditBar(page)).toBeHidden(...), so the assertion targets the
bulk-edit container (getBulkEditBar(page)) being hidden rather than just the
label text.
- Around line 131-146: The test currently allows totalCount === 2 which masks a
no-op "Select all"; update the test around the thumbnails/count logic so it
requires more than two visible collections before exercising the Select all
flow: after computing totalCount from container/thumbnails ensure totalCount > 2
(fail or skip the test if not) then call selectFirstTwoViaContextMenu(page,
"records-container"), click the Select all button obtained via
getBulkEditBar(page).getByRole("button", { name: /Select all/i }), and assert
the bulk-edit bar shows "Selected: {totalCount} collection(s)" (use the existing
RegExp matching) to verify Select all actually selects all items.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 015775fc-7d93-444b-8d81-5544a04602fa

📥 Commits

Reviewing files that changed from the base of the PR and between d2464e9 and 8b2a8ce.

📒 Files selected for processing (1)
  • apps/e2e-playwright/tests/shared/collection/bulk-editor.spec.ts

@thyaravind
Copy link
Member

@codex

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Bravo.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai coderabbitai bot mentioned this pull request Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants