Compare commits

...

2 Commits

Author SHA1 Message Date
snomiao
dae586533f [fix] Move i18n tests to separate config to avoid CI conflicts 2025-08-31 15:29:07 +00:00
snomiao
18c2163625 [fix] Fix collect-i18n script compilation error with TypeScript declare fields
The collect-i18n script was failing with babel transformer error when encountering TypeScript declare fields in litegraph classes.

Root cause:
- Playwright internal TypeScript compilation does not handle declare fields properly
- i18n test files imported ComfyNodeDefImpl which imports litegraph types

Solution:
- Move i18n tests to browser_tests/tests/ with .spec.ts extension
- Remove direct imports of types that reference litegraph
- Process node definitions in browser context where types are available
- Use nx e2e command for consistency with other browser tests

Fixes regression introduced after Nx integration
2025-08-31 13:51:38 +00:00
5 changed files with 40 additions and 30 deletions

View File

@@ -31,7 +31,7 @@
"knip": "knip --cache", "knip": "knip --cache",
"knip:no-cache": "knip", "knip:no-cache": "knip",
"locale": "lobe-i18n locale", "locale": "lobe-i18n locale",
"collect-i18n": "npx playwright test --config=playwright.i18n.config.ts", "collect-i18n": "playwright test --config=playwright.i18n.config.ts",
"json-schema": "tsx scripts/generate-json-schema.ts", "json-schema": "tsx scripts/generate-json-schema.ts",
"storybook": "nx storybook -p 6006", "storybook": "nx storybook -p 6006",
"build-storybook": "storybook build" "build-storybook": "storybook build"

View File

@@ -31,21 +31,23 @@ export default defineConfig({
name: 'chromium', name: 'chromium',
use: { ...devices['Desktop Chrome'] }, use: { ...devices['Desktop Chrome'] },
timeout: 15000, timeout: 15000,
grepInvert: /@mobile/ // Run all tests except those tagged with @mobile grepInvert: /@mobile|collect-i18n/ // Run all tests except mobile and i18n collection tests
}, },
{ {
name: 'chromium-2x', name: 'chromium-2x',
use: { ...devices['Desktop Chrome'], deviceScaleFactor: 2 }, use: { ...devices['Desktop Chrome'], deviceScaleFactor: 2 },
timeout: 15000, timeout: 15000,
grep: /@2x/ // Run all tests tagged with @2x grep: /@2x/, // Run all tests tagged with @2x
grepInvert: /collect-i18n/ // Exclude i18n collection tests
}, },
{ {
name: 'chromium-0.5x', name: 'chromium-0.5x',
use: { ...devices['Desktop Chrome'], deviceScaleFactor: 0.5 }, use: { ...devices['Desktop Chrome'], deviceScaleFactor: 0.5 },
timeout: 15000, timeout: 15000,
grep: /@0.5x/ // Run all tests tagged with @0.5x grep: /@0.5x/, // Run all tests tagged with @0.5x
grepInvert: /collect-i18n/ // Exclude i18n collection tests
}, },
// { // {
@@ -62,7 +64,8 @@ export default defineConfig({
{ {
name: 'mobile-chrome', name: 'mobile-chrome',
use: { ...devices['Pixel 5'], hasTouch: true }, use: { ...devices['Pixel 5'], hasTouch: true },
grep: /@mobile/ // Run only tests tagged with @mobile grep: /@mobile/, // Run only tests tagged with @mobile
grepInvert: /collect-i18n/ // Exclude i18n collection tests
} }
// { // {
// name: 'Mobile Safari', // name: 'Mobile Safari',

View File

@@ -1,7 +1,7 @@
import { defineConfig } from '@playwright/test' import { defineConfig } from '@playwright/test'
export default defineConfig({ export default defineConfig({
testDir: './scripts', testDir: './scripts/i18n',
use: { use: {
baseURL: 'http://localhost:5173', baseURL: 'http://localhost:5173',
headless: true headless: true
@@ -9,4 +9,5 @@ export default defineConfig({
reporter: 'list', reporter: 'list',
timeout: 60000, timeout: 60000,
testMatch: /collect-i18n-.*\.ts/ testMatch: /collect-i18n-.*\.ts/
// Don't use globalSetup/globalTeardown to avoid ComfyUI path dependencies
}) })

View File

@@ -1,11 +1,11 @@
import * as fs from 'fs' import * as fs from 'fs'
import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage' import { comfyPageFixture as test } from '../../browser_tests/fixtures/ComfyPage'
import { CORE_MENU_COMMANDS } from '../src/constants/coreMenuCommands' import { CORE_MENU_COMMANDS } from '../../src/constants/coreMenuCommands'
import { SERVER_CONFIG_ITEMS } from '../src/constants/serverConfig' import { SERVER_CONFIG_ITEMS } from '../../src/constants/serverConfig'
import type { ComfyCommandImpl } from '../src/stores/commandStore' import type { ComfyCommandImpl } from '../../src/stores/commandStore'
import type { FormItem, SettingParams } from '../src/types/settingTypes' import type { FormItem, SettingParams } from '../../src/types/settingTypes'
import { formatCamelCase, normalizeI18nKey } from '../src/utils/formatUtil' import { formatCamelCase, normalizeI18nKey } from '../../src/utils/formatUtil'
const localePath = './src/locales/en/main.json' const localePath = './src/locales/en/main.json'
const commandsPath = './src/locales/en/commands.json' const commandsPath = './src/locales/en/commands.json'

View File

@@ -1,33 +1,39 @@
import * as fs from 'fs' import * as fs from 'fs'
import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage' import { comfyPageFixture as test } from '../../browser_tests/fixtures/ComfyPage'
import type { ComfyNodeDef } from '../src/schemas/nodeDefSchema' import { normalizeI18nKey } from '../../src/utils/formatUtil'
import type { ComfyApi } from '../src/scripts/api'
import { ComfyNodeDefImpl } from '../src/stores/nodeDefStore'
import { normalizeI18nKey } from '../src/utils/formatUtil'
const localePath = './src/locales/en/main.json' const localePath = './src/locales/en/main.json'
const nodeDefsPath = './src/locales/en/nodeDefs.json' const nodeDefsPath = './src/locales/en/nodeDefs.json'
test('collect-i18n-node-defs', async ({ comfyPage }) => { test('collect-i18n-node-defs', async ({ comfyPage }) => {
// Mock view route // Mock view route
comfyPage.page.route('**/view**', async (route) => { await comfyPage.page.route('**/view**', async (route) => {
await route.fulfill({ await route.fulfill({
body: JSON.stringify({}) body: JSON.stringify({})
}) })
}) })
const nodeDefs: ComfyNodeDefImpl[] = ( const nodeDefs = await comfyPage.page.evaluate(async () => {
Object.values( const api = window['app'].api
await comfyPage.page.evaluate(async () => { const defs = await api.getNodeDefs()
const api = window['app'].api as ComfyApi // Process node definitions in the browser context where ComfyNodeDefImpl is available
return await api.getNodeDefs() return Object.values(defs)
.filter((def: any) => !def.name.startsWith('DevTools'))
.map((def: any) => {
// Create ComfyNodeDefImpl in browser context
const impl = new (window as any).ComfyNodeDefImpl(def)
// Return a plain object with the needed properties
return {
name: impl.name,
display_name: impl.display_name,
description: impl.description,
category: impl.category,
inputs: impl.inputs,
outputs: impl.outputs
}
}) })
) as ComfyNodeDef[] })
)
// Ignore DevTools nodes (used for internal testing)
.filter((def) => !def.name.startsWith('DevTools'))
.map((def) => new ComfyNodeDefImpl(def))
console.log(`Collected ${nodeDefs.length} node definitions`) console.log(`Collected ${nodeDefs.length} node definitions`)
@@ -100,7 +106,7 @@ test('collect-i18n-node-defs', async ({ comfyPage }) => {
const nodeDefLabels = await extractWidgetLabels() const nodeDefLabels = await extractWidgetLabels()
function extractInputs(nodeDef: ComfyNodeDefImpl) { function extractInputs(nodeDef: any) {
const inputs = Object.fromEntries( const inputs = Object.fromEntries(
Object.values(nodeDef.inputs).flatMap((input) => { Object.values(nodeDef.inputs).flatMap((input) => {
const name = input.name const name = input.name
@@ -124,7 +130,7 @@ test('collect-i18n-node-defs', async ({ comfyPage }) => {
return Object.keys(inputs).length > 0 ? inputs : undefined return Object.keys(inputs).length > 0 ? inputs : undefined
} }
function extractOutputs(nodeDef: ComfyNodeDefImpl) { function extractOutputs(nodeDef: any) {
const outputs = Object.fromEntries( const outputs = Object.fromEntries(
nodeDef.outputs.flatMap((output, i) => { nodeDef.outputs.flatMap((output, i) => {
// Ignore data types if they are already translated in allDataTypesLocale. // Ignore data types if they are already translated in allDataTypesLocale.