@@ -73,6 +73,8 @@ type TasksPanelClient = Pick<
7373 | "getTemplateVersionPresets"
7474 | "startWorkspace"
7575 | "stopWorkspace"
76+ | "pauseTask"
77+ | "resumeTask"
7678 | "sendTaskInput"
7779 | "getHost"
7880 | "getWorkspace"
@@ -91,6 +93,8 @@ function createClient(baseUrl = "https://coder.example.com"): MockClient {
9193 getTemplateVersionPresets : vi . fn ( ) . mockResolvedValue ( [ ] ) ,
9294 startWorkspace : vi . fn ( ) . mockResolvedValue ( undefined ) ,
9395 stopWorkspace : vi . fn ( ) . mockResolvedValue ( undefined ) ,
96+ pauseTask : vi . fn ( ) . mockResolvedValue ( undefined ) ,
97+ resumeTask : vi . fn ( ) . mockResolvedValue ( undefined ) ,
9498 sendTaskInput : vi . fn ( ) . mockResolvedValue ( undefined ) ,
9599 getHost : vi . fn ( ) . mockReturnValue ( baseUrl ) ,
96100 getWorkspace : vi . fn ( ) . mockResolvedValue ( workspace ( ) ) ,
@@ -413,40 +417,102 @@ describe("TasksPanelProvider", () => {
413417 } ) ;
414418
415419 describe ( "pauseTask / resumeTask" , ( ) => {
416- interface WorkspaceControlTestCase {
417- method : typeof TasksApi . pauseTask ;
418- clientMethod : keyof MockClient ;
419- taskOverrides : Partial < Task > ;
420- }
421- it . each < WorkspaceControlTestCase > ( [
422- {
423- method : TasksApi . pauseTask ,
424- clientMethod : "stopWorkspace" ,
425- taskOverrides : { workspace_id : "ws-1" } ,
426- } ,
427- {
428- method : TasksApi . resumeTask ,
429- clientMethod : "startWorkspace" ,
430- taskOverrides : { workspace_id : "ws-1" , template_version_id : "tv-1" } ,
431- } ,
432- ] ) (
433- "$method.method calls $clientMethod" ,
434- async ( { method, clientMethod, taskOverrides } ) => {
435- const h = createHarness ( ) ;
436- h . client . getTask . mockResolvedValue ( task ( taskOverrides ) ) ;
420+ it ( "pauseTask calls client.pauseTask" , async ( ) => {
421+ const h = createHarness ( ) ;
422+ h . client . getTask . mockResolvedValue ( task ( { workspace_id : "ws-1" } ) ) ;
437423
438- const res = await h . request ( method , {
439- taskId : "task-1" ,
440- taskName : "Test Task" ,
441- } ) ;
424+ const res = await h . request ( TasksApi . pauseTask , {
425+ taskId : "task-1" ,
426+ taskName : "Test Task" ,
427+ } ) ;
442428
443- expect ( res . success ) . toBe ( true ) ;
444- expect ( h . client [ clientMethod ] ) . toHaveBeenCalled ( ) ;
445- } ,
446- ) ;
429+ expect ( res . success ) . toBe ( true ) ;
430+ expect ( h . client . pauseTask ) . toHaveBeenCalledWith ( "me" , "task-1" ) ;
431+ expect ( h . client . stopWorkspace ) . not . toHaveBeenCalled ( ) ;
432+ } ) ;
433+
434+ it ( "resumeTask calls client.resumeTask" , async ( ) => {
435+ const h = createHarness ( ) ;
436+ h . client . getTask . mockResolvedValue ( task ( { workspace_id : "ws-1" } ) ) ;
437+
438+ const res = await h . request ( TasksApi . resumeTask , {
439+ taskId : "task-1" ,
440+ taskName : "Test Task" ,
441+ } ) ;
442+
443+ expect ( res . success ) . toBe ( true ) ;
444+ expect ( h . client . resumeTask ) . toHaveBeenCalledWith ( "me" , "task-1" ) ;
445+ expect ( h . client . startWorkspace ) . not . toHaveBeenCalled ( ) ;
446+ } ) ;
447+
448+ it ( "pauseTask falls back to stopWorkspace on 404" , async ( ) => {
449+ const h = createHarness ( ) ;
450+ h . client . pauseTask . mockRejectedValue ( createAxiosError ( 404 , "Not found" ) ) ;
451+ h . client . getTask . mockResolvedValue ( task ( { workspace_id : "ws-1" } ) ) ;
452+
453+ const res = await h . request ( TasksApi . pauseTask , {
454+ taskId : "task-1" ,
455+ taskName : "Test Task" ,
456+ } ) ;
457+
458+ expect ( res . success ) . toBe ( true ) ;
459+ expect ( h . client . stopWorkspace ) . toHaveBeenCalledWith ( "ws-1" ) ;
460+ } ) ;
461+
462+ it ( "resumeTask falls back to startWorkspace on 404" , async ( ) => {
463+ const h = createHarness ( ) ;
464+ h . client . resumeTask . mockRejectedValue ( createAxiosError ( 404 , "Not found" ) ) ;
465+ h . client . getTask . mockResolvedValue (
466+ task ( { workspace_id : "ws-1" , template_version_id : "tv-1" } ) ,
467+ ) ;
468+
469+ const res = await h . request ( TasksApi . resumeTask , {
470+ taskId : "task-1" ,
471+ taskName : "Test Task" ,
472+ } ) ;
473+
474+ expect ( res . success ) . toBe ( true ) ;
475+ expect ( h . client . startWorkspace ) . toHaveBeenCalledWith ( "ws-1" , "tv-1" ) ;
476+ } ) ;
477+
478+ it ( "caches legacy fallback after first 404" , async ( ) => {
479+ const h = createHarness ( ) ;
480+ h . client . pauseTask . mockRejectedValue ( createAxiosError ( 404 , "Not found" ) ) ;
481+ h . client . getTask . mockResolvedValue ( task ( { workspace_id : "ws-1" } ) ) ;
482+
483+ await h . request ( TasksApi . pauseTask , {
484+ taskId : "task-1" ,
485+ taskName : "Test Task" ,
486+ } ) ;
487+ h . client . pauseTask . mockClear ( ) ;
488+
489+ await h . request ( TasksApi . pauseTask , {
490+ taskId : "task-1" ,
491+ taskName : "Test Task" ,
492+ } ) ;
493+
494+ expect ( h . client . pauseTask ) . not . toHaveBeenCalled ( ) ;
495+ expect ( h . client . stopWorkspace ) . toHaveBeenCalledTimes ( 2 ) ;
496+ } ) ;
497+
498+ it ( "propagates non-404 errors without fallback" , async ( ) => {
499+ const h = createHarness ( ) ;
500+ h . client . pauseTask . mockRejectedValue (
501+ createAxiosError ( 500 , "Internal server error" ) ,
502+ ) ;
503+
504+ const res = await h . request ( TasksApi . pauseTask , {
505+ taskId : "task-1" ,
506+ taskName : "Test Task" ,
507+ } ) ;
508+
509+ expect ( res . success ) . toBe ( false ) ;
510+ expect ( h . client . stopWorkspace ) . not . toHaveBeenCalled ( ) ;
511+ } ) ;
447512
448- it ( "pauseTask fails when no workspace" , async ( ) => {
513+ it ( "legacy pause fails when task has no workspace" , async ( ) => {
449514 const h = createHarness ( ) ;
515+ h . client . pauseTask . mockRejectedValue ( createAxiosError ( 404 , "Not found" ) ) ;
450516 h . client . getTask . mockResolvedValue ( task ( { workspace_id : null } ) ) ;
451517
452518 const res = await h . request ( TasksApi . pauseTask , {
@@ -719,7 +785,7 @@ describe("TasksPanelProvider", () => {
719785
720786 it ( "shows error notification for user action failures" , async ( ) => {
721787 const h = createHarness ( ) ;
722- h . client . getTask . mockRejectedValue ( new Error ( "Workspace unavailable" ) ) ;
788+ h . client . pauseTask . mockRejectedValue ( new Error ( "Workspace unavailable" ) ) ;
723789
724790 const res = await h . request ( TasksApi . pauseTask , {
725791 taskId : "task-1" ,
0 commit comments