@@ -1493,5 +1493,125 @@ describe("Cline", () => {
14931493 expect ( noModelTask . apiConfiguration . apiProvider ) . toBe ( "openai" )
14941494 } )
14951495 } )
1496+
1497+ describe ( "submitUserMessage" , ( ) => {
1498+ it ( "should always route through webview sendMessage invoke" , async ( ) => {
1499+ const task = new Task ( {
1500+ provider : mockProvider ,
1501+ apiConfiguration : mockApiConfig ,
1502+ task : "initial task" ,
1503+ startTask : false ,
1504+ } )
1505+
1506+ // Set up some existing messages to simulate an ongoing conversation
1507+ task . clineMessages = [
1508+ {
1509+ ts : Date . now ( ) ,
1510+ type : "say" ,
1511+ say : "text" ,
1512+ text : "Initial message" ,
1513+ } ,
1514+ ]
1515+
1516+ // Call submitUserMessage
1517+ task . submitUserMessage ( "test message" , [ "image1.png" ] )
1518+
1519+ // Verify postMessageToWebview was called with sendMessage invoke
1520+ expect ( mockProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
1521+ type : "invoke" ,
1522+ invoke : "sendMessage" ,
1523+ text : "test message" ,
1524+ images : [ "image1.png" ] ,
1525+ } )
1526+ } )
1527+
1528+ it ( "should handle empty messages gracefully" , async ( ) => {
1529+ const task = new Task ( {
1530+ provider : mockProvider ,
1531+ apiConfiguration : mockApiConfig ,
1532+ task : "initial task" ,
1533+ startTask : false ,
1534+ } )
1535+
1536+ // Call with empty text and no images
1537+ task . submitUserMessage ( "" , [ ] )
1538+
1539+ // Should not call postMessageToWebview for empty messages
1540+ expect ( mockProvider . postMessageToWebview ) . not . toHaveBeenCalled ( )
1541+
1542+ // Call with whitespace only
1543+ task . submitUserMessage ( " " , [ ] )
1544+ expect ( mockProvider . postMessageToWebview ) . not . toHaveBeenCalled ( )
1545+ } )
1546+
1547+ it ( "should route through webview for both new and existing tasks" , async ( ) => {
1548+ const task = new Task ( {
1549+ provider : mockProvider ,
1550+ apiConfiguration : mockApiConfig ,
1551+ task : "initial task" ,
1552+ startTask : false ,
1553+ } )
1554+
1555+ // Test with no messages (new task scenario)
1556+ task . clineMessages = [ ]
1557+ task . submitUserMessage ( "new task" , [ "image1.png" ] )
1558+
1559+ expect ( mockProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
1560+ type : "invoke" ,
1561+ invoke : "sendMessage" ,
1562+ text : "new task" ,
1563+ images : [ "image1.png" ] ,
1564+ } )
1565+
1566+ // Clear mock
1567+ mockProvider . postMessageToWebview . mockClear ( )
1568+
1569+ // Test with existing messages (ongoing task scenario)
1570+ task . clineMessages = [
1571+ {
1572+ ts : Date . now ( ) ,
1573+ type : "say" ,
1574+ say : "text" ,
1575+ text : "Initial message" ,
1576+ } ,
1577+ ]
1578+ task . submitUserMessage ( "follow-up message" , [ "image2.png" ] )
1579+
1580+ expect ( mockProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
1581+ type : "invoke" ,
1582+ invoke : "sendMessage" ,
1583+ text : "follow-up message" ,
1584+ images : [ "image2.png" ] ,
1585+ } )
1586+ } )
1587+
1588+ it ( "should handle undefined provider gracefully" , async ( ) => {
1589+ const task = new Task ( {
1590+ provider : mockProvider ,
1591+ apiConfiguration : mockApiConfig ,
1592+ task : "initial task" ,
1593+ startTask : false ,
1594+ } )
1595+
1596+ // Simulate weakref returning undefined
1597+ Object . defineProperty ( task , "providerRef" , {
1598+ value : { deref : ( ) => undefined } ,
1599+ writable : false ,
1600+ configurable : true ,
1601+ } )
1602+
1603+ // Spy on console.error to verify error is logged
1604+ const consoleErrorSpy = vi . spyOn ( console , "error" ) . mockImplementation ( ( ) => { } )
1605+
1606+ // Should log error but not throw
1607+ task . submitUserMessage ( "test message" )
1608+
1609+ expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( "[Task#submitUserMessage] Provider reference lost" )
1610+ expect ( mockProvider . postMessageToWebview ) . not . toHaveBeenCalled ( )
1611+
1612+ // Restore console.error
1613+ consoleErrorSpy . mockRestore ( )
1614+ } )
1615+ } )
14961616 } )
14971617} )
0 commit comments