@@ -1563,6 +1563,77 @@ describe("postMessage", () => {
15631563
15641564 spy . mockRestore ( ) ;
15651565 } ) ;
1566+
1567+ it ( "does not include content text when posting a card message" , async ( ) => {
1568+ const mockResponse = new Response (
1569+ JSON . stringify ( {
1570+ id : "msg005" ,
1571+ channel_id : "channel456" ,
1572+ content : "" ,
1573+ timestamp : "2021-01-01T00:00:00.000Z" ,
1574+ author : { id : "test-app-id" , username : "bot" } ,
1575+ } ) ,
1576+ { status : 200 , headers : { "Content-Type" : "application/json" } }
1577+ ) ;
1578+ const spy = vi
1579+ . spyOn ( adapter as any , "discordFetch" )
1580+ . mockResolvedValue ( mockResponse ) ;
1581+
1582+ const cardMessage = {
1583+ card : Card ( {
1584+ title : "Test Card" ,
1585+ children : [ Actions ( [ Button ( { id : "btn1" , label : "Click me" } ) ] ) ] ,
1586+ } ) ,
1587+ } ;
1588+
1589+ await adapter . postMessage ( "discord:guild1:channel456" , cardMessage ) ;
1590+
1591+ const calledPayload = spy . mock . calls [ 0 ] ?. [ 2 ] as {
1592+ content ?: string ;
1593+ embeds ?: unknown [ ] ;
1594+ components ?: unknown [ ] ;
1595+ } ;
1596+ expect ( calledPayload . content ) . toBeUndefined ( ) ;
1597+ expect ( calledPayload . embeds ) . toBeDefined ( ) ;
1598+ expect ( calledPayload . components ) . toBeDefined ( ) ;
1599+
1600+ spy . mockRestore ( ) ;
1601+ } ) ;
1602+
1603+ it ( "uses card over text when message has both" , async ( ) => {
1604+ const mockResponse = new Response (
1605+ JSON . stringify ( {
1606+ id : "msg006" ,
1607+ channel_id : "channel456" ,
1608+ content : "" ,
1609+ timestamp : "2021-01-01T00:00:00.000Z" ,
1610+ author : { id : "test-app-id" , username : "bot" } ,
1611+ } ) ,
1612+ { status : 200 , headers : { "Content-Type" : "application/json" } }
1613+ ) ;
1614+ const spy = vi
1615+ . spyOn ( adapter as any , "discordFetch" )
1616+ . mockResolvedValue ( mockResponse ) ;
1617+
1618+ const mixedMessage = {
1619+ raw : "Some text that should be ignored" ,
1620+ card : Card ( {
1621+ title : "Card Wins" ,
1622+ children : [ Actions ( [ Button ( { id : "btn1" , label : "Click" } ) ] ) ] ,
1623+ } ) ,
1624+ } ;
1625+
1626+ await adapter . postMessage ( "discord:guild1:channel456" , mixedMessage ) ;
1627+
1628+ const calledPayload = spy . mock . calls [ 0 ] ?. [ 2 ] as {
1629+ content ?: string ;
1630+ embeds ?: unknown [ ] ;
1631+ } ;
1632+ expect ( calledPayload . content ) . toBeUndefined ( ) ;
1633+ expect ( calledPayload . embeds ) . toBeDefined ( ) ;
1634+
1635+ spy . mockRestore ( ) ;
1636+ } ) ;
15661637} ) ;
15671638
15681639// ============================================================================
@@ -1669,6 +1740,77 @@ describe("editMessage", () => {
16691740
16701741 spy . mockRestore ( ) ;
16711742 } ) ;
1743+
1744+ it ( "clears content when editing to a card message" , async ( ) => {
1745+ const mockResponse = new Response (
1746+ JSON . stringify ( {
1747+ id : "msg004" ,
1748+ channel_id : "channel456" ,
1749+ content : "" ,
1750+ timestamp : "2021-01-01T00:00:00.000Z" ,
1751+ author : { id : "test-app-id" , username : "bot" } ,
1752+ } ) ,
1753+ { status : 200 , headers : { "Content-Type" : "application/json" } }
1754+ ) ;
1755+ const spy = vi
1756+ . spyOn ( adapter as any , "discordFetch" )
1757+ . mockResolvedValue ( mockResponse ) ;
1758+
1759+ const cardMessage = {
1760+ card : Card ( {
1761+ title : "Test Card" ,
1762+ children : [ Actions ( [ Button ( { id : "btn1" , label : "Click me" } ) ] ) ] ,
1763+ } ) ,
1764+ } ;
1765+
1766+ await adapter . editMessage (
1767+ "discord:guild1:channel456" ,
1768+ "msg004" ,
1769+ cardMessage
1770+ ) ;
1771+
1772+ const calledPayload = spy . mock . calls [ 0 ] ?. [ 2 ] as {
1773+ content ?: string ;
1774+ embeds ?: unknown [ ] ;
1775+ components ?: unknown [ ] ;
1776+ } ;
1777+ expect ( calledPayload . content ) . toBe ( "" ) ;
1778+ expect ( calledPayload . embeds ) . toBeDefined ( ) ;
1779+ expect ( calledPayload . components ) . toBeDefined ( ) ;
1780+
1781+ spy . mockRestore ( ) ;
1782+ } ) ;
1783+
1784+ it ( "restores content when editing from card back to text" , async ( ) => {
1785+ const mockResponse = new Response (
1786+ JSON . stringify ( {
1787+ id : "msg004" ,
1788+ channel_id : "channel456" ,
1789+ content : "New text message" ,
1790+ timestamp : "2021-01-01T00:00:00.000Z" ,
1791+ author : { id : "test-app-id" , username : "bot" } ,
1792+ } ) ,
1793+ { status : 200 , headers : { "Content-Type" : "application/json" } }
1794+ ) ;
1795+ const spy = vi
1796+ . spyOn ( adapter as any , "discordFetch" )
1797+ . mockResolvedValue ( mockResponse ) ;
1798+
1799+ await adapter . editMessage ( "discord:guild1:channel456" , "msg004" , {
1800+ raw : "Updated to plain text" ,
1801+ } ) ;
1802+
1803+ const calledPayload = spy . mock . calls [ 0 ] ?. [ 2 ] as {
1804+ content ?: string ;
1805+ embeds ?: unknown [ ] ;
1806+ components ?: unknown [ ] ;
1807+ } ;
1808+ expect ( calledPayload . content ) . toBe ( "Updated to plain text" ) ;
1809+ expect ( calledPayload . embeds ) . toBeUndefined ( ) ;
1810+ expect ( calledPayload . components ) . toBeUndefined ( ) ;
1811+
1812+ spy . mockRestore ( ) ;
1813+ } ) ;
16721814} ) ;
16731815
16741816// ============================================================================
@@ -2578,9 +2720,12 @@ describe("postChannelMessage", () => {
25782720 await adapter . postChannelMessage ( "discord:guild1:channel456" , cardMessage ) ;
25792721
25802722 const calledPayload = spy . mock . calls [ 0 ] ?. [ 2 ] as {
2723+ content ?: string ;
25812724 embeds ?: unknown [ ] ;
25822725 components ?: unknown [ ] ;
25832726 } ;
2727+ // Should NOT include content text when card is present (avoids duplicate display)
2728+ expect ( calledPayload . content ) . toBeUndefined ( ) ;
25842729 expect ( calledPayload . embeds ) . toBeDefined ( ) ;
25852730 expect ( Array . isArray ( calledPayload . embeds ) ) . toBe ( true ) ;
25862731 expect ( ( calledPayload . embeds ?? [ ] ) . length ) . toBeGreaterThan ( 0 ) ;
0 commit comments