Skip to content

fix(testing): initialize BidiComponentManager in AppTest mock runtime#14301

Merged
lukasmasuch merged 1 commit intostreamlit:developfrom
tysoncung:fix/apptest-bidi-component-registry
Mar 12, 2026
Merged

fix(testing): initialize BidiComponentManager in AppTest mock runtime#14301
lukasmasuch merged 1 commit intostreamlit:developfrom
tysoncung:fix/apptest-bidi-component-registry

Conversation

@tysoncung
Copy link
Copy Markdown
Contributor

Summary

AppTest._run() creates a MagicMock(spec=Runtime) but does not configure bidi_component_registry, so any app that uses st.components.v2 custom components crashes with:

TypeError: bad argument type for built-in operation

The crash occurs because get_bidi_component_manager() returns a MagicMock attribute instead of a real BidiComponentManager. Component registration silently no-ops on the mock, and later, when _bidi_component() tries to set protobuf string fields from MagicMock objects, the built-in protobuf C code raises the TypeError.

Fix

Initialize a real BidiComponentManager instance on the mock runtime, alongside the existing MediaFileManager and MemoryCacheStorageManager:

mock_runtime.bidi_component_registry = BidiComponentManager()

This ensures component registration and lookup work correctly during AppTest runs.

Test

Added test_v2_custom_component that registers and mounts a v2 custom component inside AppTest.from_function(), verifying no exception is raised.

Fixes #14274

AppTest._run() creates a MagicMock runtime but does not set up
bidi_component_registry, causing apps that use st.components.v2
custom components to crash with TypeError during testing.

Initialize a real BidiComponentManager on the mock runtime so that
component registration and lookup work correctly in AppTest.

Fixes streamlit#14274
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for contributing to Streamlit! 🎈

Please make sure you have read our Contributing Guide. You can find additional information about Streamlit development in the wiki.

The review process:

  1. Initial triage: A maintainer will apply labels, approve CI to run, and trigger AI-assisted reviews. Your PR may be flagged with status:needs-product-approval if the feature requires product team sign-off.

  2. Code review: A core maintainer will start reviewing your PR once:

    • It is marked as 'ready for review', not 'draft'
    • It has status:product-approved (or doesn't need it)
    • All CI checks pass
    • All AI review comments are addressed

We're receiving many contributions and have limited review bandwidth — please expect some delay. We appreciate your patience! 🙏

@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Mar 10, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@lukasmasuch lukasmasuch requested a review from Copilot March 10, 2026 21:31
@lukasmasuch lukasmasuch added change:bugfix PR contains bug fix implementation impact:users PR changes affect end users labels Mar 10, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a crash in streamlit.testing.v1.AppTest when running apps that use st.components.v2 custom components by ensuring the mock Runtime includes a real v2 component manager.

Changes:

  • Initialize mock_runtime.bidi_component_registry with a real BidiComponentManager during AppTest._run().
  • Add a regression test that registers and mounts a v2 custom component via AppTest.from_function() (issue #14274).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
lib/streamlit/testing/v1/app_test.py Seeds the AppTest mock Runtime with a real BidiComponentManager so v2 component registration/lookup works correctly.
lib/tests/streamlit/testing/app_test_test.py Adds a regression test ensuring v2 custom components can be registered and mounted in AppTest without exceptions.

@lukasmasuch lukasmasuch added the ai-review If applied to PR or issue will run AI review workflow label Mar 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Summary

This PR fixes a crash when using st.components.v2 custom components inside AppTest (issue #14274). The root cause is that AppTest._run() creates a MagicMock(spec=Runtime) but does not initialize bidi_component_registry, causing component registration to silently no-op and later raising a TypeError when protobuf string fields are set from MagicMock objects.

The fix adds a single line initializing bidi_component_registry with a real BidiComponentManager() on the mock runtime, following the established pattern used for media_file_mgr and cache_storage_manager. A regression test is included.

Files changed:

  • lib/streamlit/testing/v1/app_test.py — one import + one line to set bidi_component_registry
  • lib/tests/streamlit/testing/app_test_test.py — new test_v2_custom_component regression test

Code Quality

Consensus (3/3 reviewers agree): The change is minimal, surgical, and follows established patterns exactly. The mock runtime setup in _run() already initializes media_file_mgr and cache_storage_manager with real instances; adding bidi_component_registry mirrors this approach. The same pattern is also used in lib/tests/delta_generator_test_case.py, confirming it as the standard approach. The import placement is correct, and no maintainability or correctness issues were identified.

Test Coverage

Consensus (3/3 reviewers agree): The new test_v2_custom_component test adequately covers the regression scenario:

  • Registers a v2 custom component via st.components.v2.component()
  • Mounts the component with key and data arguments
  • Asserts no exceptions were raised with diagnostic output on failure
  • Verifies the app rendered successfully by checking at.title[0].value

The test follows existing patterns (uses AppTest.from_function, imports inside the script function, descriptive docstring with issue link). No e2e test is necessary since behavior is isolated to Python test-runtime mocking logic.

Backwards Compatibility

Consensus (3/3 reviewers agree): No breaking changes. This is purely additive — it fixes a crash for a previously non-functional scenario. Existing AppTest users and runtime codepaths remain unaffected.

Security & Risk

Consensus (3/3 reviewers agree): No security concerns. BidiComponentManager is an in-process component registry with no network, authentication, or file-serving implications in this context. The mock runtime is torn down after each run. No new dependencies or dynamic code execution are introduced. Regression risk is very low.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/testing/v1/app_test.py: Change is confined to AppTest mock runtime setup — no routing, auth, websocket, embedding, asset serving, or cross-origin changes.
    • lib/tests/streamlit/testing/app_test_test.py: New unit test only — no integration surface.
  • Suggested external_test focus areas: None
  • Confidence: High
  • Assumptions and gaps: None. The change is strictly within the test infrastructure and does not affect any server, networking, or browser-facing behavior.

Accessibility

No frontend changes are included in this PR. No accessibility concerns.

Recommendations

  1. Add return type annotation to the new test function (non-blocking, raised by 1/3 reviewers): Per lib/tests/AGENTS.md, new tests should be fully annotated. Consider changing def test_v2_custom_component(): to def test_v2_custom_component() -> None:.
  2. Optional follow-up (raised by 1/3 reviewers): Consider adding a regression test for manifest-backed v2 components (path/glob asset resolution) under AppTest, to further align AppTest behavior with full runtime initialization.

Reviewer Agreement

Area Agreement
Fix correctness 3/3 agree — fix is correct and follows established patterns
Test coverage 3/3 agree — regression test is adequate
Backwards compatibility 3/3 agree — no breaking changes
Security & risk 3/3 agree — no concerns, very low regression risk
External tests 3/3 agree — not needed
Verdict 3/3 approve

No disagreements or conflicts between reviewers. Minor differences were in optional recommendations only.

Missing Reviews

All expected models completed their reviews:

  • gpt-5.3-codex-high
  • gemini-3.1-pro
  • opus-4.6-thinking

Verdict

APPROVED: All three reviewers unanimously approve. The fix is correct, minimal, and well-tested. It follows established patterns, introduces no risk, and includes a solid regression test. The only recommendation (non-blocking) is adding a -> None return type annotation to the new test function.


This is a consolidated AI review by opus-4.6-thinking.


📋 Review by `gemini-3.1-pro`

Summary

This PR fixes a bug in AppTest where testing apps that use st.components.v2 custom components would crash with a TypeError. The fix initializes a real BidiComponentManager on the mock runtime instead of leaving it as a MagicMock, allowing component registration and lookup to work correctly during tests.

Code Quality

The code changes are clean, concise, and directly address the root cause of the issue. The initialization of BidiComponentManager in lib/streamlit/testing/v1/app_test.py (line 343) is placed appropriately alongside other mock runtime manager initializations.

Test Coverage

The PR includes a new unit test test_v2_custom_component in lib/tests/streamlit/testing/app_test_test.py (line 271) that acts as a regression test for the reported issue (#14274). The test correctly verifies that an app using a v2 custom component can be run via AppTest without raising exceptions.

Backwards Compatibility

This is a bug fix in the testing framework (AppTest) and does not introduce any breaking changes. It restores functionality for users trying to test apps with v2 custom components.

Security & Risk

No security concerns or regression risks identified. The changes are isolated to the testing framework's mock runtime setup.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/testing/v1/app_test.py: Only modifies mock runtime setup for the AppTest framework.
    • lib/tests/streamlit/testing/app_test_test.py: Adds a unit test for the AppTest framework.
  • Suggested external_test focus areas: N/A
  • Confidence: High
  • Assumptions and gaps: The changes strictly affect the local testing utility (AppTest) and have no impact on the actual Streamlit server, routing, or frontend behavior.

Accessibility

N/A - No frontend changes.

Recommendations

None. The fix is well-implemented and adequately tested.

Verdict

APPROVED: The PR successfully fixes a crash in AppTest when using v2 custom components by properly initializing the BidiComponentManager on the mock runtime, and includes a solid regression test.


This is an automated AI review by gemini-3.1-pro.

📋 Review by `gpt-5.3-codex-high`

Summary

This PR fixes an AppTest runtime-mocking gap that caused st.components.v2 custom components to crash during tests. It initializes a real BidiComponentManager on the mock runtime and adds a regression test that mounts a v2 component in AppTest.

Code Quality

The implementation is small, targeted, and follows existing patterns in the testing runtime setup.

  • lib/streamlit/testing/v1/app_test.py (import at line 25, initialization at line 343) cleanly mirrors existing mock runtime dependency initialization (media_file_mgr, cache manager).
  • lib/tests/streamlit/testing/app_test_test.py (new test at lines 271-291) is focused and readable, and includes a regression docstring linking the issue.
  • No maintainability or correctness issues were identified in the changed lines.

Test Coverage

Coverage is appropriate for this bug fix.

  • The new unit test in lib/tests/streamlit/testing/app_test_test.py exercises the exact failure path: registering and mounting a v2 component inside AppTest.from_function(...).run().
  • The assertions verify both that no exception is emitted and that normal script execution continues (st.title output check).
  • No e2e test appears necessary for this change because behavior is isolated to Python test-runtime mocking logic.

Backwards Compatibility

No breaking changes identified.

  • Change is internal to AppTest setup behavior and only makes previously failing test scenarios work.
  • Existing users of AppTest and runtime codepaths should remain compatible.

Security & Risk

No security concerns found.

  • No changes to auth/session handling, server routes, websocket transport, file serving, cookies, CORS/CSP, or external networking.
  • No new dependency additions or dynamic code execution risk introduced.
  • Regression risk is low because the change only injects a concrete manager instance into an existing mock runtime lifecycle.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/testing/v1/app_test.py: adds only in-process test runtime mock initialization for bidi_component_registry.
    • lib/tests/streamlit/testing/app_test_test.py: adds Python unit regression test only; no routing/auth/websocket/embed/storage/policy changes.
  • Suggested external_test focus areas:
    • None required for this PR.
  • Confidence: High
  • Assumptions and gaps: Assessment is based on the PR diff (2 Python files) and assumes no hidden runtime/config changes outside this branch.

Accessibility

No frontend/UI code changed, so there are no new accessibility impacts in this PR.

Recommendations

  1. No blocking changes required.
  2. Optional follow-up: add a second regression test for manifest-backed v2 components (path/glob asset resolution) under AppTest, to further align AppTest behavior with full runtime initialization.

Verdict

APPROVED: The fix is correct, low risk, and sufficiently covered by a targeted regression test.


This is an automated AI review by gpt-5.3-codex-high. Please verify the feedback and use your judgment.

📋 Review by `opus-4.6-thinking`

Summary

This PR fixes a crash when using st.components.v2 custom components inside AppTest. The root cause is that AppTest._run() creates a MagicMock(spec=Runtime) but does not initialize bidi_component_registry, so when get_bidi_component_manager() accesses Runtime.instance().bidi_component_registry, it returns a MagicMock attribute instead of a real BidiComponentManager. Component registration silently no-ops on the mock, and later, _bidi_component() tries to set protobuf string fields from MagicMock objects, causing a TypeError.

The fix is a single line that initializes bidi_component_registry with a real BidiComponentManager() on the mock runtime, following the same pattern used for media_file_mgr and cache_storage_manager. A regression test is added.

Files changed:

  • lib/streamlit/testing/v1/app_test.py — one import + one line to set bidi_component_registry
  • lib/tests/streamlit/testing/app_test_test.py — new test_v2_custom_component regression test

Code Quality

The change is minimal, surgical, and follows the established pattern exactly. The mock runtime setup in _run() already initializes media_file_mgr and cache_storage_manager with real instances; this adds bidi_component_registry in the same fashion. The same pattern is also used in lib/tests/delta_generator_test_case.py (line 88), confirming this is the standard approach.

The import of BidiComponentManager is correctly placed at the top of the file alongside related imports.

Minor note: The new test function test_v2_custom_component lacks a -> None return type annotation. While many existing tests in this file also lack annotations, the lib/tests/AGENTS.md guideline states "New tests should be fully annotated with types." This is a very minor nit — see Recommendations.

Test Coverage

The new test test_v2_custom_component directly covers the regression scenario from issue #14274:

  • It registers a v2 custom component via st.components.v2.component()
  • It mounts the component with key and data arguments
  • It asserts no exceptions were raised (assert not at.exception)
  • It verifies the app rendered successfully by checking at.title[0].value

The test follows existing patterns in the file (uses AppTest.from_function, imports inside the script function as required, includes a descriptive docstring with issue link). The assertion assert not at.exception, [e.message for e in at.exception] is a good pattern that provides diagnostic output on failure.

The test adequately covers the fix. No additional unit tests are needed since the fix is a single-line initialization.

Backwards Compatibility

No backwards compatibility concerns. This is purely additive — it fixes a crash when v2 custom components are used with AppTest, which previously did not work at all. No existing APIs are modified, no signatures change, and no behavior changes for apps that don't use v2 custom components.

Security & Risk

No security concerns:

  • BidiComponentManager is an in-process component registry with no network, authentication, or file-serving implications in this context.
  • The mock runtime is only used during AppTest execution and is torn down after each run (line 379: Runtime._instance = None).
  • No new dependencies, external requests, or dynamic code execution are introduced.

Regression risk: Very low. The BidiComponentManager() constructor with default arguments creates an empty registry with default sub-components, which is safe and side-effect-free.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/testing/v1/app_test.py: Change is confined to AppTest mock runtime setup — no routing, auth, websocket, embedding, asset serving, or cross-origin changes.
    • lib/tests/streamlit/testing/app_test_test.py: New unit test only — no integration surface.
  • Suggested external_test focus areas: None
  • Confidence: High
  • Assumptions and gaps: None. The change is strictly within the test infrastructure and does not affect any server, networking, or browser-facing behavior.

Accessibility

No frontend changes are included in this PR. No accessibility concerns.

Recommendations

  1. Add return type annotation to the new test function (very minor): Per lib/tests/AGENTS.md, new tests should be fully annotated. Consider changing def test_v2_custom_component(): to def test_v2_custom_component() -> None: for consistency with the guideline.

Verdict

APPROVED: Clean, minimal, and well-tested fix for a real crash when using v2 custom components in AppTest. The fix follows established patterns, introduces no risk, and includes a good regression test.


This is an automated AI review by opus-4.6-thinking.

Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch left a comment

Choose a reason for hiding this comment

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

LGTM 👍 Thanks for the contribution

@lukasmasuch lukasmasuch merged commit 791585a into streamlit:develop Mar 12, 2026
80 of 82 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review If applied to PR or issue will run AI review workflow change:bugfix PR contains bug fix implementation impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AppTest crashes with TypeError when running apps that use st.components.v2 custom components

3 participants