@@ -8,8 +8,9 @@ import { useTemplateUrlLoader } from '@/platform/workflow/templates/composables/
88 * Tests the behavior of loading templates via URL query parameters:
99 * - ?template=flux_simple loads the template
1010 * - ?template=flux_simple&source=custom loads from custom source
11+ * - ?template=flux_simple&mode=linear loads template in linear mode
1112 * - Invalid template shows error toast
12- * - Input validation for template and source parameters
13+ * - Input validation for template, source, and mode parameters
1314 */
1415
1516const preservedQueryMocks = vi . hoisted ( ( ) => ( {
@@ -70,10 +71,20 @@ vi.mock('vue-i18n', () => ({
7071 } )
7172} ) )
7273
74+ // Mock canvas store
75+ const mockCanvasStore = {
76+ linearMode : false
77+ }
78+
79+ vi . mock ( '@/renderer/core/canvas/canvasStore' , ( ) => ( {
80+ useCanvasStore : ( ) => mockCanvasStore
81+ } ) )
82+
7383describe ( 'useTemplateUrlLoader' , ( ) => {
7484 beforeEach ( ( ) => {
7585 vi . clearAllMocks ( )
7686 mockQueryParams = { }
87+ mockCanvasStore . linearMode = false
7788 } )
7889
7990 it ( 'does not load template when no query param present' , ( ) => {
@@ -236,6 +247,7 @@ describe('useTemplateUrlLoader', () => {
236247 mockQueryParams = {
237248 template : 'flux_simple' ,
238249 source : 'custom' ,
250+ mode : 'linear' ,
239251 other : 'param'
240252 }
241253
@@ -270,4 +282,121 @@ describe('useTemplateUrlLoader', () => {
270282 query : { other : 'param' }
271283 } )
272284 } )
285+
286+ it ( 'sets linear mode when mode=linear and template loads successfully' , async ( ) => {
287+ mockQueryParams = { template : 'flux_simple' , mode : 'linear' }
288+
289+ const { loadTemplateFromUrl } = useTemplateUrlLoader ( )
290+ await loadTemplateFromUrl ( )
291+
292+ expect ( mockLoadWorkflowTemplate ) . toHaveBeenCalledWith (
293+ 'flux_simple' ,
294+ 'default'
295+ )
296+ expect ( mockCanvasStore . linearMode ) . toBe ( true )
297+ } )
298+
299+ it ( 'does not set linear mode when template loading fails' , async ( ) => {
300+ mockQueryParams = { template : 'invalid-template' , mode : 'linear' }
301+ mockLoadWorkflowTemplate . mockResolvedValueOnce ( false )
302+
303+ const { loadTemplateFromUrl } = useTemplateUrlLoader ( )
304+ await loadTemplateFromUrl ( )
305+
306+ expect ( mockCanvasStore . linearMode ) . toBe ( false )
307+ } )
308+
309+ it ( 'does not set linear mode when mode parameter is not linear' , async ( ) => {
310+ mockQueryParams = { template : 'flux_simple' , mode : 'graph' }
311+
312+ const { loadTemplateFromUrl } = useTemplateUrlLoader ( )
313+ await loadTemplateFromUrl ( )
314+
315+ expect ( mockLoadWorkflowTemplate ) . toHaveBeenCalledWith (
316+ 'flux_simple' ,
317+ 'default'
318+ )
319+ expect ( mockCanvasStore . linearMode ) . toBe ( false )
320+ } )
321+
322+ it ( 'rejects invalid mode parameter with special characters' , ( ) => {
323+ mockQueryParams = { template : 'flux_simple' , mode : '../malicious' }
324+
325+ const { loadTemplateFromUrl } = useTemplateUrlLoader ( )
326+ void loadTemplateFromUrl ( )
327+
328+ expect ( mockLoadTemplates ) . not . toHaveBeenCalled ( )
329+ } )
330+
331+ it ( 'handles array mode params correctly' , ( ) => {
332+ // Vue Router can return string[] for duplicate params
333+ mockQueryParams = {
334+ template : 'flux_simple' ,
335+ mode : [ 'linear' , 'graph' ] as any
336+ }
337+
338+ const { loadTemplateFromUrl } = useTemplateUrlLoader ( )
339+ void loadTemplateFromUrl ( )
340+
341+ // Should not load when mode param is an array
342+ expect ( mockLoadTemplates ) . not . toHaveBeenCalled ( )
343+ } )
344+
345+ it ( 'warns about unsupported mode values but continues loading' , async ( ) => {
346+ const consoleSpy = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } )
347+ mockQueryParams = { template : 'flux_simple' , mode : 'unsupported' }
348+
349+ const { loadTemplateFromUrl } = useTemplateUrlLoader ( )
350+ await loadTemplateFromUrl ( )
351+
352+ expect ( consoleSpy ) . toHaveBeenCalledWith (
353+ '[useTemplateUrlLoader] Unsupported mode parameter: unsupported. Supported modes: linear'
354+ )
355+ expect ( mockLoadWorkflowTemplate ) . toHaveBeenCalledWith (
356+ 'flux_simple' ,
357+ 'default'
358+ )
359+ expect ( mockCanvasStore . linearMode ) . toBe ( false )
360+
361+ consoleSpy . mockRestore ( )
362+ } )
363+
364+ it ( 'accepts supported mode parameter: linear' , async ( ) => {
365+ mockQueryParams = { template : 'flux_simple' , mode : 'linear' }
366+
367+ const { loadTemplateFromUrl } = useTemplateUrlLoader ( )
368+ await loadTemplateFromUrl ( )
369+
370+ expect ( mockLoadWorkflowTemplate ) . toHaveBeenCalledWith (
371+ 'flux_simple' ,
372+ 'default'
373+ )
374+ expect ( mockCanvasStore . linearMode ) . toBe ( true )
375+ } )
376+
377+ it ( 'accepts valid format but warns about unsupported modes' , async ( ) => {
378+ const consoleSpy = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } )
379+ const unsupportedModes = [ 'graph' , 'mode123' , 'my_mode-2' ]
380+
381+ for ( const mode of unsupportedModes ) {
382+ vi . clearAllMocks ( )
383+ consoleSpy . mockClear ( )
384+ mockCanvasStore . linearMode = false
385+ mockQueryParams = { template : 'flux_simple' , mode }
386+
387+ const { loadTemplateFromUrl } = useTemplateUrlLoader ( )
388+ await loadTemplateFromUrl ( )
389+
390+ expect ( consoleSpy ) . toHaveBeenCalledWith (
391+ `[useTemplateUrlLoader] Unsupported mode parameter: ${ mode } . Supported modes: linear`
392+ )
393+ expect ( mockLoadWorkflowTemplate ) . toHaveBeenCalledWith (
394+ 'flux_simple' ,
395+ 'default'
396+ )
397+ expect ( mockCanvasStore . linearMode ) . toBe ( false )
398+ }
399+
400+ consoleSpy . mockRestore ( )
401+ } )
273402} )
0 commit comments