fix: Fix i18n collection by handling Vue/CSS imports in Node.js

The collect-i18n Playwright tests were failing because Babel was trying to
parse Vue and CSS files as JavaScript when importing modules in Node.js.

Changes:
- Add Node.js ES module loader to stub Vue components and CSS imports
- Extend litegraph preprocessing to also handle CSS imports and declare keywords in src/scripts
- Simplify ComfyNodeDefImpl usage in i18n collection to avoid Vue dependency chains
- Add mock dialogService to bypass Vue component imports

The loader intercepts .vue and .css file imports and returns appropriate stubs,
while the preprocessing comments out CSS imports in TypeScript files to prevent
Babel parsing errors.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
snomiao
2025-09-12 04:16:02 +00:00
parent 614257a3b1
commit 7444c05564
6 changed files with 186 additions and 22 deletions

View File

@@ -2,10 +2,38 @@ import * as fs from 'fs'
import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage'
import type { ComfyNodeDef } from '../src/schemas/nodeDefSchema'
import type { ComfyApi } from '../src/scripts/api'
import { ComfyNodeDefImpl } from '../src/stores/nodeDefStore'
import { normalizeI18nKey } from '../src/utils/formatUtil'
// Simple NodeDef wrapper for i18n collection
// Avoids importing ComfyNodeDefImpl which has Vue dependencies
class SimpleNodeDef {
constructor(public readonly def: ComfyNodeDef) {}
get name() { return this.def.name }
get display_name() { return this.def.display_name }
get inputs() {
// Simple transformation - just get the input specs
const inputs: Record<string, any> = {}
if (this.def.input?.required) {
Object.entries(this.def.input.required).forEach(([key, spec]) => {
inputs[key] = { name: key, type: spec[0] }
})
}
if (this.def.input?.optional) {
Object.entries(this.def.input.optional).forEach(([key, spec]) => {
inputs[key] = { name: key, type: spec[0] }
})
}
return inputs
}
get outputs() {
return (this.def.output || []).map((type, index) => ({
type,
name: this.def.output_name?.[index] || ''
}))
}
}
const localePath = './src/locales/en/main.json'
const nodeDefsPath = './src/locales/en/nodeDefs.json'
@@ -17,17 +45,17 @@ test('collect-i18n-node-defs', async ({ comfyPage }) => {
})
})
const nodeDefs: ComfyNodeDefImpl[] = (
const nodeDefs: SimpleNodeDef[] = (
Object.values(
await comfyPage.page.evaluate(async () => {
const api = window['app'].api as ComfyApi
const api = window['app'].api as any
return await api.getNodeDefs()
})
) as ComfyNodeDef[]
)
// Ignore DevTools nodes (used for internal testing)
.filter((def) => !def.name.startsWith('DevTools'))
.map((def) => new ComfyNodeDefImpl(def))
.map((def) => new SimpleNodeDef(def))
console.log(`Collected ${nodeDefs.length} node definitions`)

View File

@@ -0,0 +1,26 @@
/**
* Mock dialogService for i18n collection
* This avoids importing Vue components during Node.js execution
*/
export const useDialogService = () => {
return {
showLoadWorkflowWarning: () => {},
showMissingModelsWarning: () => {},
showSettingsDialog: () => {},
showAboutDialog: () => {},
showExecutionErrorDialog: () => {},
showTemplateWorkflowsDialog: () => {},
showManagerDialog: () => {},
showManagerProgressDialog: () => {},
showErrorDialog: () => {},
showApiNodesSignInDialog: () => Promise.resolve(false),
showSignInDialog: () => Promise.resolve(false),
showUpdatePasswordDialog: () => Promise.resolve(false),
showConfirmationDialog: () => Promise.resolve(false),
showNodeConflictDialog: () => Promise.resolve(false),
showPromptDialog: () => Promise.resolve(''),
showDataManagementDialog: () => {},
showTopUpCreditsDialog: () => Promise.resolve(false)
}
}