Skip to content

OLS-1555: Add Cypress tests for HITL tool approval flow#1909

Open
kyoto wants to merge 1 commit intoopenshift:mainfrom
kyoto:HITL-tests
Open

OLS-1555: Add Cypress tests for HITL tool approval flow#1909
kyoto wants to merge 1 commit intoopenshift:mainfrom
kyoto:HITL-tests

Conversation

@kyoto
Copy link
Copy Markdown
Member

@kyoto kyoto commented May 7, 2026

Summary by CodeRabbit

  • Tests
    • Added end-to-end tests covering human-in-the-loop tool approval flows: verifies “Review required” approval card, approve/reject actions, disappearance of the card, tool label appearance, and resulting modal content for approved vs. rejected tool calls.
    • Added test helpers to simulate streaming responses and tool approval decisions for these scenarios.

@kyoto kyoto requested a review from JoaoFula May 7, 2026 04:55
@kyoto kyoto added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 7, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

📝 Walkthrough

Walkthrough

Adds Cypress test support and end-to-end tests for human-in-the-loop (HITL) tool approvals: new test commands stub streaming-query responses that require approval and stub approval decision submissions; test cases validate both approve and reject UI flows.

Changes

HITL Tool Approval Testing

Layer / File(s) Summary
Mock streamed response
cypress/support/commands.ts
Introduces MOCK_STREAMED_RESPONSE_WITH_APPROVAL_BODY SSE payload containing an approval_required event with approval_id: "abc" and tool metadata.
Test Command Implementations
cypress/support/commands.ts
Adds interceptQueryWithApproval(alias, query) to intercept POST /v1/streaming_query, assert media_type and query contains substring, and reply with the mock SSE body; adds interceptToolApproval(alias, approved) to intercept POST /v1/tool-approvals/decision, assert approval_id === "abc" and approved matches, and reply with {}.
Test Selectors
tests/tests/lightspeed-install.cy.ts
Adds selector constants for the HITL approval card container and the tool label used in the popover/modal UI.
Test Suite
tests/tests/lightspeed-install.cy.ts
Adds describe('Tool approval (HITL)') with two E2E tests: an approve path (approval card appears, details opened, approve action sent, card removed, tool label/modal show Status: pending and no rejection text) and a reject path (reject action sent, card removed, tool label present, modal shows “Tool call rejected” and omits Status/Content).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately describes the main changes in the pull request, which adds Cypress tests for the HITL (Human-In-The-Loop) tool approval flow.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci Bot requested a review from syedriko May 7, 2026 04:55
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 7, 2026

[APPROVALNOTIFIER] This PR is APPROVED

Approval requirements bypassed by manually added approval.

This pull-request has been approved by:

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

1 similar comment
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 7, 2026

[APPROVALNOTIFIER] This PR is APPROVED

Approval requirements bypassed by manually added approval.

This pull-request has been approved by:

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
cypress/support/commands.ts (1)

198-202: ⚡ Quick win

Add request-shape assertion parity with interceptQuery.

Line 200 only asserts query. Adding a media_type assertion here (same as interceptQuery) will catch malformed request bodies in this path too.

Proposed patch
 Cypress.Commands.add('interceptQueryWithApproval', (alias: string, query: string) => {
   cy.intercept('POST', getApiUrl('/v1/streaming_query'), (request) => {
+    expect(request.body.media_type).to.equal('application/json');
     expect(request.body.query).to.include(query);
     request.reply({ body: MOCK_STREAMED_RESPONSE_WITH_APPROVAL_BODY, delay: 500 });
   }).as(alias);
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cypress/support/commands.ts` around lines 198 - 202, The
interceptQueryWithApproval command only asserts request.body.query and misses
the media_type check present in interceptQuery; update the handler inside
Cypress.Commands.add('interceptQueryWithApproval', (alias, query) => { ... }) so
that the intercepted request callback also asserts request.body.media_type is
the same expected value used by interceptQuery (e.g., 'text' or the shared
constant), then leave the existing query assertion and reply behavior intact so
malformed request bodies with wrong media_type are caught the same way as
interceptQuery.
tests/tests/lightspeed-install.cy.ts (1)

36-37: ⚡ Quick win

Scope toolLabel selector tighter to reduce flake risk.

Line 37 currently targets any PatternFly label inside the popover. If additional labels appear, assertions/clicks may hit the wrong element.

Proposed patch
-const toolLabel = `${popover} .pf-v6-c-label`;
+const toolLabel = `${aiChatEntry} .pf-v6-c-label`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/tests/lightspeed-install.cy.ts` around lines 36 - 37, The toolLabel
selector is too broad and may match any PatternFly label inside the popover;
tighten it so interactions target the specific label associated with the tool
approval card (e.g., scope by relation to toolApprovalCard, a unique
modifier/class, data-* attribute, or text selector) — update the toolLabel
constant so it selects the label adjacent to or inside the `${popover}
.ols-plugin__tool-call` element rather than every `.pf-v6-c-label` in the
popover.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cypress/support/commands.ts`:
- Around line 198-202: The interceptQueryWithApproval command only asserts
request.body.query and misses the media_type check present in interceptQuery;
update the handler inside Cypress.Commands.add('interceptQueryWithApproval',
(alias, query) => { ... }) so that the intercepted request callback also asserts
request.body.media_type is the same expected value used by interceptQuery (e.g.,
'text' or the shared constant), then leave the existing query assertion and
reply behavior intact so malformed request bodies with wrong media_type are
caught the same way as interceptQuery.

In `@tests/tests/lightspeed-install.cy.ts`:
- Around line 36-37: The toolLabel selector is too broad and may match any
PatternFly label inside the popover; tighten it so interactions target the
specific label associated with the tool approval card (e.g., scope by relation
to toolApprovalCard, a unique modifier/class, data-* attribute, or text
selector) — update the toolLabel constant so it selects the label adjacent to or
inside the `${popover} .ols-plugin__tool-call` element rather than every
`.pf-v6-c-label` in the popover.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: fa03a085-6a6b-4f30-9ee6-e517f219be9e

📥 Commits

Reviewing files that changed from the base of the PR and between c8fbfba and 1f54ddc.

📒 Files selected for processing (2)
  • cypress/support/commands.ts
  • tests/tests/lightspeed-install.cy.ts

@kyoto
Copy link
Copy Markdown
Member Author

kyoto commented May 7, 2026

/cherry-pick release-4.19

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
cypress/support/commands.ts (1)

192-192: ⚡ Quick win

Extract approval_id magic string as a named constant.

"abc" appears in both the mock SSE body (line 192) and the assertion in interceptToolApproval (line 208). If either changes without the other, the test fails with a confusing mismatch rather than a clear signal. A single named constant makes the coupling explicit.

♻️ Proposed refactor
+const MOCK_APPROVAL_ID = 'abc';
+
 /* eslint-disable camelcase */
 const MOCK_STREAMED_RESPONSE_WITH_APPROVAL_BODY = `data: {"event": "start", ...}
 ...
-data: {"event": "approval_required", "data": {"approval_id": "abc", "tool_name": "mock_tool", ...}}
+data: {"event": "approval_required", "data": {"approval_id": "${MOCK_APPROVAL_ID}", "tool_name": "mock_tool", ...}}
 ...
 `;
 /* eslint-enable camelcase */

 Cypress.Commands.add('interceptToolApproval', (alias: string, approved: boolean) => {
   cy.intercept('POST', getApiUrl('/v1/tool-approvals/decision'), (request) => {
-    expect(request.body.approval_id).to.equal('abc');
+    expect(request.body.approval_id).to.equal(MOCK_APPROVAL_ID);
     expect(request.body.approved).to.equal(approved);
     request.reply({ statusCode: 200, body: {} });
   }).as(alias);
 });

Also applies to: 206-212

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cypress/support/commands.ts` at line 192, The test uses the literal
approval_id "abc" in the mock SSE payload and again in the assertion inside
interceptToolApproval, causing a brittle coupling; extract that magic string
into a single named constant (e.g., const MOCK_APPROVAL_ID = "abc") declared
near the top of cypress/support/commands.ts and replace the inline "abc"
occurrences in the SSE mock (the data JSON used for the approval_required event)
and in the interceptToolApproval assertion to reference MOCK_APPROVAL_ID so both
the mock and the assertion stay in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cypress/support/commands.ts`:
- Line 192: The test uses the literal approval_id "abc" in the mock SSE payload
and again in the assertion inside interceptToolApproval, causing a brittle
coupling; extract that magic string into a single named constant (e.g., const
MOCK_APPROVAL_ID = "abc") declared near the top of cypress/support/commands.ts
and replace the inline "abc" occurrences in the SSE mock (the data JSON used for
the approval_required event) and in the interceptToolApproval assertion to
reference MOCK_APPROVAL_ID so both the mock and the assertion stay in sync.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7587fdc7-96cd-4cf0-a6df-9d96b6c2ba80

📥 Commits

Reviewing files that changed from the base of the PR and between 1f54ddc and 5371f7f.

📒 Files selected for processing (2)
  • cypress/support/commands.ts
  • tests/tests/lightspeed-install.cy.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/tests/lightspeed-install.cy.ts

@kyoto
Copy link
Copy Markdown
Member Author

kyoto commented May 7, 2026

/retest

@openshift-cherrypick-robot
Copy link
Copy Markdown

@kyoto: once the present PR merges, I will cherry-pick it on top of release-4.19 in a new PR and assign it to you.

Details

In response to this:

/cherry-pick release-4.19

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@kyoto kyoto changed the title Add Cypress tests for HITL tool approval flow OLS-1555: Add Cypress tests for HITL tool approval flow May 7, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label May 7, 2026
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented May 7, 2026

@kyoto: This pull request references OLS-1555 which is a valid jira issue.

Details

In response to this:

Summary by CodeRabbit

  • Tests
  • Added end-to-end tests covering human-in-the-loop tool approval flows: verifies “Review required” approval card, approve/reject actions, disappearance of the card, tool label appearance, and resulting modal content for approved vs. rejected tool calls.
  • Added test helpers to simulate streaming responses and tool approval decisions for these scenarios.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants