Files

75 lines
2.6 KiB
JavaScript

import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import test from 'node:test';
const resolverSource = await readFile(
new URL('../web/resolver.js', import.meta.url),
'utf8'
);
const modelResolverSource = await readFile(
new URL('../web/resolver/model_resolver.js', import.meta.url),
'utf8'
);
test('frontend entrypoint registers the ComfyUI extension contract', () => {
assert.match(
resolverSource,
/import\s+\{\s*app\s*\}\s+from\s+["']\.\.\/\.\.\/\.\.\/scripts\/app\.js["']/
);
assert.match(resolverSource, /registerGlobalHelpers\(\);/);
assert.match(resolverSource, /const modelResolver = new ModelResolverClass\(\);/);
assert.match(resolverSource, /app\.registerExtension\(\{/);
assert.match(resolverSource, /name:\s*["']Model Resolver["']/);
assert.match(
modelResolverSource,
/import\s+\{\s*isSidebarButtonActive\s*\}\s+from\s+["']\.\/utils\/dom_patch_utils\.js["']/
);
assert.match(
modelResolverSource,
/import\s+\{\s*fetchJson\s+as\s+fetchJsonRequest\s*\}\s+from\s+["']\.\/utils\/api_client\.js["']/
);
assert.match(
modelResolverSource,
/fetchJsonRequest\(\s*["']\/model_resolver\/workflow-model-hashes["']/
);
assert.match(modelResolverSource, /throwOnHttpError:\s*false/);
assert.doesNotMatch(
modelResolverSource,
/api\.fetchApi\(\s*["']\/model_resolver\/workflow-model-hashes["']/
);
assert.match(resolverSource, /id:\s*MODEL_RESOLVER_OPEN_COMMAND_ID/);
assert.match(resolverSource, /function:\s*\(\)\s*=>\s*modelResolver\.activateResolverButton\(\)/);
assert.match(resolverSource, /keybindings:\s*\[\s*MODEL_RESOLVER_OPEN_DEFAULT_KEYBINDING/);
const hookPatterns = {
setup: /\bsetup\s*:/,
beforeRegisterNodeDef: /\bbeforeRegisterNodeDef\s*\(/,
nodeCreated: /\bnodeCreated\s*\(/,
loadedGraphNode: /\bloadedGraphNode\s*\(/,
afterConfigureGraph: /\bafterConfigureGraph\s*\(/,
};
for (const [hook, pattern] of Object.entries(hookPatterns)) {
assert.match(
resolverSource,
pattern,
`expected ComfyUI lifecycle hook: ${hook}`
);
}
assert.equal(
(resolverSource.match(/modelResolver\.configureNodeContextMenu\(node\?\.constructor\);/g) || []).length,
2,
'dynamically created and loaded node types must receive the widget-change hook'
);
assert.match(
resolverSource,
/modelResolver\.dialog\?\.scheduleActiveWorkflowRefresh\?\.\('node-created'\)/,
'new nodes must notify the live workflow refresh mechanism'
);
assert.match(
modelResolverSource,
/configureWorkflowNodeLifecycle\(node\)/,
'workflow nodes must receive removal tracking'
);
});