Skip to content

Persist spec list directory expansion state across reloads - #34733

Open
pj-18 wants to merge 3 commits into
cypress-io:developfrom
pj-18:issue-33964
Open

Persist spec list directory expansion state across reloads#34733
pj-18 wants to merge 3 commits into
cypress-io:developfrom
pj-18:issue-33964

Conversation

@pj-18

@pj-18 pj-18 commented Aug 29, 2026

Copy link
Copy Markdown

Additional details

The spec list's directory expansion/collapse state was only ever kept in an in-memory ref/Map, so it reset every time the app reloaded — including the runner's own "Run all specs" flow, which relaunches in a new tab and clears all localStorage for the app's origin before that tab mounts, so localStorage wasn't a viable place to persist this either.

This change persists the expansion state to the project's saved state on disk (the same disk-backed mechanism already used for the spec search filter), scoped per project, and restores it on load.

Implementation notes:

  • useCollapsibleTree's cache is now read through toRaw() when a node is first built. The tree is built inside a computed, so previously every expansion write invalidated that computed and rebuilt the whole tree, which reset scroll position and keyboard focus on every single toggle. Writes still go through the reactive object so persistence still observes them, but the read no longer subscribes to it.
  • Only collapsed directories are persisted (expanded is already the default), and directories that no longer exist in the current spec list are pruned before saving, so the saved state doesn't grow indefinitely as the project's files change over time.
  • The setPreferences GraphQL mutation previously deep-merged every saved preference, which meant a client could never actually remove an entry — only add or overwrite one. specsListTreeExpansion is now written as a full replacement snapshot instead of a merge patch, guarded so it only applies at the top level (a nested key that happens to share the name is unaffected).
  • Persistence is debounced (200ms) so collapsing several directories in a row is coalesced into a single write instead of one per toggle.
  • While a search filter is active, toggles go into a separate in-memory-only cache instead of the persisted one, so filtering never overwrites what the user had collapsed in the unfiltered view, and every filter match stays visible regardless of prior collapse state.

Steps to test

  1. Open a project with nested spec directories (e.g. src/components, src/utils) in cypress open.
  2. In the specs list, collapse one of the directories.
  3. Reload the app (or trigger "Run all specs", which relaunches in a new tab).
  4. Confirm the directory you collapsed is still collapsed after reload.
  5. Type into the spec search filter — confirm all directories expand to show matches, and toggling one while filtering doesn't affect what's saved.
  6. Clear the search filter — confirm your originally collapsed directory is still collapsed.
  7. Toggle a directory open/closed a few times in quick succession — confirm no visible flicker, scroll jump, or lost keyboard focus in the list.

How has the user experience changed?

Directory collapse/expand state in the spec list now survives page reloads and the "Run all specs" new-tab relaunch, instead of always resetting to fully expanded.

chrome_NMCTpgaHLT

PR Tasks

  • Is there an associated issue with maintainer approval for PR submission?
  • Have tests been added/updated?
  • Has a PR for user-facing changes been opened in cypress-documentation?
  • Have API changes been updated in the type definitions?

@CLAassistant

CLAassistant commented Aug 29, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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.

Persist spec accordion states

2 participants