mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
fix(editor): Improve formatting of expired trial error message (#11708)
This commit is contained in:
parent
a91abeeff5
commit
8a0ad0f910
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
|
@ -47,9 +47,7 @@
|
|||
"request": "launch",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"type": "node",
|
||||
"env": {
|
||||
// "N8N_PORT": "5679",
|
||||
},
|
||||
"envFile": "${workspaceFolder}/.env",
|
||||
"outputCapture": "std",
|
||||
"killBehavior": "polite"
|
||||
},
|
||||
|
|
|
@ -5,6 +5,10 @@ import type { PushMessage, PushPayload } from '@n8n/api-types';
|
|||
import { usePushConnection } from '@/composables/usePushConnection';
|
||||
import { usePushConnectionStore } from '@/stores/pushConnection.store';
|
||||
import { useOrchestrationStore } from '@/stores/orchestration.store';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { useToast } from '@/composables/useToast';
|
||||
import type { WorkflowOperationError } from 'n8n-workflow';
|
||||
|
||||
vi.mock('vue-router', () => {
|
||||
return {
|
||||
|
@ -16,6 +20,19 @@ vi.mock('vue-router', () => {
|
|||
};
|
||||
});
|
||||
|
||||
vi.mock('@/composables/useToast', () => {
|
||||
const showMessage = vi.fn();
|
||||
const showError = vi.fn();
|
||||
return {
|
||||
useToast: () => {
|
||||
return {
|
||||
showMessage,
|
||||
showError,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.useFakeTimers();
|
||||
|
||||
describe('usePushConnection()', () => {
|
||||
|
@ -23,6 +40,9 @@ describe('usePushConnection()', () => {
|
|||
let pushStore: ReturnType<typeof usePushConnectionStore>;
|
||||
let orchestrationStore: ReturnType<typeof useOrchestrationStore>;
|
||||
let pushConnection: ReturnType<typeof usePushConnection>;
|
||||
let uiStore: ReturnType<typeof useUIStore>;
|
||||
let workflowsStore: ReturnType<typeof useWorkflowsStore>;
|
||||
let toast: ReturnType<typeof useToast>;
|
||||
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia());
|
||||
|
@ -30,7 +50,14 @@ describe('usePushConnection()', () => {
|
|||
router = vi.mocked(useRouter)();
|
||||
pushStore = usePushConnectionStore();
|
||||
orchestrationStore = useOrchestrationStore();
|
||||
uiStore = useUIStore();
|
||||
workflowsStore = useWorkflowsStore();
|
||||
pushConnection = usePushConnection({ router });
|
||||
toast = useToast();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('initialize()', () => {
|
||||
|
@ -106,5 +133,89 @@ describe('usePushConnection()', () => {
|
|||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('executionFinished', () => {
|
||||
it('should handle executionFinished event correctly', async () => {
|
||||
const event: PushMessage = {
|
||||
type: 'executionFinished',
|
||||
data: {
|
||||
executionId: '1',
|
||||
data: {
|
||||
data: {
|
||||
resultData: {
|
||||
runData: {},
|
||||
},
|
||||
},
|
||||
finished: true,
|
||||
mode: 'manual',
|
||||
startedAt: new Date(),
|
||||
stoppedAt: new Date(),
|
||||
status: 'success',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
workflowsStore.activeExecutionId = '1';
|
||||
uiStore.isActionActive.workflowRunning = true;
|
||||
|
||||
const result = await pushConnection.pushMessageReceived(event);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(workflowsStore.workflowExecutionData).toBeDefined();
|
||||
expect(uiStore.isActionActive['workflowRunning']).toBeTruthy();
|
||||
|
||||
expect(toast.showMessage).toHaveBeenCalledWith({
|
||||
title: 'Workflow executed successfully',
|
||||
type: 'success',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle isManualExecutionCancelled correctly', async () => {
|
||||
const event: PushMessage = {
|
||||
type: 'executionFinished',
|
||||
data: {
|
||||
executionId: '1',
|
||||
data: {
|
||||
data: {
|
||||
startData: {},
|
||||
resultData: {
|
||||
runData: {
|
||||
'Last Node': [],
|
||||
},
|
||||
lastNodeExecuted: 'Last Node',
|
||||
error: {
|
||||
message:
|
||||
'Your trial has ended. <a href="https://app.n8n.cloud/account/change-plan">Upgrade now</a> to keep automating',
|
||||
name: 'NodeApiError',
|
||||
node: 'Last Node',
|
||||
} as unknown as WorkflowOperationError,
|
||||
},
|
||||
},
|
||||
startedAt: new Date(),
|
||||
mode: 'manual',
|
||||
status: 'running',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
workflowsStore.activeExecutionId = '1';
|
||||
uiStore.isActionActive['workflowRunning'] = true;
|
||||
|
||||
const result = await pushConnection.pushMessageReceived(event);
|
||||
|
||||
expect(useToast().showMessage).toHaveBeenCalledWith({
|
||||
message:
|
||||
'Your trial has ended. <a href="https://app.n8n.cloud/account/change-plan">Upgrade now</a> to keep automating',
|
||||
title: 'Problem in node ‘Last Node‘',
|
||||
type: 'error',
|
||||
duration: 0,
|
||||
dangerouslyUseHTMLString: true,
|
||||
});
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(workflowsStore.workflowExecutionData).toBeDefined();
|
||||
expect(uiStore.isActionActive.workflowRunning).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -423,6 +423,7 @@ export function usePushConnection({ router }: { router: ReturnType<typeof useRou
|
|||
message: runDataExecutedErrorMessage,
|
||||
type: 'error',
|
||||
duration: 0,
|
||||
dangerouslyUseHTMLString: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
55
packages/editor-ui/src/composables/useToast.test.ts
Normal file
55
packages/editor-ui/src/composables/useToast.test.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { useToast } from './useToast';
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { ElNotification as Notification } from 'element-plus';
|
||||
|
||||
vi.mock('element-plus', async () => {
|
||||
const original = await vi.importActual('element-plus');
|
||||
return {
|
||||
...original,
|
||||
ElNotification: vi.fn(),
|
||||
ElTooltip: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
describe('useToast', () => {
|
||||
let toast: ReturnType<typeof useToast>;
|
||||
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia());
|
||||
|
||||
toast = useToast();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should show a message', () => {
|
||||
const messageData = { message: 'Test message', title: 'Test title' };
|
||||
toast.showMessage(messageData);
|
||||
|
||||
expect(Notification).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
message: 'Test message',
|
||||
title: 'Test title',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should sanitize message and title', () => {
|
||||
const messageData = {
|
||||
message: '<script>alert("xss")</script>',
|
||||
title: '<script>alert("xss")</script>',
|
||||
};
|
||||
|
||||
toast.showMessage(messageData);
|
||||
|
||||
expect(Notification).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
message: 'alert("xss")',
|
||||
title: 'alert("xss")',
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue