Handle a null currentUser in homepage widgets

What does this MR do and why?

The homepage widgets read nested fields of currentUser in their Apollo update hooks. The GraphQL API returns currentUser: null when the request has no valid session. The hooks then throw, and the browser logs an uncaught TypeError. Under Vue 2 the widget stays blank. Under Vue 3 the render error in HomepageApp can take down the whole page.

This happens to a real user when the session expires while the homepage is open. When the tab gets focus again, the widgets refetch their data, and every request comes back with currentUser: null.

This MR treats a null currentUser as "no data" once, in each update hook. The widgets then render their empty state instead of throwing. The error handlers and the error states are not changed.

The change fixes these three browser console errors:

  • TypeError: Cannot read properties of null (reading 'assigned') in homepage_app.vue
  • TypeError: Cannot read properties of null (reading 'recentlyViewedItems') in recently_viewed_items.vue
  • TypeError: Cannot destructure property 'id' of '{}' as it is null. in todos_widget.vue

Ruled out

  • The queries do not resolve with partial data before the network response. vue-apollo only calls update when the result has data.
  • A user without to-do items or recently viewed items gets an empty list, not a null currentUser. Only a missing session makes the field null.

Follow-up

Once this MR and MR 256639 both merge, these three entries can be removed from spec/support/browser_console_allowlist.yml. All three list spec/features/users/login/regular_user_spec.rb:

  • TypeError: Cannot read properties of null (reading 'assigned')
  • TypeError: Cannot read properties of null (reading 'recentlyViewedItems')
  • TypeError: Cannot destructure property 'id' of '{}' as it is null.

How to verify

The errors are timing dependent in spec/features/users/login/regular_user_spec.rb. The session-expiry examples call expire_session while the homepage queries are still in flight in CI. Locally, the queries finish first, so the spec is green on master too.

A deterministic reproduction, run locally before and after the fix:

  1. Sign in and open the homepage.
  2. Expire the session in Redis (expire_session from SessionHelpers).
  3. Dispatch two visibilitychange events with Date.now moved forward by 10 seconds between them. This passes the widgets' debounce and makes them refetch.

Before the fix, the SEVERE browser log shows the three errors above. After the fix, it shows none of them. The login feature spec passes with an empty SEVERE console log.

Jest specs cover the state before the queries resolve and the state where they resolve with currentUser: null. They pass under yarn jest and VUE_VERSION=3 yarn jest. Without the fix, the two widget specs fail with the exact error messages, because the exception from update is rethrown from a timer that jest.runOnlyPendingTimers() flushes.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

References

Edited by Miguel Rincon

Merge request reports

Loading
Loading