1+ // npx jest src/core/__tests__/Cline.test.ts
2+
13import { Cline } from "../Cline"
24import { ClineProvider } from "../webview/ClineProvider"
35import { ApiConfiguration , ModelInfo } from "../../shared/api"
@@ -324,8 +326,8 @@ describe("Cline", () => {
324326 } )
325327
326328 describe ( "constructor" , ( ) => {
327- it ( "should respect provided settings" , ( ) => {
328- const cline = new Cline (
329+ it ( "should respect provided settings" , async ( ) => {
330+ const [ cline , task ] = Cline . create (
329331 mockProvider ,
330332 mockApiConfig ,
331333 "custom instructions" ,
@@ -337,10 +339,13 @@ describe("Cline", () => {
337339
338340 expect ( cline . customInstructions ) . toBe ( "custom instructions" )
339341 expect ( cline . diffEnabled ) . toBe ( false )
342+
343+ await cline . abortTask ( true )
344+ await task . catch ( ( ) => { } )
340345 } )
341346
342- it ( "should use default fuzzy match threshold when not provided" , ( ) => {
343- const cline = new Cline (
347+ it ( "should use default fuzzy match threshold when not provided" , async ( ) => {
348+ const [ cline , task ] = await Cline . create (
344349 mockProvider ,
345350 mockApiConfig ,
346351 "custom instructions" ,
@@ -353,12 +358,15 @@ describe("Cline", () => {
353358 expect ( cline . diffEnabled ) . toBe ( true )
354359 // The diff strategy should be created with default threshold (1.0)
355360 expect ( cline . diffStrategy ) . toBeDefined ( )
361+
362+ await cline . abortTask ( true )
363+ await task . catch ( ( ) => { } )
356364 } )
357365
358- it ( "should use provided fuzzy match threshold" , ( ) => {
366+ it ( "should use provided fuzzy match threshold" , async ( ) => {
359367 const getDiffStrategySpy = jest . spyOn ( require ( "../diff/DiffStrategy" ) , "getDiffStrategy" )
360368
361- const cline = new Cline (
369+ const [ cline , task ] = Cline . create (
362370 mockProvider ,
363371 mockApiConfig ,
364372 "custom instructions" ,
@@ -373,12 +381,15 @@ describe("Cline", () => {
373381 expect ( getDiffStrategySpy ) . toHaveBeenCalledWith ( "claude-3-5-sonnet-20241022" , 0.9 , false )
374382
375383 getDiffStrategySpy . mockRestore ( )
384+
385+ await cline . abortTask ( true )
386+ await task . catch ( ( ) => { } )
376387 } )
377388
378- it ( "should pass default threshold to diff strategy when not provided" , ( ) => {
389+ it ( "should pass default threshold to diff strategy when not provided" , async ( ) => {
379390 const getDiffStrategySpy = jest . spyOn ( require ( "../diff/DiffStrategy" ) , "getDiffStrategy" )
380391
381- const cline = new Cline (
392+ const [ cline , task ] = Cline . create (
382393 mockProvider ,
383394 mockApiConfig ,
384395 "custom instructions" ,
@@ -393,6 +404,9 @@ describe("Cline", () => {
393404 expect ( getDiffStrategySpy ) . toHaveBeenCalledWith ( "claude-3-5-sonnet-20241022" , 1.0 , false )
394405
395406 getDiffStrategySpy . mockRestore ( )
407+
408+ await cline . abortTask ( true )
409+ await task . catch ( ( ) => { } )
396410 } )
397411
398412 it ( "should require either task or historyItem" , ( ) => {
@@ -455,7 +469,15 @@ describe("Cline", () => {
455469 } )
456470
457471 it ( "should include timezone information in environment details" , async ( ) => {
458- const cline = new Cline ( mockProvider , mockApiConfig , undefined , false , false , undefined , "test task" )
472+ const [ cline , task ] = Cline . create (
473+ mockProvider ,
474+ mockApiConfig ,
475+ undefined ,
476+ false ,
477+ false ,
478+ undefined ,
479+ "test task" ,
480+ )
459481
460482 const details = await cline [ "getEnvironmentDetails" ] ( false )
461483
@@ -464,11 +486,24 @@ describe("Cline", () => {
464486 expect ( details ) . toMatch ( / U T C - 7 : 0 0 / ) // Fixed offset for America/Los_Angeles
465487 expect ( details ) . toContain ( "# Current Time" )
466488 expect ( details ) . toMatch ( / 1 \/ 1 \/ 2 0 2 4 .* 5 : 0 0 : 0 0 A M .* \( A m e r i c a \/ L o s _ A n g e l e s , U T C - 7 : 0 0 \) / ) // Full time string format
489+
490+ await cline . abortTask ( true )
491+ await task . catch ( ( ) => { } )
467492 } )
468493
469494 describe ( "API conversation handling" , ( ) => {
470495 it ( "should clean conversation history before sending to API" , async ( ) => {
471- const cline = new Cline ( mockProvider , mockApiConfig , undefined , false , false , undefined , "test task" )
496+ const [ cline , task ] = Cline . create (
497+ mockProvider ,
498+ mockApiConfig ,
499+ undefined ,
500+ false ,
501+ false ,
502+ undefined ,
503+ "test task" ,
504+ )
505+ cline . abandoned = true
506+ await task
472507
473508 // Mock the API's createMessage method to capture the conversation history
474509 const createMessageSpy = jest . fn ( )
@@ -576,7 +611,7 @@ describe("Cline", () => {
576611 ]
577612
578613 // Test with model that supports images
579- const clineWithImages = new Cline (
614+ const [ clineWithImages , taskWithImages ] = Cline . create (
580615 mockProvider ,
581616 configWithImages ,
582617 undefined ,
@@ -585,6 +620,7 @@ describe("Cline", () => {
585620 undefined ,
586621 "test task" ,
587622 )
623+
588624 // Mock the model info to indicate image support
589625 jest . spyOn ( clineWithImages . api , "getModel" ) . mockReturnValue ( {
590626 id : "claude-3-sonnet" ,
@@ -598,10 +634,11 @@ describe("Cline", () => {
598634 outputPrice : 0.75 ,
599635 } as ModelInfo ,
600636 } )
637+
601638 clineWithImages . apiConversationHistory = conversationHistory
602639
603640 // Test with model that doesn't support images
604- const clineWithoutImages = new Cline (
641+ const [ clineWithoutImages , taskWithoutImages ] = Cline . create (
605642 mockProvider ,
606643 configWithoutImages ,
607644 undefined ,
@@ -610,6 +647,7 @@ describe("Cline", () => {
610647 undefined ,
611648 "test task" ,
612649 )
650+
613651 // Mock the model info to indicate no image support
614652 jest . spyOn ( clineWithoutImages . api , "getModel" ) . mockReturnValue ( {
615653 id : "gpt-3.5-turbo" ,
@@ -623,6 +661,7 @@ describe("Cline", () => {
623661 outputPrice : 0.2 ,
624662 } as ModelInfo ,
625663 } )
664+
626665 clineWithoutImages . apiConversationHistory = conversationHistory
627666
628667 // Mock abort state for both instances
@@ -631,6 +670,7 @@ describe("Cline", () => {
631670 set : ( ) => { } ,
632671 configurable : true ,
633672 } )
673+
634674 Object . defineProperty ( clineWithoutImages , "abort" , {
635675 get : ( ) => false ,
636676 set : ( ) => { } ,
@@ -645,6 +685,7 @@ describe("Cline", () => {
645685 content ,
646686 "" ,
647687 ] )
688+
648689 // Set up mock streams
649690 const mockStreamWithImages = ( async function * ( ) {
650691 yield { type : "text" , text : "test response" }
@@ -672,6 +713,12 @@ describe("Cline", () => {
672713 } ,
673714 ]
674715
716+ clineWithImages . abandoned = true
717+ await taskWithImages . catch ( ( ) => { } )
718+
719+ clineWithoutImages . abandoned = true
720+ await taskWithoutImages . catch ( ( ) => { } )
721+
675722 // Trigger API requests
676723 await clineWithImages . recursivelyMakeClineRequests ( [ { type : "text" , text : "test request" } ] )
677724 await clineWithoutImages . recursivelyMakeClineRequests ( [ { type : "text" , text : "test request" } ] )
@@ -695,7 +742,15 @@ describe("Cline", () => {
695742 } )
696743
697744 it . skip ( "should handle API retry with countdown" , async ( ) => {
698- const cline = new Cline ( mockProvider , mockApiConfig , undefined , false , false , undefined , "test task" )
745+ const [ cline , task ] = Cline . create (
746+ mockProvider ,
747+ mockApiConfig ,
748+ undefined ,
749+ false ,
750+ false ,
751+ undefined ,
752+ "test task" ,
753+ )
699754
700755 // Mock delay to track countdown timing
701756 const mockDelay = jest . fn ( ) . mockResolvedValue ( undefined )
@@ -809,10 +864,21 @@ describe("Cline", () => {
809864 expect ( errorMessage ) . toBe (
810865 `${ mockError . message } \n\nRetry attempt 1\nRetrying in ${ baseDelay } seconds...` ,
811866 )
867+
868+ await cline . abortTask ( true )
869+ await task . catch ( ( ) => { } )
812870 } )
813871
814872 it . skip ( "should not apply retry delay twice" , async ( ) => {
815- const cline = new Cline ( mockProvider , mockApiConfig , undefined , false , false , undefined , "test task" )
873+ const [ cline , task ] = Cline . create (
874+ mockProvider ,
875+ mockApiConfig ,
876+ undefined ,
877+ false ,
878+ false ,
879+ undefined ,
880+ "test task" ,
881+ )
816882
817883 // Mock delay to track countdown timing
818884 const mockDelay = jest . fn ( ) . mockResolvedValue ( undefined )
@@ -925,11 +991,14 @@ describe("Cline", () => {
925991 undefined ,
926992 false ,
927993 )
994+
995+ await cline . abortTask ( true )
996+ await task . catch ( ( ) => { } )
928997 } )
929998
930999 describe ( "loadContext" , ( ) => {
9311000 it ( "should process mentions in task and feedback tags" , async ( ) => {
932- const cline = new Cline (
1001+ const [ cline , task ] = Cline . create (
9331002 mockProvider ,
9341003 mockApiConfig ,
9351004 undefined ,
@@ -1002,6 +1071,9 @@ describe("Cline", () => {
10021071 const toolResult2 = processedContent [ 3 ] as Anthropic . ToolResultBlockParam
10031072 const content2 = Array . isArray ( toolResult2 . content ) ? toolResult2 . content [ 0 ] : toolResult2 . content
10041073 expect ( ( content2 as Anthropic . TextBlockParam ) . text ) . toBe ( "Regular tool result with @/path" )
1074+
1075+ await cline . abortTask ( true )
1076+ await task . catch ( ( ) => { } )
10051077 } )
10061078 } )
10071079 } )
0 commit comments