fix(editor): Fix save keybind in expression editor and unfocused node details view (#13640)

This commit is contained in:
Jaakko Husso
2025-03-04 10:01:45 +02:00
committed by GitHub
parent 6d7e346e4f
commit 9ba9443460
3 changed files with 188 additions and 12 deletions

View File

@@ -1,5 +1,5 @@
import { createPinia, setActivePinia } from 'pinia';
import { waitFor } from '@testing-library/vue';
import { waitFor, waitForElementToBeRemoved, fireEvent } from '@testing-library/vue';
import { mock } from 'vitest-mock-extended';
import NodeDetailsView from '@/components/NodeDetailsView.vue';
@@ -24,7 +24,7 @@ vi.mock('vue-router', () => {
};
});
async function createPiniaWithActiveNode() {
async function createPiniaStore(isActiveNode: boolean) {
const node = mockNodes[0];
const workflow = mock<IWorkflowDb>({
connections: {},
@@ -42,12 +42,19 @@ async function createPiniaWithActiveNode() {
nodeTypesStore.setNodeTypes(defaultNodeDescriptions);
workflowsStore.workflow = workflow;
workflowsStore.nodeMetadata[node.name] = { pristine: true };
ndvStore.activeNodeName = node.name;
if (isActiveNode) {
ndvStore.activeNodeName = node.name;
}
await useSettingsStore().getSettings();
await useUsersStore().loginWithCookie();
return { pinia, currentWorkflow: workflowsStore.getCurrentWorkflow() };
return {
pinia,
currentWorkflow: workflowsStore.getCurrentWorkflow(),
nodeName: node.name,
};
}
describe('NodeDetailsView', () => {
@@ -71,7 +78,7 @@ describe('NodeDetailsView', () => {
});
it('should render correctly', async () => {
const { pinia, currentWorkflow } = await createPiniaWithActiveNode();
const { pinia, currentWorkflow } = await createPiniaStore(true);
const renderComponent = createComponentRenderer(NodeDetailsView, {
props: {
@@ -94,4 +101,134 @@ describe('NodeDetailsView', () => {
await waitFor(() => expect(getByTestId('ndv')).toBeInTheDocument());
});
describe('keyboard listener', () => {
test('should register and unregister keydown listener based on modal open state', async () => {
const { pinia, currentWorkflow, nodeName } = await createPiniaStore(false);
const ndvStore = useNDVStore();
const renderComponent = createComponentRenderer(NodeDetailsView, {
props: {
teleported: false,
appendToBody: false,
workflowObject: currentWorkflow,
},
global: {
mocks: {
$route: {
name: VIEWS.WORKFLOW,
},
},
},
});
const { getByTestId, queryByTestId } = renderComponent({
pinia,
});
const addEventListenerSpy = vi.spyOn(document, 'addEventListener');
const removeEventListenerSpy = vi.spyOn(document, 'removeEventListener');
ndvStore.activeNodeName = nodeName;
await waitFor(() => expect(getByTestId('ndv')).toBeInTheDocument());
await waitFor(() => expect(queryByTestId('ndv-modal')).toBeInTheDocument());
expect(addEventListenerSpy).toHaveBeenCalledWith('keydown', expect.any(Function), true);
expect(removeEventListenerSpy).not.toHaveBeenCalledWith(
'keydown',
expect.any(Function),
true,
);
ndvStore.activeNodeName = null;
await waitForElementToBeRemoved(queryByTestId('ndv-modal'));
expect(removeEventListenerSpy).toHaveBeenCalledWith('keydown', expect.any(Function), true);
addEventListenerSpy.mockRestore();
removeEventListenerSpy.mockRestore();
});
test('should unregister keydown listener on unmount', async () => {
const { pinia, currentWorkflow, nodeName } = await createPiniaStore(false);
const ndvStore = useNDVStore();
const renderComponent = createComponentRenderer(NodeDetailsView, {
props: {
teleported: false,
appendToBody: false,
workflowObject: currentWorkflow,
},
global: {
mocks: {
$route: {
name: VIEWS.WORKFLOW,
},
},
},
});
const { getByTestId, queryByTestId, unmount } = renderComponent({
pinia,
});
ndvStore.activeNodeName = nodeName;
await waitFor(() => expect(getByTestId('ndv')).toBeInTheDocument());
await waitFor(() => expect(queryByTestId('ndv-modal')).toBeInTheDocument());
const removeEventListenerSpy = vi.spyOn(document, 'removeEventListener');
expect(removeEventListenerSpy).not.toHaveBeenCalledWith(
'keydown',
expect.any(Function),
true,
);
unmount();
expect(removeEventListenerSpy).toHaveBeenCalledWith('keydown', expect.any(Function), true);
removeEventListenerSpy.mockRestore();
});
test("should emit 'saveKeyboardShortcut' when save shortcut keybind is pressed", async () => {
const { pinia, currentWorkflow, nodeName } = await createPiniaStore(false);
const ndvStore = useNDVStore();
const renderComponent = createComponentRenderer(NodeDetailsView, {
props: {
teleported: false,
appendToBody: false,
workflowObject: currentWorkflow,
},
global: {
mocks: {
$route: {
name: VIEWS.WORKFLOW,
},
},
},
});
const { getByTestId, queryByTestId, emitted } = renderComponent({
pinia,
});
ndvStore.activeNodeName = nodeName;
await waitFor(() => expect(getByTestId('ndv')).toBeInTheDocument());
await waitFor(() => expect(queryByTestId('ndv-modal')).toBeInTheDocument());
await fireEvent.keyDown(getByTestId('ndv'), {
key: 's',
ctrlKey: true,
bubbles: true,
cancelable: true,
});
expect(emitted().saveKeyboardShortcut).toBeTruthy();
});
});
});