tests.test_plugin_update_detection module

Which manifest’s version the Claude Code CLI reads to detect an update.

Two manifests carry a version: the marketplace entry, and the plugin’s own .claude-plugin/plugin.json. The release freeze stamps both, so the plugin ships correctly whichever one a client reads. The docs state which one the CLI reads, and this is what keeps that statement honest.

Measured against Claude Code 2.1.274: the CLI compares plugin.json and ignores the catalog entry, for a path source and a git-subdir source alike. The Desktop app, which the docs also cover, is out of reach of any test here.

Caution

This measures a behavior Anthropic can change without a version bump, so a failure here is a signal to re-read the docs page, not a bug in this repository.

The scene is built under tmp_path with its own CLAUDE_CONFIG_DIR, and the plugin’s remote is a file:// URL onto a second scratch repository, so parallel workers cannot collide. Nothing leaves the machine either: the egress fixture turns off the CLI’s own traffic and refuses whatever is left.

tests.test_plugin_update_detection.TIMEOUT = 120

Seconds any one CLI call may take before the probe fails instead of hanging.

tests.test_plugin_update_detection.OFFLINE_SWITCH = 'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC'

The CLI’s own setting for telemetry, error reports and update checks.

Measured against Claude Code 2.1.284: each plugin command that changes something asks for api.anthropic.com:443 once, and asks for nothing with this variable set.

tests.test_plugin_update_detection.PROXY_VARIABLES = ('HTTP_PROXY', 'HTTPS_PROXY', 'ALL_PROXY')

The variables the CLI reads to find its way out, in upper case.

tests.test_plugin_update_detection.egress(monkeypatch: pytest.MonkeyPatch) → Iterator[list[str]][source]

Keep the CLI on this machine, and collect what it still asks to reach.

The suite runs offline, and tests/conftest.py refuses every unmocked call the Python side makes. The CLI is a child process with a client of its own, which none of those stubs reach, so it gets two answers of its own. OFFLINE_SWITCH stops the calls at their source. A proxy that forwards nothing takes whatever the switch does not cover, and keeps each request line for the test to assert on.

A sandbox can refuse the bind on the loopback. The test is then skipped: without the proxy, nothing proves that the CLI stays on this machine.

Return type:

Iterator[list[str]]

Returns:

The request line of every call the proxy refused.

tests.test_plugin_update_detection.test_cli_update_detection_reads_the_plugin_manifest(tmp_path, egress)[source]

Bump each version on its own and see which one the CLI reacts to.

The four cases are one test rather than four parametrized ones because two of them are controls for the other two: a run where the controls misbehave says nothing about the question, and splitting them would let that run report a verdict anyway.

Return type:

None

tests.test_plugin_update_detection.test_egress_skips_when_the_loopback_refuses_a_bind(request, monkeypatch)[source]

A bind that the sandbox refuses skips the test, with the error as reason.

Any other error of the bind still fails: only PermissionError says that the machine forbids the proxy.

Return type:

None