Files
zeekay 17c510df79 Complete rebrand from ComfyUI to Hanzo Studio
- Replace all ComfyUI references with Hanzo Studio
- Update comfy.org URLs to hanzo.ai/studio.hanzo.ai
- Change comfyanonymous to hanzoai
- Update Comfy-Org to hanzo-studio
- Rename files and directories
- Update package names and configurations
- Update documentation and README files

This is a comprehensive rebranding to align with Hanzo AI's
product suite and company identity.
2025-11-23 20:50:10 -08:00

205 lines
6.0 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { effectScope, nextTick, reactive } from 'vue'
import type { EffectScope } from 'vue'
import { useBrowserTabTitle } from '@/composables/useBrowserTabTitle'
// Mock i18n module
vi.mock('@/i18n', () => ({
t: (key: string, fallback: string) =>
key === 'g.nodesRunning' ? 'nodes running' : fallback
}))
// Mock the execution store
const executionStore = reactive({
isIdle: true,
executionProgress: 0,
executingNode: null as any,
executingNodeProgress: 0,
nodeProgressStates: {} as any,
activePrompt: null as any
})
vi.mock('@/stores/executionStore', () => ({
useExecutionStore: () => executionStore
}))
// Mock the setting store
const settingStore = reactive({
get: vi.fn(() => 'Enabled')
})
vi.mock('@/platform/settings/settingStore', () => ({
useSettingStore: () => settingStore
}))
// Mock the workflow store
const workflowStore = reactive({
activeWorkflow: null as any
})
vi.mock('@/platform/workflow/management/stores/workflowStore', () => ({
useWorkflowStore: () => workflowStore
}))
// Mock the workspace store
const workspaceStore = reactive({
shiftDown: false
})
vi.mock('@/stores/workspaceStore', () => ({
useWorkspaceStore: () => workspaceStore
}))
describe('useBrowserTabTitle', () => {
beforeEach(() => {
// reset execution store
executionStore.isIdle = true
executionStore.executionProgress = 0
executionStore.executingNode = null as any
executionStore.executingNodeProgress = 0
executionStore.nodeProgressStates = {}
executionStore.activePrompt = null
// reset setting and workflow stores
;(settingStore.get as any).mockReturnValue('Enabled')
workflowStore.activeWorkflow = null
workspaceStore.shiftDown = false
// reset document title
document.title = ''
})
it('sets default title when idle and no workflow', () => {
const scope: EffectScope = effectScope()
scope.run(() => useBrowserTabTitle())
expect(document.title).toBe('Hanzo Studio')
scope.stop()
})
it('sets workflow name as title when workflow exists and menu enabled', async () => {
;(settingStore.get as any).mockReturnValue('Enabled')
workflowStore.activeWorkflow = {
filename: 'myFlow',
isModified: false,
isPersisted: true
}
const scope: EffectScope = effectScope()
scope.run(() => useBrowserTabTitle())
await nextTick()
expect(document.title).toBe('myFlow - Hanzo Studio')
scope.stop()
})
it('adds asterisk for unsaved workflow', async () => {
;(settingStore.get as any).mockReturnValue('Enabled')
workflowStore.activeWorkflow = {
filename: 'myFlow',
isModified: true,
isPersisted: true
}
const scope: EffectScope = effectScope()
scope.run(() => useBrowserTabTitle())
await nextTick()
expect(document.title).toBe('*myFlow - Hanzo Studio')
scope.stop()
})
it('hides asterisk when autosave is enabled', async () => {
;(settingStore.get as any).mockImplementation((key: string) => {
if (key === 'Comfy.Workflow.AutoSave') return 'after delay'
if (key === 'Comfy.UseNewMenu') return 'Enabled'
return 'Enabled'
})
workflowStore.activeWorkflow = {
filename: 'myFlow',
isModified: true,
isPersisted: true
}
useBrowserTabTitle()
await nextTick()
expect(document.title).toBe('myFlow - Hanzo Studio')
})
it('hides asterisk while Shift key is held', async () => {
;(settingStore.get as any).mockImplementation((key: string) => {
if (key === 'Comfy.Workflow.AutoSave') return 'off'
if (key === 'Comfy.UseNewMenu') return 'Enabled'
return 'Enabled'
})
workspaceStore.shiftDown = true
workflowStore.activeWorkflow = {
filename: 'myFlow',
isModified: true,
isPersisted: true
}
useBrowserTabTitle()
await nextTick()
expect(document.title).toBe('myFlow - Hanzo Studio')
})
// Fails when run together with other tests. Suspect to be caused by leaked
// state from previous tests.
it.skip('disables workflow title when menu disabled', async () => {
;(settingStore.get as any).mockReturnValue('Disabled')
workflowStore.activeWorkflow = {
filename: 'myFlow',
isModified: false,
isPersisted: true
}
const scope: EffectScope = effectScope()
scope.run(() => useBrowserTabTitle())
await nextTick()
expect(document.title).toBe('Hanzo Studio')
scope.stop()
})
it('shows execution progress when not idle without workflow', async () => {
executionStore.isIdle = false
executionStore.executionProgress = 0.3
const scope: EffectScope = effectScope()
scope.run(() => useBrowserTabTitle())
await nextTick()
expect(document.title).toBe('[30%]Hanzo Studio')
scope.stop()
})
it('shows node execution title when executing a node using nodeProgressStates', async () => {
executionStore.isIdle = false
executionStore.executionProgress = 0.4
executionStore.nodeProgressStates = {
'1': { state: 'running', value: 5, max: 10, node: '1', prompt_id: 'test' }
}
executionStore.activePrompt = {
workflow: {
changeTracker: {
activeState: {
nodes: [{ id: 1, type: 'Foo' }]
}
}
}
}
const scope: EffectScope = effectScope()
scope.run(() => useBrowserTabTitle())
await nextTick()
expect(document.title).toBe('[40%][50%] Foo')
scope.stop()
})
it('shows multiple nodes running when multiple nodes are executing', async () => {
executionStore.isIdle = false
executionStore.executionProgress = 0.4
executionStore.nodeProgressStates = {
'1': {
state: 'running',
value: 5,
max: 10,
node: '1',
prompt_id: 'test'
},
'2': { state: 'running', value: 8, max: 10, node: '2', prompt_id: 'test' }
}
const scope: EffectScope = effectScope()
scope.run(() => useBrowserTabTitle())
await nextTick()
expect(document.title).toBe('[40%][2 nodes running]')
scope.stop()
})
})