Files
ComfyAssets-ComfyUI_PromptM…/tests/js/gallery-review.test.js

89 lines
4.0 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const vm = require('node:vm');
const ImageHelpers = require('../../web/js/image-helpers.js');
function deferred() {
let resolve;
const promise = new Promise(yes => { resolve = yes; });
return { promise, resolve };
}
function fixture() {
const elements = new Map();
const requests = [];
const document = { addEventListener() {}, getElementById(id) {
if (!elements.has(id)) elements.set(id, {});
return elements.get(id);
} };
const context = vm.createContext({ document, window: {}, ImageHelpers,
escapeHtml: value => value, console: { error() {} },
ApiClient: { resolveUrl: value => value, fetchUrl: (url, options) => {
const request = deferred();
requests.push({ url, body: JSON.parse(options.body), ...request });
return request.promise;
} },
});
const Manager = vm.runInContext(fs.readFileSync(path.join(__dirname, '../../web/js/gallery.js'), 'utf8') + '\nGalleryManager;', context, { filename: path.join(__dirname, '../../web/js/gallery.js') });
const manager = Object.create(Manager.prototype);
const notifications = [];
Object.assign(manager, { autoTagState: { reviewImages: [
{ id: 'digest', path: 'same.png', root_index: 1, url: '/same.png' },
{ id: 'other', path: 'next.png', root_index: 0, url: '/next.png' },
], reviewIndex: 0, currentTags: [], modelType: 'gguf' },
renderReviewTags() {}, showNotification: (...args) => notifications.push(args), hideModal() {}, loadImages() {},
});
const reply = (index, data) => requests[index].resolve({ json: async () => data });
return { manager, requests, reply, notifications };
}
test('gallery review retains root identity and applies tags with the returned prompt ID', async () => {
const { manager, requests, reply } = fixture();
const load = manager.loadNextReviewImage();
assert.equal(requests[0].body.root_index, 1);
reply(0, { success: true, prompt_id: 42, tags: ['smile'] });
await load;
manager.loadNextReviewImage = () => {};
const apply = manager.applyReviewTags();
assert.deepEqual(requests[1].body, { prompt_id: 42, tags: ['smile'] });
reply(1, { success: true });
await apply;
});
test('unlinked images do not submit an invalid apply request or advance', async () => {
const { manager, requests, reply } = fixture();
const load = manager.loadNextReviewImage();
reply(0, { success: true, prompt_id: null, tags: ['smile'] });
await load;
const apply = manager.applyReviewTags();
if (requests[1]) reply(1, { success: false, error: "Unexpected apply" });
await apply;
assert.equal(requests.length, 1);
assert.equal(manager.autoTagState.reviewIndex, 0);
});
test('a failed apply keeps the current image available for retry', async () => {
const { manager, requests, reply } = fixture();
const load = manager.loadNextReviewImage();
reply(0, { success: true, prompt_id: 42, tags: ['smile'] });
await load;
const apply = manager.applyReviewTags();
reply(1, { success: false, error: 'Try again' });
await apply;
assert.equal(manager.autoTagState.reviewIndex, 0);
assert.equal(requests.length, 2);
});
test('late generation responses cannot restore tags from a skipped or closed image', async () => {
const { manager, reply } = fixture();
const first = manager.loadNextReviewImage();
manager.autoTagState.reviewIndex = 1;
const second = manager.loadNextReviewImage();
reply(1, { success: true, prompt_id: 2, tags: ['current'] });
await second;
reply(0, { success: true, prompt_id: 1, tags: ['stale'] });
await first;
assert.deepEqual(Array.from(manager.autoTagState.currentTags), ['current']);
const third = manager.loadNextReviewImage();
manager.cancelReview();
reply(2, { success: true, prompt_id: 2, tags: ['closed'] });
await third;
assert.equal(manager.autoTagState.currentTags.length, 0);
});