@@ -4788,4 +4788,231 @@ describe('beforePasswordResetRequest hook', () => {
47884788 Parse . Cloud . beforePasswordResetRequest ( Parse . User , ( ) => { } ) ;
47894789 } ) . not . toThrow ( ) ;
47904790 } ) ;
4791+
4792+ describe ( 'Express-style cloud functions with (req, res) parameters' , ( ) => {
4793+ it ( 'should support express-style cloud function with res.success()' , async ( ) => {
4794+ Parse . Cloud . define ( 'expressStyleFunction' , ( req , res ) => {
4795+ res . success ( { message : 'Hello from express style!' } ) ;
4796+ } ) ;
4797+
4798+ const result = await Parse . Cloud . run ( 'expressStyleFunction' , { } ) ;
4799+ expect ( result . message ) . toEqual ( 'Hello from express style!' ) ;
4800+ } ) ;
4801+
4802+ it ( 'should support express-style cloud function with res.error()' , async ( ) => {
4803+ Parse . Cloud . define ( 'expressStyleError' , ( req , res ) => {
4804+ res . error ( 'Custom error message' ) ;
4805+ } ) ;
4806+
4807+ await expectAsync ( Parse . Cloud . run ( 'expressStyleError' , { } ) ) . toBeRejectedWith (
4808+ new Parse . Error ( Parse . Error . SCRIPT_FAILED , 'Custom error message' )
4809+ ) ;
4810+ } ) ;
4811+
4812+ it ( 'should support setting custom HTTP status code with res.status().success()' , async ( ) => {
4813+ Parse . Cloud . define ( 'customStatusCode' , ( req , res ) => {
4814+ res . status ( 201 ) . success ( { created : true } ) ;
4815+ } ) ;
4816+
4817+ const response = await request ( {
4818+ method : 'POST' ,
4819+ url : 'http://localhost:8378/1/functions/customStatusCode' ,
4820+ headers : {
4821+ 'X-Parse-Application-Id' : 'test' ,
4822+ 'X-Parse-REST-API-Key' : 'rest' ,
4823+ } ,
4824+ json : true ,
4825+ body : { } ,
4826+ } ) ;
4827+
4828+ expect ( response . status ) . toBe ( 201 ) ;
4829+ expect ( response . data . result . created ) . toBe ( true ) ;
4830+ } ) ;
4831+
4832+ it ( 'should support 401 unauthorized status code with error' , async ( ) => {
4833+ Parse . Cloud . define ( 'unauthorizedFunction' , ( req , res ) => {
4834+ if ( ! req . user ) {
4835+ res . status ( 401 ) . error ( 'Unauthorized access' ) ;
4836+ } else {
4837+ res . success ( { message : 'Authorized' } ) ;
4838+ }
4839+ } ) ;
4840+
4841+ await expectAsync (
4842+ request ( {
4843+ method : 'POST' ,
4844+ url : 'http://localhost:8378/1/functions/unauthorizedFunction' ,
4845+ headers : {
4846+ 'X-Parse-Application-Id' : 'test' ,
4847+ 'X-Parse-REST-API-Key' : 'rest' ,
4848+ } ,
4849+ json : true ,
4850+ body : { } ,
4851+ } )
4852+ ) . toBeRejected ( ) ;
4853+ } ) ;
4854+
4855+ it ( 'should support 404 not found status code with error' , async ( ) => {
4856+ Parse . Cloud . define ( 'notFoundFunction' , ( req , res ) => {
4857+ res . status ( 404 ) . error ( 'Resource not found' ) ;
4858+ } ) ;
4859+
4860+ await expectAsync (
4861+ request ( {
4862+ method : 'POST' ,
4863+ url : 'http://localhost:8378/1/functions/notFoundFunction' ,
4864+ headers : {
4865+ 'X-Parse-Application-Id' : 'test' ,
4866+ 'X-Parse-REST-API-Key' : 'rest' ,
4867+ } ,
4868+ json : true ,
4869+ body : { } ,
4870+ } )
4871+ ) . toBeRejected ( ) ;
4872+ } ) ;
4873+
4874+ it ( 'should default to 200 status code when not specified' , async ( ) => {
4875+ Parse . Cloud . define ( 'defaultStatusCode' , ( req , res ) => {
4876+ res . success ( { message : 'Default status' } ) ;
4877+ } ) ;
4878+
4879+ const response = await request ( {
4880+ method : 'POST' ,
4881+ url : 'http://localhost:8378/1/functions/defaultStatusCode' ,
4882+ headers : {
4883+ 'X-Parse-Application-Id' : 'test' ,
4884+ 'X-Parse-REST-API-Key' : 'rest' ,
4885+ } ,
4886+ json : true ,
4887+ body : { } ,
4888+ } ) ;
4889+
4890+ expect ( response . status ) . toBe ( 200 ) ;
4891+ expect ( response . data . result . message ) . toBe ( 'Default status' ) ;
4892+ } ) ;
4893+
4894+ it ( 'should maintain backward compatibility with single-parameter functions' , async ( ) => {
4895+ Parse . Cloud . define ( 'traditionalFunction' , ( req ) => {
4896+ return { message : 'Traditional style works!' } ;
4897+ } ) ;
4898+
4899+ const result = await Parse . Cloud . run ( 'traditionalFunction' , { } ) ;
4900+ expect ( result . message ) . toEqual ( 'Traditional style works!' ) ;
4901+ } ) ;
4902+
4903+ it ( 'should maintain backward compatibility with implicit return functions' , async ( ) => {
4904+ Parse . Cloud . define ( 'implicitReturnFunction' , ( ) => 'Implicit return works!' ) ;
4905+
4906+ const result = await Parse . Cloud . run ( 'implicitReturnFunction' , { } ) ;
4907+ expect ( result ) . toEqual ( 'Implicit return works!' ) ;
4908+ } ) ;
4909+
4910+ it ( 'should support async express-style functions' , async ( ) => {
4911+ Parse . Cloud . define ( 'asyncExpressStyle' , async ( req , res ) => {
4912+ await new Promise ( resolve => setTimeout ( resolve , 10 ) ) ;
4913+ res . success ( { async : true } ) ;
4914+ } ) ;
4915+
4916+ const result = await Parse . Cloud . run ( 'asyncExpressStyle' , { } ) ;
4917+ expect ( result . async ) . toBe ( true ) ;
4918+ } ) ;
4919+
4920+ it ( 'should access request parameters in express-style functions' , async ( ) => {
4921+ Parse . Cloud . define ( 'expressWithParams' , ( req , res ) => {
4922+ const { name } = req . params ;
4923+ res . success ( { greeting : `Hello, ${ name } !` } ) ;
4924+ } ) ;
4925+
4926+ const result = await Parse . Cloud . run ( 'expressWithParams' , { name : 'World' } ) ;
4927+ expect ( result . greeting ) . toEqual ( 'Hello, World!' ) ;
4928+ } ) ;
4929+
4930+ it ( 'should access user in express-style functions' , async ( ) => {
4931+ const user = new Parse . User ( ) ;
4932+ user . set ( 'username' , 'testuser' ) ;
4933+ user . set ( 'password' , 'testpass' ) ;
4934+ await user . signUp ( ) ;
4935+
4936+ Parse . Cloud . define ( 'expressWithUser' , ( req , res ) => {
4937+ if ( req . user ) {
4938+ res . success ( { username : req . user . get ( 'username' ) } ) ;
4939+ } else {
4940+ res . status ( 401 ) . error ( 'Not authenticated' ) ;
4941+ }
4942+ } ) ;
4943+
4944+ const result = await Parse . Cloud . run ( 'expressWithUser' , { } ) ;
4945+ expect ( result . username ) . toEqual ( 'testuser' ) ;
4946+
4947+ await Parse . User . logOut ( ) ;
4948+ } ) ;
4949+
4950+ it ( 'should support setting custom headers with res.header()' , async ( ) => {
4951+ Parse . Cloud . define ( 'customHeaderFunction' , ( req , res ) => {
4952+ res . header ( 'X-Custom-Header' , 'custom-value' ) . success ( { message : 'OK' } ) ;
4953+ } ) ;
4954+
4955+ const response = await request ( {
4956+ method : 'POST' ,
4957+ url : 'http://localhost:8378/1/functions/customHeaderFunction' ,
4958+ headers : {
4959+ 'X-Parse-Application-Id' : 'test' ,
4960+ 'X-Parse-REST-API-Key' : 'rest' ,
4961+ } ,
4962+ json : true ,
4963+ body : { } ,
4964+ } ) ;
4965+
4966+ expect ( response . status ) . toBe ( 200 ) ;
4967+ expect ( response . headers [ 'x-custom-header' ] ) . toBe ( 'custom-value' ) ;
4968+ expect ( response . data . result . message ) . toBe ( 'OK' ) ;
4969+ } ) ;
4970+
4971+ it ( 'should support setting multiple custom headers' , async ( ) => {
4972+ Parse . Cloud . define ( 'multipleHeadersFunction' , ( req , res ) => {
4973+ res . header ( 'X-Header-One' , 'value1' )
4974+ . header ( 'X-Header-Two' , 'value2' )
4975+ . success ( { message : 'Multiple headers' } ) ;
4976+ } ) ;
4977+
4978+ const response = await request ( {
4979+ method : 'POST' ,
4980+ url : 'http://localhost:8378/1/functions/multipleHeadersFunction' ,
4981+ headers : {
4982+ 'X-Parse-Application-Id' : 'test' ,
4983+ 'X-Parse-REST-API-Key' : 'rest' ,
4984+ } ,
4985+ json : true ,
4986+ body : { } ,
4987+ } ) ;
4988+
4989+ expect ( response . status ) . toBe ( 200 ) ;
4990+ expect ( response . headers [ 'x-header-one' ] ) . toBe ( 'value1' ) ;
4991+ expect ( response . headers [ 'x-header-two' ] ) . toBe ( 'value2' ) ;
4992+ expect ( response . data . result . message ) . toBe ( 'Multiple headers' ) ;
4993+ } ) ;
4994+
4995+ it ( 'should support combining status code and custom headers' , async ( ) => {
4996+ Parse . Cloud . define ( 'statusAndHeaderFunction' , ( req , res ) => {
4997+ res . status ( 201 )
4998+ . header ( 'X-Resource-Id' , '12345' )
4999+ . success ( { created : true } ) ;
5000+ } ) ;
5001+
5002+ const response = await request ( {
5003+ method : 'POST' ,
5004+ url : 'http://localhost:8378/1/functions/statusAndHeaderFunction' ,
5005+ headers : {
5006+ 'X-Parse-Application-Id' : 'test' ,
5007+ 'X-Parse-REST-API-Key' : 'rest' ,
5008+ } ,
5009+ json : true ,
5010+ body : { } ,
5011+ } ) ;
5012+
5013+ expect ( response . status ) . toBe ( 201 ) ;
5014+ expect ( response . headers [ 'x-resource-id' ] ) . toBe ( '12345' ) ;
5015+ expect ( response . data . result . created ) . toBe ( true ) ;
5016+ } ) ;
5017+ } ) ;
47915018} ) ;
0 commit comments