mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-08-29 17:01:26 -03:00
fix(recipes): distinguish unobtainable LoRAs in recipe status and skip them in syntax
The recipe card pill counted LoRAs deleted from the source (isDeleted) as available, showing a green 'ready 2/2' for recipes that cannot be fully reproduced. LoRAs with an unresolvable hash (hashInvalid) were counted as missing/downloadable even though downloads always fail, and recipe syntax generation emitted broken tokens for them. - Four-state status on RecipeCard pill and RecipeTab badge: ready (all in library), missing (downloadable, red, keeps the action cue), partial (unobtainable entries skipped when used, amber, fa-circle-minus), unavailable (nothing usable, gray, fa-ban) - Pill numerator is now the real in-library count; tooltips spell out missing vs unavailable (deleted from source or unresolvable hash) - get_recipe_syntax_tokens skips hashInvalid entries like deleted ones instead of emitting tokens pointing at nonexistent files - Bulk missing-download manager and recipe context menu exclude hashInvalid LoRAs, matching the modal's per-item download block - New locale keys loraStatus.missingAndUnavailable/partial/noneUsable, translated for all 9 non-en locales
This commit is contained in:
@@ -130,14 +130,61 @@ describe('RecipeCard LoRA status pill', () => {
|
||||
expect(card.element.querySelector('.lora-count.missing')).toBeNull();
|
||||
});
|
||||
|
||||
it('does not count deleted LoRAs as missing', async () => {
|
||||
it('marks deleted-from-source LoRAs as partial instead of ready', async () => {
|
||||
const card = await createCard([
|
||||
{ name: 'a', inLibrary: true },
|
||||
{ name: 'b', inLibrary: false, isDeleted: true },
|
||||
]);
|
||||
|
||||
expect(card.element.querySelector('.lora-count.missing')).toBeNull();
|
||||
expect(card.element.querySelector('.lora-count.ready')).not.toBeNull();
|
||||
expect(card.element.querySelector('.lora-count.ready')).toBeNull();
|
||||
|
||||
const pill = card.element.querySelector('.lora-count.partial');
|
||||
expect(pill).not.toBeNull();
|
||||
expect(pill.querySelector('.fa-circle-minus')).not.toBeNull();
|
||||
expect(pill.textContent).toContain('1/2');
|
||||
expect(pill.title).toBe('1 of 2 LoRAs unavailable (deleted from source or unresolvable hash) - skipped when recipe is used');
|
||||
});
|
||||
|
||||
it('treats an unresolvable hash as unobtainable, not missing', async () => {
|
||||
const card = await createCard([
|
||||
{ name: 'a', inLibrary: true },
|
||||
{ name: 'b', inLibrary: false, hashInvalid: true },
|
||||
]);
|
||||
|
||||
expect(card.element.querySelector('.lora-count.missing')).toBeNull();
|
||||
|
||||
const pill = card.element.querySelector('.lora-count.partial');
|
||||
expect(pill).not.toBeNull();
|
||||
expect(pill.textContent).toContain('1/2');
|
||||
});
|
||||
|
||||
it('shows 0/n unavailable when every LoRA is deleted and none is in the library', async () => {
|
||||
const card = await createCard([
|
||||
{ name: 'a', inLibrary: false, isDeleted: true },
|
||||
{ name: 'b', inLibrary: false, isDeleted: true },
|
||||
]);
|
||||
|
||||
const pill = card.element.querySelector('.lora-count.unavailable');
|
||||
expect(pill).not.toBeNull();
|
||||
expect(pill.querySelector('.fa-ban')).not.toBeNull();
|
||||
expect(pill.textContent).toContain('0/2');
|
||||
expect(pill.title).toBe('No usable LoRAs - 2 of 2 deleted from source or unresolvable hash');
|
||||
expect(card.element.querySelector('.lora-count.ready')).toBeNull();
|
||||
});
|
||||
|
||||
it('keeps the actionable missing state when LoRAs are both missing and deleted', async () => {
|
||||
const card = await createCard([
|
||||
{ name: 'a', inLibrary: true },
|
||||
{ name: 'b', inLibrary: false },
|
||||
{ name: 'c', inLibrary: false, isDeleted: true },
|
||||
]);
|
||||
|
||||
const pill = card.element.querySelector('.lora-count.missing');
|
||||
expect(pill).not.toBeNull();
|
||||
expect(pill.textContent).toContain('1/3');
|
||||
expect(pill.title).toBe('1 of 3 LoRAs missing, 1 unavailable (deleted from source or unresolvable hash)');
|
||||
expect(card.element.querySelector('.lora-count.partial')).toBeNull();
|
||||
});
|
||||
|
||||
it('shows a neutral layers icon with a bare 0 when the recipe has no LoRAs', async () => {
|
||||
|
||||
Reference in New Issue
Block a user