[bugfix] Fix execute button incorrectly disabled on empty workflows (#6774)

## Summary

Fixes a bug where the queue/execute button was incorrectly disabled with
a warning icon when creating a new empty workflow, due to stale missing
nodes data persisting from a previous workflow.

## Root Cause

When switching from a workflow with missing nodes to an empty workflow,
the `getWorkflowPacks()` function in `useWorkflowPacks.ts` would return
early without clearing the `workflowPacks.value` ref, causing stale
missing node data to persist.

## Changes

- **`useWorkflowPacks.ts`**: Explicitly clear `workflowPacks.value = []`
when switching to empty workflow
- **`useMissingNodes.test.ts`**: Add test case to verify missing nodes
state clears when switching to empty workflow

## Test Plan

- [x] Added unit test covering the empty workflow scenario
- [x] All 20 unit tests pass
- [x] TypeScript type checking passes
- [x] Manual verification: Create workflow with missing nodes → Create
new empty workflow → Button should be enabled

## Before

1. Open workflow with missing nodes → Button disabled  (correct)
2. Create new empty workflow → Button still disabled  (bug)
3. Click valid workflow → Button enabled 

## After

1. Open workflow with missing nodes → Button disabled 
2. Create new empty workflow → Button enabled  (fixed)
3. Click valid workflow → Button enabled 

[screen-capture
(2).webm](https://github.com/user-attachments/assets/833355d6-6b4b-4e77-94b9-d7964454cfce)

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

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6774-bugfix-Fix-execute-button-incorrectly-disabled-on-empty-workflows-2b16d73d365081e3a050c3f7c0a20cc6)
by [Unito](https://www.unito.io)
This commit is contained in:
Jin Yi
2025-11-20 14:22:32 +09:00
committed by GitHub
parent a20fb7d260
commit 87106ccb95
2 changed files with 30 additions and 1 deletions

View File

@@ -114,7 +114,10 @@ export const useWorkflowPacks = (options: UseNodePacksOptions = {}) => {
const getWorkflowPacks = async () => {
if (!app.graph) return []
const allNodes = collectAllNodes(app.graph)
if (!allNodes.length) return []
if (!allNodes.length) {
workflowPacks.value = []
return []
}
const packs = await Promise.all(allNodes.map(workflowNodeToPack))
workflowPacks.value = packs.filter((pack) => pack !== undefined)
}

View File

@@ -277,6 +277,32 @@ describe('useMissingNodes', () => {
// Should update missing packs (2 missing since pack-3 is installed)
expect(missingNodePacks.value).toHaveLength(2)
})
it('clears missing nodes when switching to empty workflow', async () => {
const workflowPacksRef = ref(mockWorkflowPacks)
mockUseWorkflowPacks.mockReturnValue({
workflowPacks: workflowPacksRef,
isLoading: ref(false),
error: ref(null),
startFetchWorkflowPacks: mockStartFetchWorkflowPacks,
isReady: ref(true),
filterWorkflowPack: vi.fn()
})
const { hasMissingNodes, missingNodePacks } = useMissingNodes()
// Should have missing nodes initially (2 missing since pack-3 is installed)
expect(missingNodePacks.value).toHaveLength(2)
expect(hasMissingNodes.value).toBe(true)
// Switch to empty workflow (simulates creating a new empty workflow)
workflowPacksRef.value = []
await nextTick()
// Should clear missing nodes
expect(missingNodePacks.value).toHaveLength(0)
expect(hasMissingNodes.value).toBe(false)
})
})
describe('missing core nodes detection', () => {