fix(editor): Fix command bar test workflow command issue (#20910)

This commit is contained in:
Svetoslav Dekov 2025-10-20 09:12:33 +03:00 committed by GitHub
parent 84e676b194
commit be27e94cb5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 33 additions and 47 deletions

View File

@ -181,24 +181,6 @@ describe('useRunWorkflow({ router })', () => {
vi.clearAllMocks();
});
it('should use passed workflowState parameter', async () => {
const customWorkflowState = vi.mocked(useWorkflowState());
const setActiveExecutionIdSpy = vi.spyOn(customWorkflowState, 'setActiveExecutionId');
const { runWorkflowApi } = useRunWorkflow({ router, workflowState: customWorkflowState });
vi.mocked(pushConnectionStore).isConnected = true;
vi.mocked(workflowsStore).runWorkflow.mockResolvedValue({
executionId: '123',
waitingForWebhook: false,
});
await runWorkflowApi({} as IStartRunData);
expect(setActiveExecutionIdSpy).toHaveBeenCalledWith(null);
expect(setActiveExecutionIdSpy).toHaveBeenCalledWith('123');
});
describe('runWorkflowApi()', () => {
it('should throw an error if push connection is not active', async () => {
const { runWorkflowApi } = useRunWorkflow({ router });

View File

@ -46,12 +46,11 @@ import { useCanvasOperations } from './useCanvasOperations';
import { useAgentRequestStore } from '@n8n/stores/useAgentRequestStore';
import { useWorkflowSaving } from './useWorkflowSaving';
import { computed } from 'vue';
import { injectWorkflowState, type WorkflowState } from './useWorkflowState';
import { injectWorkflowState } from './useWorkflowState';
import { useDocumentTitle } from './useDocumentTitle';
export function useRunWorkflow(useRunWorkflowOpts: {
router: ReturnType<typeof useRouter>;
workflowState?: WorkflowState;
}) {
const nodeHelpers = useNodeHelpers();
const workflowHelpers = useWorkflowHelpers();
@ -66,7 +65,7 @@ export function useRunWorkflow(useRunWorkflowOpts: {
const rootStore = useRootStore();
const pushConnectionStore = usePushConnectionStore();
const workflowsStore = useWorkflowsStore();
const workflowState = useRunWorkflowOpts.workflowState ?? injectWorkflowState();
const workflowState = injectWorkflowState();
const executionsStore = useExecutionsStore();
const { dirtinessByName } = useNodeDirtiness();
const { startChat } = useCanvasOperations();

View File

@ -26,6 +26,7 @@ vi.mock('vue-router', () => ({
useRouter: () => ({
resolve: vi.fn((route) => ({ href: `/workflow/${route.params.name}` })),
}),
useRoute: () => ({}),
RouterLink: vi.fn(),
}));
vi.mock('@n8n/i18n', async (importOriginal) => ({

View File

@ -13,7 +13,6 @@ import { useTelemetry } from '@/composables/useTelemetry';
import { useWorkflowSaving } from '@/composables/useWorkflowSaving';
import { useRunWorkflow } from '@/composables/useRunWorkflow';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { useWorkflowState } from '@/composables/useWorkflowState';
import {
DUPLICATE_MODAL_KEY,
EXECUTE_WORKFLOW_NODE_TYPE,
@ -59,11 +58,12 @@ export function useWorkflowCommands(): CommandGroup {
const uiStore = useUIStore();
const tagsStore = useTagsStore();
const workflowsStore = useWorkflowsStore();
const workflowState = useWorkflowState();
const sourceControlStore = useSourceControlStore();
const router = useRouter();
const runWorkflow = useRunWorkflow({ router });
const workflowHelpers = useWorkflowHelpers();
const telemetry = useTelemetry();
const workflowSaving = useWorkflowSaving({ router });
@ -170,8 +170,7 @@ export function useWorkflowCommands(): CommandGroup {
i18n.baseText('commandBar.workflow.keywords.workflow'),
],
handler: () => {
// Lazily instantiate useRunWorkflow only when the handler runs to avoid early initialization side effects
void useRunWorkflow({ router, workflowState }).runEntireWorkflow('main');
void runWorkflow.runEntireWorkflow('main');
},
icon: {
component: N8nIcon,

View File

@ -44,13 +44,13 @@ export const usePushConnectionStore = defineStore(STORES.PUSH, () => {
};
};
const useWebSockets = settingsStore.pushBackend === 'websocket';
const useWebSockets = computed(() => settingsStore.pushBackend === 'websocket');
const getConnectionUrl = () => {
const restUrl = rootStore.restUrl;
const url = `/push?pushRef=${rootStore.pushRef}`;
if (useWebSockets) {
if (useWebSockets.value) {
const { protocol, host } = window.location;
const baseUrl = restUrl.startsWith('http')
? restUrl.replace(/^http/, 'ws')
@ -88,13 +88,15 @@ export const usePushConnectionStore = defineStore(STORES.PUSH, () => {
const url = getConnectionUrl();
const client = useWebSockets
? useWebSocketClient({ url, onMessage })
: useEventSourceClient({ url, onMessage });
const client = computed(() =>
useWebSockets.value
? useWebSocketClient({ url, onMessage })
: useEventSourceClient({ url, onMessage }),
);
function serializeAndSend(message: unknown) {
if (client.isConnected.value) {
client.sendMessage(JSON.stringify(message));
if (client.value.isConnected.value) {
client.value.sendMessage(JSON.stringify(message));
} else {
outgoingQueue.value.push(message);
}
@ -102,34 +104,37 @@ export const usePushConnectionStore = defineStore(STORES.PUSH, () => {
const pushConnect = () => {
isConnectionRequested.value = true;
client.connect();
client.value.connect();
};
const pushDisconnect = () => {
isConnectionRequested.value = false;
client.disconnect();
client.value.disconnect();
};
watch(client.isConnected, (didConnect) => {
if (!didConnect) {
return;
}
// Send any buffered messages
if (outgoingQueue.value.length) {
for (const message of outgoingQueue.value) {
serializeAndSend(message);
watch(
() => client.value.isConnected.value,
(didConnect) => {
if (!didConnect) {
return;
}
outgoingQueue.value = [];
}
});
// Send any buffered messages
if (outgoingQueue.value.length) {
for (const message of outgoingQueue.value) {
serializeAndSend(message);
}
outgoingQueue.value = [];
}
},
);
/** Removes all buffered messages from the sent queue */
const clearQueue = () => {
outgoingQueue.value = [];
};
const isConnected = computed(() => client.isConnected.value);
const isConnected = computed(() => client.value.isConnected.value);
return {
isConnected,