@@ -8,7 +8,7 @@ import { describe, expect, it } from "vitest";
88import { createQaBusState } from "./bus-state.js" ;
99import { createQaCrablineTransportAdapter } from "./crabline-transport.js" ;
1010
11- function createSelection ( channel : "slack" | "telegram" = "telegram" ) {
11+ function createSelection ( channel : "slack" | "telegram" | "whatsapp" = "telegram" ) {
1212 return {
1313 capabilityMatrixPath : "crabline-fake-provider-capabilities.json" ,
1414 channel,
@@ -160,6 +160,91 @@ describe("crabline transport", () => {
160160 } ) ;
161161 } ) ;
162162
163+ it ( "configures OpenClaw's WhatsApp plugin against a Crabline Baileys WebSocket server" , async ( ) => {
164+ await withTempDir ( "qa-crabline-transport-" , async ( outputDir ) => {
165+ const transport = await createQaCrablineTransportAdapter ( {
166+ outputDir,
167+ selection : createSelection ( "whatsapp" ) ,
168+ state : createQaBusState ( ) ,
169+ } ) ;
170+
171+ try {
172+ expect ( transport . id ) . toBe ( "crabline" ) ;
173+ expect ( transport . requiredPluginIds ) . toEqual ( [ "whatsapp" ] ) ;
174+ expect ( transport . createGatewayConfig ( { baseUrl : "http://127.0.0.1:1" } ) ) . toMatchObject ( {
175+ channels : {
176+ whatsapp : {
177+ allowFrom : [ "*" ] ,
178+ dmPolicy : "open" ,
179+ enabled : true ,
180+ groupAllowFrom : [ "*" ] ,
181+ groupPolicy : "open" ,
182+ } ,
183+ } ,
184+ } ) ;
185+ expect ( transport . buildAgentDelivery ( { target :
"[email protected] " } ) ) . toEqual ( { 186+ channel : "whatsapp" ,
187+ 188+ replyChannel : "whatsapp" ,
189+ 190+ } ) ;
191+ const env = transport . createRuntimeEnvPatch ?.( ) ?? { } ;
192+ expect ( env ) . toMatchObject ( {
193+ CRABLINE_WHATSAPP_ADMIN_TOKEN : expect . any ( String ) ,
194+ CRABLINE_WHATSAPP_RECORDER_PATH : expect . stringMatching ( / w h a t s a p p - f a k e - p r o v i d e r \. j s o n l $ / u) ,
195+ CRABLINE_WHATSAPP_SELF_JID :
"[email protected] " , 196+ OPENCLAW_WHATSAPP_WEB_SOCKET_URL : expect . stringMatching (
197+ / ^ w s : \/ \/ 1 2 7 \. 0 \. 0 \. 1 : \d + \/ c r a b l i n e \/ w h a t s a p p \/ w s \/ c h a t \? a c c e s s _ t o k e n = / u,
198+ ) ,
199+ } ) ;
200+ expect ( env . CRABLINE_WHATSAPP_ACCESS_TOKEN ) . toBeUndefined ( ) ;
201+ expect ( env . CRABLINE_WHATSAPP_API_ROOT ) . toBeUndefined ( ) ;
202+
203+ const manifest = JSON . parse (
204+ await fs . readFile ( path . join ( outputDir , OPENCLAW_CRABLINE_MANIFEST_PATH ) , "utf8" ) ,
205+ ) as {
206+ provider ?: string ;
207+ } ;
208+ expect ( manifest . provider ) . toBe ( "whatsapp" ) ;
209+ } finally {
210+ await transport . cleanup ?.( ) ;
211+ }
212+ } ) ;
213+ } ) ;
214+
215+ it ( "injects WhatsApp inbound messages through Crabline into normalized state" , async ( ) => {
216+ await withTempDir ( "qa-crabline-transport-" , async ( outputDir ) => {
217+ const transport = await createQaCrablineTransportAdapter ( {
218+ outputDir,
219+ selection : createSelection ( "whatsapp" ) ,
220+ state : createQaBusState ( ) ,
221+ } ) ;
222+
223+ try {
224+ const message = await transport . state . addInboundMessage ( {
225+ conversation : {
226+ 227+ kind : "direct" ,
228+ } ,
229+ 230+ senderName : "Alice" ,
231+ text : "WhatsApp baseline marker check." ,
232+ } ) ;
233+ expect ( message ) . toMatchObject ( {
234+ conversation : {
235+ 236+ kind : "direct" ,
237+ } ,
238+ direction : "inbound" ,
239+ 240+ text : "WhatsApp baseline marker check." ,
241+ } ) ;
242+ } finally {
243+ await transport . cleanup ?.( ) ;
244+ }
245+ } ) ;
246+ } ) ;
247+
163248 it ( "injects inbound messages through Crabline and mirrors Telegram sends into normalized state" , async ( ) => {
164249 await withTempDir ( "qa-crabline-transport-" , async ( outputDir ) => {
165250 const transport = await createQaCrablineTransportAdapter ( {
0 commit comments