Cover the Duo panel session inbox with an MSW integration spec

What does this MR do and why?

Adds an MSW integration spec for the Duo side panel's tabbed session inbox, plus the Rails-generated GraphQL fixture that feeds it. No application code changes.

The inbox reads two aliases of duoWorkflowWorkflows, needsDecision and all, out of one document, both selected through the fragment InboxConnection on DuoWorkflowConnection. Apollo drops fields whose fragment type condition cannot match and does not raise, so a hand-written __typename naming a type not in the schema renders two empty tabs with no error anywhere. An earlier iteration of the handler had that bug. Generating the fixture makes the schema the source of that __typename. No handler wiring is needed: api_handlers.js auto-maps fixture filenames through loadFixturesMap.

The fixture seeds 21 awaiting-input sessions so the decision tab paginates and 3 running sessions that sort ahead of them, so the two aliases' first 20 rows differ and a test cannot pass by reading the wrong alias. It lives in a nested describe with its own let_it_be records so it does not rewrite get_user_agent_flows and the specs that count its rows.

Chat-definition sessions are not seeded. The inbox excludes them with type: non_foundational_chat_agents, which ee/spec/finders/ai/duo_workflows/workflows_finder_spec.rb already covers, so asserting it again here would only restate the fixture.

One setup detail worth knowing before reading the fixture diff: DuoWorkflow is an authorized type and graphql-ruby drops unauthorized nodes out of a connection without error. read_duo_workflow needs :duo_workflow on the container, which ProjectPolicy prevents unless the ai_workflows licence is present and allowed_to_use?(:duo_agent_platform) holds. Under the file's outer gitlab_com_subscriptions stub that entitlement resolves through a Duo add-on purchase this fixture has no reason to seed, so the nested block drops back to the self-managed path. Without it both aliases come back as empty edge lists.

mountAISidebar now takes a namespace argument defaulted to user, mirroring what init_duo_panel.js passes in production. The inbox passes side_panel so the Sessions route resolves to the inbox index component; the default keeps every sibling spec on the route it had.

The empty-state cases use the variant framework. api_handlers.js did not consult getActiveVariant, so registering variants for a Duo panel operation was inert; it now checks for one ahead of the fixture-backed handler. The variant file is imported by the spec rather than by the handler, so a stale fixture takes down this spec alone instead of every suite that loads the panel handlers. Two variants cover the inbox's two empty states: the decision tab has its own copy, while the All tab has no empty-state slot and falls through to the shared list copy.

yarn jest:msw-integration ee/spec/frontend/msw_integration passes 35 suites and 167 tests, so the variant wiring is checked against the work-item specs that already depended on it. Search and pagination interactions are not covered here; they were verified in the browser on the parent MR.

References

Screenshots or screen recordings

No visual change; this is a test-only MR.

How to set up and validate locally

  1. Regenerate the fixture:
    bundle exec rspec ee/spec/frontend/fixtures/ai_duo_panel_integration.rb
  2. Run the suite:
    yarn jest:msw-integration ee/spec/frontend/msw_integration/ai_duo_panel

Plain yarn jest will not find these specs: testPathIgnorePatterns excludes msw_integration and reports a misleading No tests found, exiting with code 1.

Edited by Andrew Fontaine

Merge request reports

Loading
Loading