ComfyUI-Manager/tests/glob/test_installed_api_original_case.py
Dr.Lt.Data 43647249cf refactor: remove package-level caching to support dynamic installation
Remove package-level caching in cnr_utils and node_package modules to enable
proper dynamic custom node installation and version switching without ComfyUI
server restarts.

Key Changes:
- Remove @lru_cache decorators from version-sensitive functions
- Remove cached_property from NodePackage for dynamic state updates
- Add comprehensive test suite with parallel execution support
- Implement version switching tests (CNR ↔ Nightly)
- Add case sensitivity integration tests
- Improve error handling and logging

API Priority Rules (manager_core.py:1801):
- Enabled-Priority: Show only enabled version when both exist
- CNR-Priority: Show only CNR when both CNR and Nightly are disabled
- Prevents duplicate package entries in /v2/customnode/installed API
- Cross-match using cnr_id and aux_id for CNR ↔ Nightly detection

Test Infrastructure:
- 8 test files with 59 comprehensive test cases
- Parallel test execution across 5 isolated environments
- Automated test scripts with environment setup
- Configurable timeout (60 minutes default)
- Support for both master and dr-support-pip-cm branches

Bug Fixes:
- Fix COMFYUI_CUSTOM_NODES_PATH environment variable export
- Resolve test fixture regression with module-level variables
- Fix import timing issues in test configuration
- Register pytest integration marker to eliminate warnings
- Fix POSIX compliance in shell scripts (((var++)) → $((var + 1)))

Documentation:
- CNR_VERSION_MANAGEMENT_DESIGN.md v1.0 → v1.1 with API priority rules
- Add test guides and execution documentation (TESTING_PROMPT.md)
- Add security-enhanced installation guide
- Create CLI migration guides and references
- Document package version management

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 09:07:09 +09:00

107 lines
4.2 KiB
Python

"""
Test that /installed API preserves original case in cnr_id.
This test verifies that the `/v2/customnode/installed` API:
1. Returns cnr_id with original case (e.g., "ComfyUI_SigmoidOffsetScheduler")
2. Does NOT include an "original_name" field
3. Maintains frontend compatibility with PyPI baseline
This matches the PyPI 4.0.3b1 baseline behavior.
"""
import requests
def test_installed_api_preserves_original_case(server_url):
"""Test that /installed API returns cnr_id with original case."""
response = requests.get(f"{server_url}/v2/customnode/installed")
assert response.status_code == 200
installed = response.json()
assert len(installed) > 0, "Should have at least one installed package"
# Check each installed package
for package_key, package_info in installed.items():
# Verify cnr_id field exists
assert 'cnr_id' in package_info, f"Package {package_key} should have cnr_id field"
cnr_id = package_info['cnr_id']
# Verify cnr_id preserves original case (contains uppercase letters)
# For ComfyUI_SigmoidOffsetScheduler, it should NOT be all lowercase
if 'comfyui' in cnr_id.lower():
# If it contains "comfyui", it should have uppercase letters
assert cnr_id != cnr_id.lower(), \
f"cnr_id '{cnr_id}' should preserve original case, not be normalized to lowercase"
# Verify no original_name field in response (PyPI baseline)
assert 'original_name' not in package_info, \
f"Package {package_key} should NOT have original_name field for frontend compatibility"
def test_cnr_package_original_case(server_url):
"""Test specifically that CNR packages preserve original case."""
response = requests.get(f"{server_url}/v2/customnode/installed")
assert response.status_code == 200
installed = response.json()
# Find a CNR package (has version like "1.0.1")
cnr_packages = {k: v for k, v in installed.items()
if v.get('ver', '').count('.') >= 2}
assert len(cnr_packages) > 0, "Should have at least one CNR package for testing"
for package_key, package_info in cnr_packages.items():
cnr_id = package_info['cnr_id']
# CNR packages should have original case preserved
# Example: "ComfyUI_SigmoidOffsetScheduler" not "comfyui_sigmoidoffsetscheduler"
assert any(c.isupper() for c in cnr_id), \
f"CNR package cnr_id '{cnr_id}' should contain uppercase letters"
def test_nightly_package_original_case(server_url):
"""Test specifically that Nightly packages preserve original case."""
response = requests.get(f"{server_url}/v2/customnode/installed")
assert response.status_code == 200
installed = response.json()
# Find a Nightly package (key contains "@nightly")
nightly_packages = {k: v for k, v in installed.items() if '@nightly' in k}
if len(nightly_packages) == 0:
# No nightly packages installed, skip test
return
for package_key, package_info in nightly_packages.items():
cnr_id = package_info['cnr_id']
# Nightly packages should also have original case preserved
# Example: "ComfyUI_SigmoidOffsetScheduler" not "comfyui_sigmoidoffsetscheduler"
assert any(c.isupper() for c in cnr_id), \
f"Nightly package cnr_id '{cnr_id}' should contain uppercase letters"
def test_api_response_structure_matches_pypi(server_url):
"""Test that API response structure matches PyPI 4.0.3b1 baseline."""
response = requests.get(f"{server_url}/v2/customnode/installed")
assert response.status_code == 200
installed = response.json()
# Skip test if no packages installed (may happen in parallel environments)
if len(installed) == 0:
pytest.skip("No packages installed - skipping structure validation test")
# Check first package structure
first_package = next(iter(installed.values()))
# Required fields from PyPI baseline
required_fields = {'ver', 'cnr_id', 'aux_id', 'enabled'}
actual_fields = set(first_package.keys())
assert required_fields == actual_fields, \
f"API response fields should match PyPI baseline: {required_fields}, got: {actual_fields}"