feat(user-metadata): enhance Google metadata handling and update tests#1531
feat(user-metadata): enhance Google metadata handling and update tests#1531tyler-dane merged 23 commits intomainfrom
Conversation
c3693b4 to
b246bab
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Redundant identical return blocks in hook
- Removed the redundant syncStatus === "healthy" check block since the catch-all connectionStatus === "connected" block already handles it with identical return values.
|
@cursoragent web tests are failing, plz fix |
|
Bugbot Autofix prepared a fix for the issue found in the latest run.
|
- Updated the user metadata service to assess Google connection and sync status, enriching metadata with connection status and sync state. - Introduced a new driver for user metadata service tests to streamline testing of metadata updates. - Modified existing tests to validate new Google metadata assessment logic, ensuring accurate handling of connection and sync states. - Refactored user driver to support conditional user creation based on Google connection status. - Cleaned up WebSocket server logic by removing deprecated Google token status checks on connection.
Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
…tIncremental Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
- fix(sync): force-restart sync when Google returns 410 error instead of delegating to assessGoogleMetadata, which checks token existence not validity - fix(web): add catch-all for connected users with unhandled sync status to show correct label Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
- Introduced new functions to wait for Google Calendar import start and end events. - Updated tests to utilize these functions for improved clarity and reliability. - Refactored import result parsing for better type safety and readability. - Adjusted test assertions to ensure correct behavior during import processes.
- Added a catch block to handle errors from the afterEvent promise, ensuring proper rejection with a standardized Error object. - Enhanced error handling in the beforeEvent callback to ensure consistent error reporting.
…Google hook - Refactored the useConnectGoogle hook to return a structured configuration for command actions and sidebar status. - Updated tests to reflect changes in the hook's return structure, ensuring accurate assertions for various connection states. - Improved the SidebarIconRow component to utilize the new configuration for displaying Google Calendar connection status. - Added a disabled state for the TooltipWrapper when the Google Calendar is connected or syncing.
- Added a `force` option to the `importGCal` method in `SyncControllerDriver` to allow forced imports. - Introduced a new `WatchDriver` for managing watch collection tests, improving test isolation and flexibility. - Updated `importGCal` method in `SyncController` to handle the `force` parameter, enabling forced sync operations. - Enhanced tests in `sync.controller.test.ts` to verify forced import behavior and ensure correct handling of completed sync states. - Improved user metadata service to return healthy status without active watches when not using HTTPS. - Updated user service tests to validate event sync token persistence without HTTPS, ensuring local sync health.
…tGoogle hook - Enhanced the useConnectGoogle hook to manage Google Calendar repair state, integrating a new repair action that triggers forced imports. - Updated the SyncApi to accept an options parameter for the importGCal method, allowing for forced sync operations. - Refactored tests for useConnectGoogle and related components to validate the new repair logic and ensure accurate assertions for various connection states. - Improved user interface feedback during repair processes, including updated tooltips and sidebar statuses. - Ensured that socket emissions for user metadata fetching are correctly triggered during import events.
…yer imports - Added a note in testing documentation to discourage importing `mongoService` or other persistence layers directly in tests. - Recommended using test drivers (e.g., `UserDriver`, `WatchDriver`) to maintain test agnosticism towards the backing store, facilitating easier transitions away from MongoDB in the future.
Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
…ndar labels Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
…e UI fix(backend): add race condition check before scheduling Google repair fix(web): only close command palette when repair triggered from command palette Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
…cessing - Updated SyncController to skip recovery if a full import is already active for the user. - Refactored syncService to ignore stale notifications when no exact watch record exists, improving notification handling. - Enhanced tests to validate the new behavior for handling Google Calendar notifications and sync states. - Improved user metadata service to return appropriate sync statuses without scheduling unnecessary repairs.
- Introduced a new type for the response structure from SupertokensUserMetadata, improving type safety. - Updated the getStoredUserMetadata and updateUserMetadata methods to handle the new response format, ensuring proper error handling and returning the correct metadata. - Enhanced code readability by simplifying the response handling process.
…e management - Introduced a new utility function, `refreshUserMetadata`, to handle user metadata retrieval and state updates in the Redux store. - Enhanced the `userMetadataSlice` to include loading states, allowing for better user experience during metadata fetching. - Updated the `SessionProvider` to refresh user metadata upon session initialization and when a session already exists. - Refactored the `useConnectGoogle` hook to incorporate user metadata status, improving the handling of Google Calendar connection states. - Added tests for the new user metadata utility and updated existing tests to ensure proper functionality and state management.
- Mocked the `react-cmdk` library to provide a more accurate testing environment for the command palette component. - Updated test assertions to use `getByRole` for button state checks, ensuring better accessibility compliance and clarity in tests. - Improved the handling of disabled button states in tests for Google Calendar connection and syncing actions.
- Removed the use of `FETCH_USER_METADATA` in favor of directly reconnecting the socket to ensure a fresh session after Google revocation. - Updated the test case to reflect the new behavior, verifying that the socket reconnects instead of emitting a metadata fetch event. - Improved code clarity by simplifying the revocation handling logic.
dacb533 to
960611f
Compare
…red payloads - Introduced a new type, `ImportGCalEndPayload`, to standardize the payload structure for Google Calendar import completion events. - Updated the `handleImportGCalEnd` method to accept the new payload type, improving type safety and clarity. - Refactored various components and tests to utilize the structured payload, ensuring consistent handling of import results and error messages. - Enhanced tests to validate the new payload structure and its impact on the import flow.
…unctions - Introduced utility functions for managing Google sign-in success and session user ID resolution, improving the handling of Google authentication flows. - Updated the `signInUpPOST` API implementation to integrate Google sign-in success handling, ensuring proper session management. - Added tests for the new utility functions to validate their behavior in various scenarios, enhancing overall test coverage. - Refactored the `useGoogleAuth` hook to support reconnect intents, improving user experience during Google Calendar reconnections.
| ); | ||
| } | ||
|
|
||
| // Trigger refetch to load imported events (no page reload) |
There was a problem hiding this comment.
Import-ignored status still dispatches triggerFetch for refetch
Medium Severity
In onImportEnd, when payload is undefined (or has an unrecognized status) and isImportPendingRef.current is true, none of the if checks for "errored", "ignored", or "completed" match, so the code falls through and dispatches triggerFetch with reason IMPORT_COMPLETE. This triggers a data refetch without setting any import results, effectively signaling a successful import completion when none occurred. While the backend currently always sends typed payloads, this fall-through is a defensive gap.
| describe("CompassApi interceptor auth handling", () => { | ||
| it("sends cookies with cross-origin API requests", () => { | ||
| expect(CompassApi.defaults.withCredentials).toBe(true); | ||
| }); |
There was a problem hiding this comment.
Test places it block before beforeEach setup
Low Severity
The new test "sends cookies with cross-origin API requests" is placed before the beforeEach block in its describe scope. While Jest still runs beforeEach before each it, this unconventional ordering breaks the established readability pattern where setup comes before test cases. Moving the test after beforeEach would match the rest of the test file's structure.





manual test steps
Use this sequence in a local dev session.
Setup
Run
yarn dev:web. If you need backend-backed auth/sync behavior, also run the backend with a valid.envand Google/Mongo config. Open the app in two tabs so you can verify cross-tab durability.1. Never connected
Start with a user that has never linked Google, or a fresh account.
Open the command palette in each tab.
Confirm the Google item says
Connect Google Calendar.Refresh both tabs.
Confirm it still says
Connect Google Calendar.2. Healthy connected state
Connect Google successfully.
Wait for the initial import to finish.
Open the command palette.
Confirm the Google item says
Google Calendar Connected.Refresh the page and open a second tab.
Confirm both tabs still show
Google Calendar Connected.3. Reconnect required after revoke/prune
Use a user that previously connected Google, then revoke access or clear the stored refresh token on the backend while keeping
googleIdon the user.Refresh the page or reconnect the socket.
Open the command palette.
Confirm the Google item says
Reconnect Google Calendar.Confirm this appears immediately after refresh in a new tab too, without needing a prior in-tab revoke event.
If the app receives
GOOGLE_REVOKED, confirm Google events disappear and the import overlay clears, but the durable command-palette state still settles onReconnect Google Calendar.4. Auto-repair for broken local sync
Use a connected user with a valid refresh token, then break local sync state on the backend:
delete the sync row, or remove an events
nextSyncToken, or delete/expire a required watch.Refresh the page or reconnect the socket.
Open the command palette immediately.
Confirm the Google item says
Syncing Google Calendar...and is disabled.Wait for repair/import to finish.
Reopen the command palette.
Confirm it changes to
Google Calendar Connected.Repeat in a second tab to confirm reconnecting tabs self-heal too.
5. No duplicate repair while already importing
With a broken connected account, trigger the auto-repair once.
While the backend import is still running, refresh repeatedly or open additional tabs.
Confirm the UI continues to show
Syncing Google Calendar....Check backend logs and confirm only one forced restart/import is started for that repair window.
6. Attention state after failed repair
Use a connected user with valid credentials, but force repair to fail repeatedly on the backend.
Refresh/reconnect the client after the failed repair leaves
importGCalerrored and sync still broken.Open the command palette.
Confirm the Google item says
Repair Google Calendar.Confirm it does not immediately auto-retry just because metadata says
errored.Click
Repair Google Calendar.Confirm the existing Google auth/reconnect flow opens.
7. Overlay behavior
During an explicit connect/reconnect flow, confirm the import overlay still appears while import is pending/running.
If the backend reports import already completed on reconnect, confirm the overlay clears correctly.
For the
attentionstate, confirm there is no stuck overlay and only the command-palette status changes.8. Sign-out cleanup
While connected or in reconnect/attention state, sign out.
Confirm the stored Google metadata clears.
Sign back in as an unauthenticated/fresh session and open the command palette.
Confirm stale Google labels are gone and the item reflects the current server state.
9. Unknown stale watch notification regression
If you can hit the notification endpoint manually, send a stale/unknown watch notification:
one with no matching watch, and one where only
resourceIdcan still be mapped.Confirm the endpoint returns success/ignored behavior rather than surfacing a 400.
For the mappable case, confirm backend logs show cleanup/repair scheduling and the user eventually returns to
Syncing Google Calendar...orGoogle Calendar Connected.10. Cross-tab durability summary check
Keep two tabs open throughout.
For each transition:
Connect->ConnectedConnectedbroken ->Syncingfailed repair ->
Repairrevoked token ->
ReconnectRefresh both tabs after each transition.
Confirm the label is derived from backend metadata in both tabs, not from stale local tab state.
Note
Medium Risk
Touches Google auth/sync and websocket payload contracts across backend+web; behavior changes around imports/repairs and session handling could impact login and sync UX if edge cases are missed.
Overview
Adds richer Google account health to
UserMetadataby assessing connection state (not_connected/reconnect_required/connected) and sync state (healthy/repairing/attention/none) inuser-metadata.service, and updates tests/drivers to cover these scenarios.Refactors Google OAuth handling to pass a
googleAuthIntent(connect vs reconnect) through SuperTokenssignInUpPOST, adds a small util layer with unit tests, and updates web session init/auth flows to refresh/clear metadata on session changes.Changes the Google Calendar import/repair workflow:
POST /sync/import-gcalnow supports{ force: true }, websocketIMPORT_GCAL_ENDnow emits a structuredImportGCalEndPayload(completed/ignored/errored), and stale watch cleanup now only acts on exact watch matches (ignoring resourceId-only notifications). Web UI (CmdPalette, sidebar) is updated to drive connect/reconnect/repair actions from metadata, including forced repair triggers, socket metadata refetch on import end, and reconnecting the socket on Google revoke.Written by Cursor Bugbot for commit ca471b7. This will update automatically on new commits. Configure here.