* 🔖 fix: Decrement Bookmark Counts When Deleting Conversations Deleting a bookmarked/tagged conversation removed the conversation but never decremented the affected ConversationTag counts, leaving stale bookmark counts in the UI. - Add decrementTagCounts helper that atomically decrements tag counts (clamped at 0, deduped per conversation) in deleteConvos, covering single delete, clear-all, and account deletion. - Invalidate the conversationTags query in the single-delete and clear-all client mutations so counts refetch. - Add deleteConvos tag-count tests. * 🔒 fix: Guard tag-count decrement on actual deletion and message-failure Addresses Codex review findings: - Guard the decrement on deleteConvoResult.deletedCount > 0 so a losing concurrent delete (double-click/two-tab) does not decrement counts for a conversation it did not actually remove. - Move the count adjustment to run immediately after the conversation deletion, before message cleanup, so a deleteMessages failure cannot leave bookmark counts permanently stale. - Add regression tests for both cases. * 🔀 fix: Refresh project stats after message cleanup in deleteConvos Addresses Codex finding: bundling refreshChatProjectStatsForUser into a Promise.all before deleteMessages let a stats-refresh error abort the function and orphan the deleted conversations' messages. Split the steps so the (best-effort) tag-count decrement still runs before message cleanup (counts reconciled even if messages fail), while project-stats refresh runs after, matching the original ordering. * ✅ test: Add e2e coverage for bookmark counts on conversation delete Two mock-harness specs for the deleteConvos bookmark-count behavior: - Deleting the only conversation carrying a bookmark drops its count to 0. - Deleting one of two conversations that share a bookmark leaves the count at 1. Both assert the persisted server count via GET /api/tags after the real delete round-trip. * chore: import order |
||
|---|---|---|
| .. | ||
| config | ||
| fixtures/deployment-skills/e2e-deployment-skill | ||
| recordings | ||
| setup | ||
| specs | ||
| config.local.example.ts | ||
| jestSetup.js | ||
| playwright.config.a11y.ts | ||
| playwright.config.local.ts | ||
| playwright.config.mock.ts | ||
| playwright.config.real.ts | ||
| playwright.config.ts | ||
| README.md | ||
| types.ts | ||
LibreChat e2e
The mock e2e profile is the safest default for generated tests. It starts LibreChat with e2e/config/librechat.e2e.yaml, injects an in-process fake LLM (via LIBRECHAT_TEST_RUN_HOOK), creates an authenticated e2e user, and avoids real provider credentials.
Recording Tests
Use Playwright codegen when you want to turn an exploratory browser session into a draft test:
npm run e2e:record
That command builds the app, starts the LibreChat test server (with an in-process fake LLM) when needed, writes e2e/storageState.json, and opens Playwright codegen at /c/new. The npm script uses http://localhost:3333 so it does not collide with a normal dev server on 3080. Raw recordings are written to e2e/recordings/ and ignored by git.
For a real local LibreChat config instead of the mock profile:
npm run e2e:record:local
Useful direct options:
node e2e/setup/record.js --url=http://localhost:3080/c/new
node e2e/setup/record.js --profile=local --no-output
node e2e/setup/record.js --auth-only
node e2e/setup/record.js --output=e2e/recordings/settings-draft.spec.ts
LLM-Assisted Loop
- Start
npm run e2e:record. - Let the LLM use Computer Use to operate the headed Playwright browser.
- Stop codegen after the workflow is captured.
- Move the useful parts from
e2e/recordings/into a committed spec undere2e/specs/mock/. - Replace brittle generated selectors with role, label, text, or
data-testidlocators. - Add assertions that prove the behavior, not just the clicked path.
- Run the finished spec with
npm run e2e:mock -- <spec name>.
Generated recordings are a draft, not the final test. The committed version should use the shared helpers in e2e/specs/mock/helpers.ts where possible, wait on network or visible UI state instead of fixed sleeps, and keep test data deterministic.