1
- import { createPinia , setActivePinia } from 'pinia' ;
2
- import WorkflowSettingsVue from '@/components/WorkflowSettings.vue' ;
3
-
4
- import { setupServer } from '@/__tests__/server' ;
1
+ import { nextTick , reactive } from 'vue' ;
2
+ import { createTestingPinia } from '@pinia/testing' ;
5
3
import type { MockInstance } from 'vitest' ;
6
- import { afterAll , beforeAll } from 'vitest' ;
7
- import { within } from '@testing-library/vue' ;
4
+ import { within , waitFor } from '@testing-library/vue' ;
8
5
import userEvent from '@testing-library/user-event' ;
9
-
6
+ import type { FrontendSettings } from '@n8n/api-types' ;
7
+ import { createComponentRenderer } from '@/__tests__/render' ;
8
+ import { getDropdownItems , mockedStore , type MockedStore } from '@/__tests__/utils' ;
9
+ import { EnterpriseEditionFeature } from '@/constants' ;
10
+ import WorkflowSettingsVue from '@/components/WorkflowSettings.vue' ;
10
11
import { useWorkflowsStore } from '@/stores/workflows.store' ;
11
12
import { useSettingsStore } from '@/stores/settings.store' ;
12
- import { useUIStore } from '@/stores/ui.store' ;
13
-
14
- import { createComponentRenderer } from '@/__tests__/render' ;
15
- import { cleanupAppModals , createAppModals , getDropdownItems } from '@/__tests__/utils' ;
16
- import { EnterpriseEditionFeature , WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants' ;
17
-
18
- import { nextTick } from 'vue' ;
19
- import type { IWorkflowDb } from '@/Interface' ;
20
- import * as permissions from '@/permissions' ;
21
- import type { PermissionsRecord } from '@/permissions' ;
13
+ import { useSourceControlStore } from '@/stores/sourceControl.store' ;
14
+
15
+ vi . mock ( 'vue-router' , async ( ) => ( {
16
+ useRouter : vi . fn ( ) ,
17
+ useRoute : ( ) =>
18
+ reactive ( {
19
+ params : {
20
+ name : '1' ,
21
+ } ,
22
+ } ) ,
23
+ RouterLink : {
24
+ template : '<a><slot /></a>' ,
25
+ } ,
26
+ } ) ) ;
22
27
23
- let pinia : ReturnType < typeof createPinia > ;
24
- let workflowsStore : ReturnType < typeof useWorkflowsStore > ;
25
- let settingsStore : ReturnType < typeof useSettingsStore > ;
26
- let uiStore : ReturnType < typeof useUIStore > ;
28
+ let workflowsStore : MockedStore < typeof useWorkflowsStore > ;
29
+ let settingsStore : MockedStore < typeof useSettingsStore > ;
30
+ let sourceControlStore : MockedStore < typeof useSourceControlStore > ;
31
+ let pinia : ReturnType < typeof createTestingPinia > ;
27
32
28
33
let fetchAllWorkflowsSpy : MockInstance < ( typeof workflowsStore ) [ 'fetchAllWorkflows' ] > ;
29
34
30
- const createComponent = createComponentRenderer ( WorkflowSettingsVue ) ;
35
+ const createComponent = createComponentRenderer ( WorkflowSettingsVue , {
36
+ global : {
37
+ stubs : {
38
+ Modal : {
39
+ template :
40
+ '<div role="dialog"><slot name="header" /><slot name="content" /><slot name="footer" /></div>' ,
41
+ } ,
42
+ } ,
43
+ } ,
44
+ } ) ;
31
45
32
46
describe ( 'WorkflowSettingsVue' , ( ) => {
33
- let server : ReturnType < typeof setupServer > ;
34
- beforeAll ( ( ) => {
35
- server = setupServer ( ) ;
36
- } ) ;
37
-
38
47
beforeEach ( async ( ) => {
39
- pinia = createPinia ( ) ;
40
- setActivePinia ( pinia ) ;
41
-
42
- createAppModals ( ) ;
43
-
44
- workflowsStore = useWorkflowsStore ( ) ;
45
- settingsStore = useSettingsStore ( ) ;
46
- uiStore = useUIStore ( ) ;
47
-
48
- await settingsStore . getSettings ( ) ;
49
-
50
- vi . spyOn ( workflowsStore , 'workflowName' , 'get' ) . mockReturnValue ( 'Test Workflow' ) ;
51
- vi . spyOn ( workflowsStore , 'workflowId' , 'get' ) . mockReturnValue ( '1' ) ;
52
- fetchAllWorkflowsSpy = vi . spyOn ( workflowsStore , 'fetchAllWorkflows' ) . mockResolvedValue ( [
48
+ pinia = createTestingPinia ( ) ;
49
+ workflowsStore = mockedStore ( useWorkflowsStore ) ;
50
+ settingsStore = mockedStore ( useSettingsStore ) ;
51
+ sourceControlStore = mockedStore ( useSourceControlStore ) ;
52
+
53
+ settingsStore . settings = {
54
+ enterprise : { } ,
55
+ } as FrontendSettings ;
56
+ workflowsStore . workflowName = 'Test Workflow' ;
57
+ workflowsStore . workflowId = '1' ;
58
+ fetchAllWorkflowsSpy = workflowsStore . fetchAllWorkflows . mockResolvedValue ( [
53
59
{
54
60
id : '1' ,
55
61
name : 'Test Workflow' ,
@@ -61,7 +67,7 @@ describe('WorkflowSettingsVue', () => {
61
67
versionId : '123' ,
62
68
} ,
63
69
] ) ;
64
- vi . spyOn ( workflowsStore , ' getWorkflowById' ) . mockReturnValue ( {
70
+ workflowsStore . getWorkflowById . mockImplementation ( ( ) => ( {
65
71
id : '1' ,
66
72
name : 'Test Workflow' ,
67
73
active : true ,
@@ -70,24 +76,12 @@ describe('WorkflowSettingsVue', () => {
70
76
createdAt : 1 ,
71
77
updatedAt : 1 ,
72
78
versionId : '123' ,
73
- } as IWorkflowDb ) ;
74
- vi . spyOn ( permissions , 'getResourcePermissions' ) . mockReturnValue ( {
75
- workflow : {
76
- update : true ,
77
- } ,
78
- } as PermissionsRecord ) ;
79
-
80
- uiStore . modalsById [ WORKFLOW_SETTINGS_MODAL_KEY ] = {
81
- open : true ,
82
- } ;
79
+ scopes : [ 'workflow:update' ] ,
80
+ } ) ) ;
83
81
} ) ;
84
82
85
83
afterEach ( ( ) => {
86
- cleanupAppModals ( ) ;
87
- } ) ;
88
-
89
- afterAll ( ( ) => {
90
- server . shutdown ( ) ;
84
+ vi . clearAllMocks ( ) ;
91
85
} ) ;
92
86
93
87
it ( 'should render correctly' , async ( ) => {
@@ -220,4 +214,79 @@ describe('WorkflowSettingsVue', () => {
220
214
expect ( dropdownItems [ 0 ] ) . toHaveTextContent ( optionText ) ;
221
215
} ,
222
216
) ;
217
+
218
+ it ( 'should save time saved per execution correctly' , async ( ) => {
219
+ const { getByTestId, getByRole } = createComponent ( { pinia } ) ;
220
+ await nextTick ( ) ;
221
+
222
+ const timeSavedPerExecutionInput = getByTestId ( 'workflow-settings-time-saved-per-execution' ) ;
223
+
224
+ expect ( timeSavedPerExecutionInput ) . toBeVisible ( ) ;
225
+
226
+ await userEvent . type ( timeSavedPerExecutionInput as Element , '10' ) ;
227
+ expect ( timeSavedPerExecutionInput ) . toHaveValue ( 10 ) ;
228
+
229
+ await userEvent . click ( getByRole ( 'button' , { name : 'Save' } ) ) ;
230
+ expect ( workflowsStore . updateWorkflow ) . toHaveBeenCalledWith (
231
+ expect . any ( String ) ,
232
+ expect . objectContaining ( { settings : expect . objectContaining ( { timeSavedPerExecution : 10 } ) } ) ,
233
+ ) ;
234
+ } ) ;
235
+
236
+ it ( 'should remove time saved per execution setting' , async ( ) => {
237
+ workflowsStore . workflowSettings . timeSavedPerExecution = 10 ;
238
+
239
+ const { getByTestId, getByRole } = createComponent ( { pinia } ) ;
240
+ await nextTick ( ) ;
241
+
242
+ const timeSavedPerExecutionInput = getByTestId ( 'workflow-settings-time-saved-per-execution' ) ;
243
+
244
+ expect ( timeSavedPerExecutionInput ) . toBeVisible ( ) ;
245
+ await waitFor ( ( ) => expect ( timeSavedPerExecutionInput ) . toHaveValue ( 10 ) ) ;
246
+
247
+ await userEvent . clear ( timeSavedPerExecutionInput as Element ) ;
248
+ expect ( timeSavedPerExecutionInput ) . not . toHaveValue ( ) ;
249
+
250
+ await userEvent . click ( getByRole ( 'button' , { name : 'Save' } ) ) ;
251
+ expect ( workflowsStore . updateWorkflow ) . toHaveBeenCalledWith (
252
+ expect . any ( String ) ,
253
+ expect . objectContaining ( {
254
+ settings : expect . not . objectContaining ( { timeSavedPerExecution : 10 } ) ,
255
+ } ) ,
256
+ ) ;
257
+ } ) ;
258
+
259
+ it ( 'should disable save time saved per execution if env is read-only' , async ( ) => {
260
+ sourceControlStore . preferences . branchReadOnly = true ;
261
+
262
+ const { getByTestId } = createComponent ( { pinia } ) ;
263
+ await nextTick ( ) ;
264
+
265
+ const timeSavedPerExecutionInput = getByTestId ( 'workflow-settings-time-saved-per-execution' ) ;
266
+
267
+ expect ( timeSavedPerExecutionInput ) . toBeVisible ( ) ;
268
+ expect ( timeSavedPerExecutionInput ) . toBeDisabled ( ) ;
269
+ } ) ;
270
+
271
+ it ( 'should disable save time saved per execution if user has no permission to update workflow' , async ( ) => {
272
+ workflowsStore . getWorkflowById . mockImplementation ( ( ) => ( {
273
+ id : '1' ,
274
+ name : 'Test Workflow' ,
275
+ active : true ,
276
+ nodes : [ ] ,
277
+ connections : { } ,
278
+ createdAt : 1 ,
279
+ updatedAt : 1 ,
280
+ versionId : '123' ,
281
+ scopes : [ 'workflow:read' ] ,
282
+ } ) ) ;
283
+
284
+ const { getByTestId } = createComponent ( { pinia } ) ;
285
+ await nextTick ( ) ;
286
+
287
+ const timeSavedPerExecutionInput = getByTestId ( 'workflow-settings-time-saved-per-execution' ) ;
288
+
289
+ expect ( timeSavedPerExecutionInput ) . toBeVisible ( ) ;
290
+ expect ( timeSavedPerExecutionInput ) . toBeDisabled ( ) ;
291
+ } ) ;
223
292
} ) ;
0 commit comments