@@ -24,10 +24,19 @@ describe('Custom Integrations Module', () => {
2424 nock . cleanAll ( ) ;
2525 } ) ;
2626
27- test ( 'custom.call() should send POST request to correct endpoint ' , async ( ) => {
27+ test ( 'custom.call() should convert camelCase params to snake_case for backend ' , async ( ) => {
2828 const slug = 'github' ;
2929 const operationId = 'listIssues' ;
30- const params = {
30+
31+ // SDK call uses camelCase (JS convention)
32+ const sdkParams = {
33+ payload : { title : 'Test Issue' } ,
34+ pathParams : { owner : 'testuser' , repo : 'testrepo' } ,
35+ queryParams : { state : 'open' } ,
36+ } ;
37+
38+ // Backend expects snake_case (Python convention)
39+ const expectedBody = {
3140 payload : { title : 'Test Issue' } ,
3241 path_params : { owner : 'testuser' , repo : 'testrepo' } ,
3342 query_params : { state : 'open' } ,
@@ -39,13 +48,13 @@ describe('Custom Integrations Module', () => {
3948 data : { issues : [ { id : 1 , title : 'Test Issue' } ] } ,
4049 } ;
4150
42- // Mock the API response
51+ // Mock expects snake_case body
4352 scope
44- . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , params )
53+ . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , expectedBody )
4554 . reply ( 200 , mockResponse ) ;
4655
47- // Call the API
48- const result = await base44 . integrations . custom . call ( slug , operationId , params ) ;
56+ // SDK call uses camelCase
57+ const result = await base44 . integrations . custom . call ( slug , operationId , sdkParams ) ;
4958
5059 // Verify the response
5160 expect ( result . success ) . toBe ( true ) ;
@@ -195,7 +204,7 @@ describe('Custom Integrations Module', () => {
195204 metadata : { key : `value_${ i } ` } ,
196205 } ) ) ;
197206
198- const params = {
207+ const sdkParams = {
199208 payload : { items : largeArray } ,
200209 } ;
201210
@@ -207,11 +216,11 @@ describe('Custom Integrations Module', () => {
207216
208217 // Mock the API response
209218 scope
210- . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , params )
219+ . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , sdkParams )
211220 . reply ( 200 , mockResponse ) ;
212221
213222 // Call the API with large payload
214- const result = await base44 . integrations . custom . call ( slug , operationId , params ) ;
223+ const result = await base44 . integrations . custom . call ( slug , operationId , sdkParams ) ;
215224
216225 // Verify the response
217226 expect ( result . success ) . toBe ( true ) ;
@@ -224,7 +233,7 @@ describe('Custom Integrations Module', () => {
224233 test ( 'custom.call() should include custom headers in request' , async ( ) => {
225234 const slug = 'myapi' ;
226235 const operationId = 'getData' ;
227- const params = {
236+ const sdkParams = {
228237 headers : { 'X-Custom-Header' : 'custom-value' } ,
229238 } ;
230239
@@ -236,11 +245,11 @@ describe('Custom Integrations Module', () => {
236245
237246 // Mock the API response
238247 scope
239- . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , params )
248+ . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , sdkParams )
240249 . reply ( 200 , mockResponse ) ;
241250
242251 // Call the API
243- const result = await base44 . integrations . custom . call ( slug , operationId , params ) ;
252+ const result = await base44 . integrations . custom . call ( slug , operationId , sdkParams ) ;
244253
245254 // Verify the response
246255 expect ( result . success ) . toBe ( true ) ;
@@ -252,7 +261,7 @@ describe('Custom Integrations Module', () => {
252261 test ( 'custom.call() should pass through multiple headers' , async ( ) => {
253262 const slug = 'myapi' ;
254263 const operationId = 'secureEndpoint' ;
255- const params = {
264+ const sdkParams = {
256265 headers : {
257266 'X-API-Key' : 'secret-key-123' ,
258267 'X-Request-ID' : 'req-456' ,
@@ -269,11 +278,11 @@ describe('Custom Integrations Module', () => {
269278
270279 // Mock the API response - verify all headers are passed in the body
271280 scope
272- . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , params )
281+ . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , sdkParams )
273282 . reply ( 200 , mockResponse ) ;
274283
275284 // Call the API
276- const result = await base44 . integrations . custom . call ( slug , operationId , params ) ;
285+ const result = await base44 . integrations . custom . call ( slug , operationId , sdkParams ) ;
277286
278287 // Verify the response
279288 expect ( result . success ) . toBe ( true ) ;
@@ -283,6 +292,36 @@ describe('Custom Integrations Module', () => {
283292 expect ( scope . isDone ( ) ) . toBe ( true ) ;
284293 } ) ;
285294
295+ test ( 'custom.call() should only include defined params in body' , async ( ) => {
296+ const slug = 'github' ;
297+ const operationId = 'getUser' ;
298+
299+ // SDK call with only pathParams
300+ const sdkParams = {
301+ pathParams : { username : 'octocat' } ,
302+ } ;
303+
304+ // Expected body should only have path_params, not empty payload/query_params/headers
305+ const expectedBody = {
306+ path_params : { username : 'octocat' } ,
307+ } ;
308+
309+ const mockResponse = {
310+ success : true ,
311+ status_code : 200 ,
312+ data : { login : 'octocat' } ,
313+ } ;
314+
315+ scope
316+ . post ( `/api/apps/${ appId } /integrations/custom/${ slug } /${ operationId } ` , expectedBody )
317+ . reply ( 200 , mockResponse ) ;
318+
319+ const result = await base44 . integrations . custom . call ( slug , operationId , sdkParams ) ;
320+
321+ expect ( result . success ) . toBe ( true ) ;
322+ expect ( scope . isDone ( ) ) . toBe ( true ) ;
323+ } ) ;
324+
286325 test ( 'custom property should not interfere with other integration packages' , async ( ) => {
287326 // Test that Core still works
288327 const coreParams = {
0 commit comments