Files
ComfyUI-Lora-Manager/tests/frontend/managers/loraSyntaxUtils.test.js
Will Miao 39586f4a20 feat: add LoRA syntax utilities and comprehensive test suite, fixes #600
- Implement core LoRA syntax manipulation functions including:
  - applyLoraValuesToText for updating LoRA strengths and clip values
  - normalizeStrengthValue for consistent numeric formatting
  - shouldIncludeClipStrength for clip strength inclusion logic
  - cleanupLoraSyntax for text normalization
  - debounce utility for input handling

- Add comprehensive test suite covering all utility functions
- Include edge cases for clip strength handling, numeric formatting, and syntax cleanup
- Support both basic and expanded LoRA syntax formats with proper value preservation
- Enable debounced input synchronization for better performance

The utilities provide robust handling of LoRA syntax patterns while maintaining compatibility with existing ComfyUI workflows.
2025-10-29 22:13:54 +08:00

114 lines
3.2 KiB
JavaScript

import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { applyLoraValuesToText, debounce, __testables } from "../../../web/comfyui/lora_syntax_utils.js";
const { normalizeStrengthValue, shouldIncludeClipStrength, cleanupLoraSyntax } = __testables();
describe("applyLoraValuesToText", () => {
it("updates existing LoRA strengths", () => {
const original = "<lora:StrengthTest:0.50>";
const result = applyLoraValuesToText(original, [
{ name: "StrengthTest", strength: 0.8 }
]);
expect(result).toBe("<lora:StrengthTest:0.80>");
});
it("updates clip strength while preserving syntax", () => {
const original = "<lora:ClipTest:1.00:0.50>";
const result = applyLoraValuesToText(original, [
{ name: "ClipTest", strength: 1, clipStrength: 0.75 }
]);
expect(result).toBe("<lora:ClipTest:1.00:0.75>");
});
it("appends missing LoRAs to the input text", () => {
const original = "<lora:Present:0.70>";
const result = applyLoraValuesToText(original, [
{ name: "Present", strength: 0.7 },
{ name: "Additional", strength: 0.4 }
]);
expect(result).toBe("<lora:Present:0.70> <lora:Additional:0.40>");
});
it("keeps clip entry when expanded even if values match", () => {
const original = "<lora:Expanded:1.00>";
const result = applyLoraValuesToText(original, [
{ name: "Expanded", strength: 1, clipStrength: 1, expanded: true }
]);
expect(result).toBe("<lora:Expanded:1.00:1.00>");
});
});
describe("normalizeStrengthValue", () => {
it("defaults to 1.00 for non-numeric input", () => {
expect(normalizeStrengthValue("foo")).toBe("1.00");
});
it("formats numeric input to two decimals", () => {
expect(normalizeStrengthValue(0.3333)).toBe("0.33");
});
});
describe("shouldIncludeClipStrength", () => {
it("returns true when clip differs", () => {
expect(
shouldIncludeClipStrength({ strength: 1, clipStrength: 0.8 }, undefined)
).toBe(true);
});
it("returns true when expanded despite equal values", () => {
expect(
shouldIncludeClipStrength({ strength: 1, clipStrength: 1, expanded: true }, undefined)
).toBe(true);
});
it("falls back to existing syntax when clip missing", () => {
expect(shouldIncludeClipStrength({}, "0.7")).toBe(true);
});
});
describe("cleanupLoraSyntax", () => {
it("collapses whitespace and stray commas", () => {
expect(cleanupLoraSyntax(" <lora:A:1.00> , ," )).toBe("<lora:A:1.00>");
});
});
describe("debounce", () => {
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
it("delays execution and keeps latest arguments", () => {
const spy = vi.fn();
const debounced = debounce(spy, 100);
debounced("first");
debounced("second");
expect(spy).not.toHaveBeenCalled();
vi.advanceTimersByTime(100);
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith("second");
});
it("flushes pending calls immediately", () => {
const spy = vi.fn();
const debounced = debounce(spy, 200);
debounced("queued");
debounced.flush();
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith("queued");
});
});