Skip to content

LCORE-1329: Adding new MCP E2E Tests#1327

Open
jrobertboos wants to merge 1 commit intolightspeed-core:mainfrom
jrobertboos:lcore-1329
Open

LCORE-1329: Adding new MCP E2E Tests#1327
jrobertboos wants to merge 1 commit intolightspeed-core:mainfrom
jrobertboos:lcore-1329

Conversation

@jrobertboos
Copy link
Contributor

@jrobertboos jrobertboos commented Mar 16, 2026

Description

E2E tests were added to cover all of the types of MCP authorization (static token, kubernetes, client, oauth). For each type of MCP Auth all endpoints that could be affected by auth are tested on each path (valid, invalid, omitted).

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Konflux configuration change
  • Unit tests improvement
  • Integration tests improvement
  • End to end tests improvement
  • Benchmarks improvement

Tools used to create PR

Identify any AI code assistants used in this PR (for transparency and review context)

  • Assisted-by: (e.g., Claude, CodeRabbit, Ollama, etc., N/A if not used)
  • Generated by: (e.g., tool name and version; N/A if not used)

Related Tickets & Documents

  • Related Issue LCORE-1329
  • Closes LCORE-1329

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

  • Please provide detailed steps to perform tests related to this code change.
  • How were the fix/results from this change verified? Please provide relevant screenshots or results.

Summary by CodeRabbit

  • Tests

    • Expanded MCP end-to-end coverage for OAuth, Kubernetes, file, and client auth with success/failure paths, invalid-token and missing-credentials scenarios, and per-auth configurations; removed an obsolete file-based feature.
    • Added test utilities to select configs, perform mode-specific cleanup, clear test storage between scenarios, and restart services; improved assertions including a "response does not contain" check; added a test secret fixture for invalid MCP tokens.
  • Documentation

    • Updated e2e testing docs to reflect new utilities and MCP toolgroup/shield workflows.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 16, 2026

Walkthrough

Adds comprehensive MCP e2e auth permutations (file, invalid-file, kubernetes, client, oauth), new test configs and secret, expands MCP feature tests, updates environment hooks to pick/restore MCP configs and perform mode-specific cleanup, and adds utilities to unregister MCP toolgroups and clear Llama Stack storage.

Changes

Cohort / File(s) Summary
New per-auth configs (library & server)
tests/e2e/configuration/library-mode/lightspeed-stack-invalid-mcp-file-auth.yaml, tests/e2e/configuration/library-mode/lightspeed-stack-mcp-client-auth.yaml, tests/e2e/configuration/library-mode/lightspeed-stack-mcp-kubernetes-auth.yaml, tests/e2e/configuration/library-mode/lightspeed-stack-mcp-oauth-auth.yaml, tests/e2e/configuration/server-mode/lightspeed-stack-invalid-mcp-file-auth.yaml, tests/e2e/configuration/server-mode/lightspeed-stack-mcp-client-auth.yaml, tests/e2e/configuration/server-mode/lightspeed-stack-mcp-kubernetes-auth.yaml, tests/e2e/configuration/server-mode/lightspeed-stack-mcp-oauth-auth.yaml
Added configs that exercise each MCP auth variant in both library and server modes.
Aggregate MCP configs
tests/e2e/configuration/library-mode/lightspeed-stack-mcp.yaml, tests/e2e/configuration/server-mode/lightspeed-stack-mcp.yaml
Removed provider_id from an entry; added mcp-kubernetes, mcp-file, and mcp-client entries with url and Authorization values.
Feature tests (added/removed)
tests/e2e/features/mcp.feature, tests/e2e/features/mcp_file_auth.feature
Deleted standalone mcp_file_auth.feature; added/expanded mcp.feature to cover file, invalid-file, kubernetes, client, and oauth auth flows including success and 401 cases.
Environment hooks
tests/e2e/features/environment.py
Extended before/after scenario hooks to detect MCP tags, select config, perform mode-specific cleanup (unregister toolgroups or clear storage), update scenario_config, restart lightspeed-stack, and restore configs.
Llama Stack utilities
tests/e2e/utils/llama_stack_utils.py
Reworked e2e utilities: added async helpers to unregister MCP toolgroups (_unregister_toolgroup_async, _unregister_mcp_toolgroups_async) and public wrapper unregister_mcp_toolgroups(); added shield-unregister helper stub and updated docstring.
Storage & restart utils
tests/e2e/utils/utils.py
Added clear_llama_stack_storage() to remove ~/.llama inside container (skips in Prow); updated restart_container to use pod restart in Prow and ensure health checks after restart.
Step definitions
tests/e2e/features/steps/common_http.py
Added check_response_body_does_not_contain() step to assert absence of a substring in response bodies.
Secrets & docker-compose
tests/e2e/secrets/invalid-mcp-token, docker-compose.yaml
Added tests/e2e/secrets/invalid-mcp-token (contents "invalid-token") and mounted it into lightspeed-stack via a new volume mapping.
Docs & test list
docs/e2e_testing.md, tests/e2e/test_list.txt
Updated docs to reference llama_stack_utils.py and removed features/mcp_file_auth.feature from tests/e2e/test_list.txt.

Sequence Diagram(s)

sequenceDiagram
participant TestRunner
participant EnvHook as Environment Hook
participant Docker as Docker/Compose
participant LCS as Lightspeed Stack
participant MCP as Mock MCP

TestRunner->>EnvHook: start scenario with MCP tag
EnvHook->>EnvHook: resolve config & selected cleanup
EnvHook->>EnvHook: if server -> unregister_mcp_toolgroups / if library -> clear storage
EnvHook->>Docker: apply config files & mount secrets
EnvHook->>LCS: restart service
TestRunner->>LCS: send API request (tools/query/stream)
LCS->>MCP: forward request with configured Authorization
MCP-->>LCS: respond (200 / 401)
LCS-->>TestRunner: return response
TestRunner->>EnvHook: teardown -> restore config & cleanup
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'LCORE-1329: Adding new MCP E2E Tests' directly matches the PR's main objective of adding comprehensive end-to-end tests for all MCP authorization types.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/e2e/features/steps/common_http.py`:
- Around line 181-197: There are two identical step definitions for the
`@then`("The body of the response does not contain {substring}") decorator
(function check_response_body_does_not_contain), causing AmbiguousStep and F811
errors; remove the duplicate definition so only the first
check_response_body_does_not_contain implementation remains, leaving its
assertion and docstring intact and deleting the second repeated block.

In `@tests/e2e/utils/llama_stack_utils.py`:
- Around line 40-53: The docstring for _unregister_toolgroup_async is
misleading—it says it returns (provider_id, provider_shield_id) but the function
signature and implementation return None; update the docstring in
_unregister_toolgroup_async to accurately state that it unregisters the
toolgroup and returns None (or remove the restoration tuple reference), making
sure to reference the function name _unregister_toolgroup_async and not change
the current return behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2c485079-4707-4284-b15d-82140aa7f41f

📥 Commits

Reviewing files that changed from the base of the PR and between 84faf9f and 128906f.

📒 Files selected for processing (22)
  • docker-compose.yaml
  • docs/e2e_testing.md
  • tests/e2e/configuration/library-mode/lightspeed-stack-invalid-mcp-file-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-client-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-file-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-kubernetes-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-oauth-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-invalid-mcp-file-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-client-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-file-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-kubernetes-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-oauth-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp.yaml
  • tests/e2e/features/environment.py
  • tests/e2e/features/mcp.feature
  • tests/e2e/features/mcp_file_auth.feature
  • tests/e2e/features/steps/common_http.py
  • tests/e2e/secrets/invalid-mcp-token
  • tests/e2e/test_list.txt
  • tests/e2e/utils/llama_stack_utils.py
  • tests/e2e/utils/utils.py
💤 Files with no reviewable changes (2)
  • tests/e2e/test_list.txt
  • tests/e2e/features/mcp_file_auth.feature

Comment on lines +40 to +53
async def _unregister_toolgroup_async(identifier: str) -> None:
"""Unregister a toolgroup by identifier; return (provider_id, provider_shield_id) for restore."""
client = _get_llama_stack_client()
try:
await client.toolgroups.unregister(identifier)
except APIConnectionError:
raise
except APIStatusError as e:
# 400 "not found": toolgroup already absent, scenario can proceed
if e.status_code == 400 and "not found" in str(e).lower():
return None
raise
finally:
await client.close()
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading docstring: function returns None, not a tuple.

The docstring says "return (provider_id, provider_shield_id) for restore" but the function signature is -> None and the implementation only returns None. This appears to be copied from _unregister_shield_async which does return restoration data.

📝 Proposed fix for the docstring
 async def _unregister_toolgroup_async(identifier: str) -> None:
-    """Unregister a toolgroup by identifier; return (provider_id, provider_shield_id) for restore."""
+    """Unregister a toolgroup by identifier."""
     client = _get_llama_stack_client()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/utils/llama_stack_utils.py` around lines 40 - 53, The docstring for
_unregister_toolgroup_async is misleading—it says it returns (provider_id,
provider_shield_id) but the function signature and implementation return None;
update the docstring in _unregister_toolgroup_async to accurately state that it
unregisters the toolgroup and returns None (or remove the restoration tuple
reference), making sure to reference the function name
_unregister_toolgroup_async and not change the current return behavior.

Copy link
Contributor

@tisnik tisnik left a comment

Choose a reason for hiding this comment

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

LGTM in overall. Two or three nits. Also please rebase + squash commits before merge

switch_config(context.scenario_config)
restart_container("lightspeed-stack")

config_name: str | None = None
Copy link
Contributor

Choose a reason for hiding this comment

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

later it will need to be refactored, not to use tags

config_name: str | None = None
if "MCPFileAuthConfig" in scenario.effective_tags:
config_name = "mcp-file-auth"
elif "InvalidMCPFileAuthConfig" in scenario.effective_tags:
Copy link
Contributor

Choose a reason for hiding this comment

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

and one reason why not to use tags is this (basically) mapping set->one item

raise
except APIStatusError as e:
# 400 "not found": toolgroup already absent, scenario can proceed
if e.status_code == 400 and "not found" in str(e).lower():
Copy link
Contributor

Choose a reason for hiding this comment

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

prob. ok, but later 400 might be changed to names constants (from requests etc.)

Copy link
Contributor

@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)
tests/e2e/features/mcp.feature (1)

12-12: Trailing whitespace in scenario names.

Several scenario names have trailing whitespace (e.g., lines 12, 51, 86, 106, 148, 185). This can cause unnecessary diff noise in future changes.

🧹 Remove trailing whitespace
-  Scenario: Check if tools endpoint succeeds when MCP file-based auth token is passed 
+  Scenario: Check if tools endpoint succeeds when MCP file-based auth token is passed

Apply similar fix to lines 51, 86, 106, 148, and 185.

Also applies to: 51-51, 86-86, 106-106, 148-148, 185-185

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/features/mcp.feature` at line 12, Remove the trailing spaces at the
end of the Scenario titles so they don't introduce diff noise; specifically trim
the trailing whitespace from "Scenario: Check if tools endpoint succeeds when
MCP file-based auth token is passed " and the other Scenario lines with trailing
spaces (the Scenario names at the same positions such as the ones currently
ending with a space on lines with texts like the ones referenced in the review),
ensuring each Scenario title string has no trailing whitespace.
tests/e2e/utils/utils.py (1)

266-276: Consider adding debug logging for observability.

The function silently ignores all non-timeout failures due to check=False without any logging. While this is reasonable (e.g., ~/.llama may not exist yet), the complete lack of feedback can make E2E test debugging harder.

💡 Optional: Add minimal logging for debugging
     try:
-        subprocess.run(
+        result = subprocess.run(
             ["docker", "exec", container_name, "sh", "-c", "rm -rf ~/.llama"],
             capture_output=True,
             text=True,
             timeout=10,
             check=False,
         )
+        if result.returncode != 0:
+            print(f"Note: clear_llama_stack_storage returned {result.returncode} (may be expected if directory doesn't exist)")
     except subprocess.TimeoutExpired as e:
         print(f"Failed to clear Llama Stack storage: {e}")
         raise
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/utils/utils.py` around lines 266 - 276, The subprocess.run call
that removes ~/.llama (inside the try block using container_name) uses
check=False so non-timeout failures are silent; capture the CompletedProcess
result (assign subprocess.run(...) to a variable) and if result.returncode != 0
log a debug/info message including container_name, the command run, and
result.stderr/result.stdout (or at least returncode) so failed removals are
observable while still not raising; keep the existing TimeoutExpired except
branch unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/e2e/features/mcp.feature`:
- Line 12: Remove the trailing spaces at the end of the Scenario titles so they
don't introduce diff noise; specifically trim the trailing whitespace from
"Scenario: Check if tools endpoint succeeds when MCP file-based auth token is
passed " and the other Scenario lines with trailing spaces (the Scenario names
at the same positions such as the ones currently ending with a space on lines
with texts like the ones referenced in the review), ensuring each Scenario title
string has no trailing whitespace.

In `@tests/e2e/utils/utils.py`:
- Around line 266-276: The subprocess.run call that removes ~/.llama (inside the
try block using container_name) uses check=False so non-timeout failures are
silent; capture the CompletedProcess result (assign subprocess.run(...) to a
variable) and if result.returncode != 0 log a debug/info message including
container_name, the command run, and result.stderr/result.stdout (or at least
returncode) so failed removals are observable while still not raising; keep the
existing TimeoutExpired except branch unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 11b9840f-0d97-4f06-9634-2227f5fed4d1

📥 Commits

Reviewing files that changed from the base of the PR and between 7b4f1f0 and 5e1c59e.

📒 Files selected for processing (3)
  • tests/e2e/features/environment.py
  • tests/e2e/features/mcp.feature
  • tests/e2e/utils/utils.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/features/environment.py

- Introduced new YAML configuration files for MCP authentication methods: file, Kubernetes, and OAuth.
- Updated existing MCP configuration to include new authentication methods.
- Enhanced end-to-end tests to cover scenarios for file-based, Kubernetes, and OAuth authentication.
- Added utility functions for unregistering MCP toolgroups in the testing environment.
- Implemented new step definitions for checking response body content in tests.

Add invalid MCP token configuration and update tests

- Added a new invalid MCP token file for testing purposes.
- Updated the Docker Compose configuration to mount the invalid MCP token.
- Introduced a new YAML configuration for testing invalid MCP file authentication.
- Enhanced the test scenarios to include checks for invalid MCP file authentication.
- Updated feature files to reflect the new authentication configurations.

Add additional MCP authentication configurations and update scenario handling

- Added new configurations for invalid, Kubernetes, client, and OAuth MCP authentication methods.
- Updated scenario handling to reference the new configuration paths for Kubernetes, client, and OAuth authentication.
- Enhanced the testing environment to support the new authentication configurations.

fixed errored tests

skipped failing scenarios and added library mode configs

fixed library mode tests error

fixed black

skipped acidentally missed failing test

Refactor Llama Stack utilities and update E2E tests

- Renamed `llama_stack_shields.py` to `llama_stack_utils.py` and expanded its functionality to manage both toolgroups and shields.
- Removed the deprecated `llama_stack_tools.py` file.
- Updated E2E test scenarios to utilize the new utility functions for unregistering toolgroups and clearing Llama Stack storage.
- Enhanced feature files to include comments indicating pending fixes for skipped scenarios.

Enhance MCP feature tests and streamline Llama Stack storage clearing

- Added checks to ensure the response body does not contain 'mcp-client' in MCP feature tests.
- Simplified the `clear_llama_stack_storage` function to remove the entire `~/.llama` directory instead of specific files, improving clarity and efficiency.
- Updated comments to reflect the changes in storage clearing logic.

Remove deprecated MCP file-based authorization feature and update test list

addressed code rabbit

Add new MCP authentication configurations and update tests

- Introduced new YAML configuration files for MCP authentication methods: file, Kubernetes, and OAuth.
- Updated existing MCP configuration to include new authentication methods.
- Enhanced end-to-end tests to cover scenarios for file-based, Kubernetes, and OAuth authentication.
- Added utility functions for unregistering MCP toolgroups in the testing environment.
- Implemented new step definitions for checking response body content in tests.

fixed errored tests

fixed library mode tests error

fixed black

Refactor Llama Stack utilities and update E2E tests

- Renamed `llama_stack_shields.py` to `llama_stack_utils.py` and expanded its functionality to manage both toolgroups and shields.
- Removed the deprecated `llama_stack_tools.py` file.
- Updated E2E test scenarios to utilize the new utility functions for unregistering toolgroups and clearing Llama Stack storage.
- Enhanced feature files to include comments indicating pending fixes for skipped scenarios.

Enhance MCP feature tests and streamline Llama Stack storage clearing

- Added checks to ensure the response body does not contain 'mcp-client' in MCP feature tests.
- Simplified the `clear_llama_stack_storage` function to remove the entire `~/.llama` directory instead of specific files, improving clarity and efficiency.
- Updated comments to reflect the changes in storage clearing logic.

Remove deprecated MCP file-based authorization feature and update test list

addressed code rabbit

fixed ruff

addressed comments
Copy link
Contributor

@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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/e2e/features/environment.py (1)

229-248: Consider simplifying tag-to-config mapping with a dictionary.

The if/elif chain could be reduced to a dictionary lookup for better maintainability, though the current implementation is functionally correct.

♻️ Optional refactor using dictionary lookup
-    config_name: Optional[str] = None
-    if "MCPFileAuthConfig" in scenario.effective_tags:
-        config_name = "mcp-file-auth"
-    elif "InvalidMCPFileAuthConfig" in scenario.effective_tags:
-        config_name = "invalid-mcp-file-auth"
-    elif "MCPKubernetesAuthConfig" in scenario.effective_tags:
-        config_name = "mcp-kubernetes-auth"
-    elif "MCPClientAuthConfig" in scenario.effective_tags:
-        config_name = "mcp-client-auth"
-    elif "MCPOAuthAuthConfig" in scenario.effective_tags:
-        config_name = "mcp-oauth-auth"
+    _MCP_TAG_TO_CONFIG = {
+        "MCPFileAuthConfig": "mcp-file-auth",
+        "InvalidMCPFileAuthConfig": "invalid-mcp-file-auth",
+        "MCPKubernetesAuthConfig": "mcp-kubernetes-auth",
+        "MCPClientAuthConfig": "mcp-client-auth",
+        "MCPOAuthAuthConfig": "mcp-oauth-auth",
+    }
+    config_name: Optional[str] = None
+    for tag, name in _MCP_TAG_TO_CONFIG.items():
+        if tag in scenario.effective_tags:
+            config_name = name
+            break
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/features/environment.py` around lines 229 - 248, The if/elif chain
mapping scenario.effective_tags to config_name can be simplified by replacing it
with a dictionary lookup: build a tag->config map and set config_name =
tag_map.get(next_matching_tag) (or iterate keys to find the first tag present)
instead of the long if/elif; keep the surrounding logic that checks config_name,
calls unregister_mcp_toolgroups()/clear_llama_stack_storage(), sets
context.scenario_config via _get_config_path(config_name, mode_dir), then calls
switch_config(context.scenario_config) and
restart_container("lightspeed-stack"). Ensure you reference the existing symbols
config_name, scenario.effective_tags, _get_config_path, switch_config,
restart_container, unregister_mcp_toolgroups, clear_llama_stack_storage, and
context.scenario_config when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/e2e/features/steps/common_http.py`:
- Around line 181-187: The negated step check_response_body_does_not_contain
currently checks the raw substring against context.response.text without
performing placeholder replacement; update the function to run the incoming
substring through the same placeholder resolver used by the positive variant
(e.g., call context.replace_placeholders(substring) or the project’s placeholder
helper) before asserting it is not in context.response.text, and use the
resolved value in the assertion message as well.

---

Nitpick comments:
In `@tests/e2e/features/environment.py`:
- Around line 229-248: The if/elif chain mapping scenario.effective_tags to
config_name can be simplified by replacing it with a dictionary lookup: build a
tag->config map and set config_name = tag_map.get(next_matching_tag) (or iterate
keys to find the first tag present) instead of the long if/elif; keep the
surrounding logic that checks config_name, calls
unregister_mcp_toolgroups()/clear_llama_stack_storage(), sets
context.scenario_config via _get_config_path(config_name, mode_dir), then calls
switch_config(context.scenario_config) and
restart_container("lightspeed-stack"). Ensure you reference the existing symbols
config_name, scenario.effective_tags, _get_config_path, switch_config,
restart_container, unregister_mcp_toolgroups, clear_llama_stack_storage, and
context.scenario_config when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1a0586f4-7f52-4779-a794-08ebdc383d7d

📥 Commits

Reviewing files that changed from the base of the PR and between 5e1c59e and a589492.

📒 Files selected for processing (22)
  • docker-compose.yaml
  • docs/e2e_testing.md
  • tests/e2e/configuration/library-mode/lightspeed-stack-invalid-mcp-file-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-client-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-file-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-kubernetes-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-oauth-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-invalid-mcp-file-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-client-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-file-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-kubernetes-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-oauth-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp.yaml
  • tests/e2e/features/environment.py
  • tests/e2e/features/mcp.feature
  • tests/e2e/features/mcp_file_auth.feature
  • tests/e2e/features/steps/common_http.py
  • tests/e2e/secrets/invalid-mcp-token
  • tests/e2e/test_list.txt
  • tests/e2e/utils/llama_stack_utils.py
  • tests/e2e/utils/utils.py
💤 Files with no reviewable changes (2)
  • tests/e2e/features/mcp_file_auth.feature
  • tests/e2e/test_list.txt
🚧 Files skipped from review as they are similar to previous changes (7)
  • tests/e2e/configuration/library-mode/lightspeed-stack-invalid-mcp-file-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-client-auth.yaml
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp-kubernetes-auth.yaml
  • tests/e2e/configuration/library-mode/lightspeed-stack-mcp-kubernetes-auth.yaml
  • tests/e2e/secrets/invalid-mcp-token
  • tests/e2e/utils/utils.py
  • tests/e2e/configuration/server-mode/lightspeed-stack-mcp.yaml

Comment on lines +181 to +187
@then("The body of the response does not contain {substring}")
def check_response_body_does_not_contain(context: Context, substring: str) -> None:
"""Check that response body does not contain a substring."""
assert context.response is not None, "Request needs to be performed first"
assert (
substring not in context.response.text
), f"The response text '{context.response.text}' contains '{substring}'"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Apply placeholder replacement in the negated body assertion.

This step checks the raw substring while the positive variant resolves placeholders first. Placeholder-based scenarios can fail incorrectly.

🐛 Proposed fix
 `@then`("The body of the response does not contain {substring}")
 def check_response_body_does_not_contain(context: Context, substring: str) -> None:
     """Check that response body does not contain a substring."""
     assert context.response is not None, "Request needs to be performed first"
+    expected = replace_placeholders(context, substring)
     assert (
-        substring not in context.response.text
-    ), f"The response text '{context.response.text}' contains '{substring}'"
+        expected not in context.response.text
+    ), f"The response text '{context.response.text}' contains '{expected}'"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/features/steps/common_http.py` around lines 181 - 187, The negated
step check_response_body_does_not_contain currently checks the raw substring
against context.response.text without performing placeholder replacement; update
the function to run the incoming substring through the same placeholder resolver
used by the positive variant (e.g., call context.replace_placeholders(substring)
or the project’s placeholder helper) before asserting it is not in
context.response.text, and use the resolved value in the assertion message as
well.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants