Files
ComfyUI-Lora-Manager/tests/nodes/test_lora_cycler.py
T
Will Miao c16de68640 test: make the backend suite pass on Windows
The new informational Windows job surfaced 91 failures: four real bugs (fixed in
the previous two commits) and a long tail of POSIX assumptions in the tests
themselves. None of them assert behaviour that differs on Windows, so they are
fixed rather than skipped wherever the behaviour is the same:

* Path spelling: expectations built with `str(tmp_path)` are compared through an
  identity helper (`normalize_root_identity`) or the platform's separator, since
  the code hands out forward-slashed business paths while `str()` is native.
* Root labels: `_root_display_labels` prefixes the drive on Windows ("C: loras"),
  so label assertions compare the final path component or derive the expected
  label from the same helper.
* `~` expansion reads USERPROFILE (ntpath), not HOME; timer granularity rounds
  0.1s down; a case-only rename counts as "already named" via `os.path.normcase`.
* Genuinely POSIX-only strategies are skipped with a reason instead of failing:
  the headless clipboard fallback, dbus file-manager selection, xdg-open, and
  the case-fold index test that simulates a case-sensitive filesystem.
2026-10-12 11:35:33 +08:00

111 lines
2.8 KiB
Python

"""Tests for preset strength behavior in LoraCyclerLM."""
from unittest.mock import AsyncMock
import pytest
from py.nodes.lora_cycler import LoraCyclerLM
from py.services import service_registry
import os
@pytest.fixture
def cycler_node():
return LoraCyclerLM()
@pytest.fixture
def cycler_config():
return {
"current_index": 1,
"model_strength": 0.8,
"clip_strength": 0.6,
"use_same_clip_strength": False,
"use_preset_strength": True,
"preset_strength_scale": 1.5,
"include_no_lora": False,
}
@pytest.mark.asyncio
async def test_cycler_uses_scaled_preset_strength_when_available(
cycler_node, cycler_config, mock_scanner, monkeypatch
):
monkeypatch.setattr(
service_registry.ServiceRegistry,
"get_lora_scanner",
AsyncMock(return_value=mock_scanner),
)
mock_scanner._cache.raw_data = [
{
"file_name": "preset_lora.safetensors",
"file_path": "/models/loras/preset_lora.safetensors",
"folder": "",
"usage_tips": '{"strength": 0.7, "clipStrength": 0.5}',
}
]
result = await cycler_node.cycle(cycler_config)
assert result["result"][0] == [
("/models/loras/preset_lora.safetensors".replace("/", os.sep), 1.05, 0.75)
]
@pytest.mark.asyncio
async def test_cycler_falls_back_to_manual_strength_when_preset_missing(
cycler_node, cycler_config, mock_scanner, monkeypatch
):
monkeypatch.setattr(
service_registry.ServiceRegistry,
"get_lora_scanner",
AsyncMock(return_value=mock_scanner),
)
mock_scanner._cache.raw_data = [
{
"file_name": "manual_lora.safetensors",
"file_path": "/models/loras/manual_lora.safetensors",
"folder": "",
"usage_tips": "",
}
]
result = await cycler_node.cycle(cycler_config)
assert result["result"][0] == [
("/models/loras/manual_lora.safetensors".replace("/", os.sep), 0.8, 0.6)
]
@pytest.mark.asyncio
async def test_cycler_syncs_clip_to_model_when_same_clip_strength_enabled(
cycler_node, cycler_config, mock_scanner, monkeypatch
):
monkeypatch.setattr(
service_registry.ServiceRegistry,
"get_lora_scanner",
AsyncMock(return_value=mock_scanner),
)
mock_scanner._cache.raw_data = [
{
"file_name": "preset_lora.safetensors",
"file_path": "/models/loras/preset_lora.safetensors",
"folder": "",
"usage_tips": '{"strength": 0.7, "clipStrength": 0.3}',
}
]
result = await cycler_node.cycle(
{
**cycler_config,
"use_same_clip_strength": True,
}
)
assert result["result"][0] == [
("/models/loras/preset_lora.safetensors".replace("/", os.sep), 1.05, 1.05)
]