2016-01-28 10:58:12 -08:00
// A bunch of different tests are in here - it isn't very thematic.
// It would probably be better to refactor them into different files.
2016-02-23 22:00:48 -08:00
'use strict' ;
2016-01-28 10:58:12 -08:00
2018-09-24 17:07:51 -04:00
const request = require ( '../lib/request' ) ;
2018-09-01 13:58:06 -04:00
const Parse = require ( 'parse/node' ) ;
2018-07-02 23:30:14 -04:00
const Config = require ( '../lib/Config' ) ;
const SchemaController = require ( '../lib/Controllers/SchemaController' ) ;
2025-11-23 13:51:42 +01:00
const { destroyAllDataPermanently } = require ( '../lib/TestUtils' ) ;
2016-06-10 20:27:21 -07:00
2018-09-01 13:58:06 -04:00
const userSchema = SchemaController . convertSchemaToAdapterSchema ( {
className : '_User' ,
fields : Object . assign (
{ } ,
SchemaController . defaultColumns . _Default ,
SchemaController . defaultColumns . _User
) ,
} ) ;
2018-08-05 13:58:07 -04:00
const headers = {
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
'X-Parse-REST-API-Key' : 'rest' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Installation-Id' : 'yolo' ,
} ;
2016-01-28 10:58:12 -08:00
2021-10-18 10:51:56 -04:00
describe ( 'miscellaneous' , ( ) => {
2021-01-13 12:40:18 -05:00
it ( 'db contains document after successful save' , async ( ) => {
const obj = new Parse . Object ( 'TestObject' ) ;
obj . set ( 'foo' , 'bar' ) ;
await obj . save ( ) ;
const config = Config . get ( defaultConfiguration . appId ) ;
const results = await config . database . adapter . find ( 'TestObject' , { fields : { } } , { } , { } ) ;
expect ( results . length ) . toEqual ( 1 ) ;
expect ( results [ 0 ] [ 'foo' ] ) . toEqual ( 'bar' ) ;
2016-08-15 16:48:39 -04:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'create a GameScore object' , function ( done ) {
2018-02-17 09:55:30 -05:00
const obj = new Parse . Object ( 'GameScore' ) ;
2016-01-28 10:58:12 -08:00
obj . set ( 'score' , 1337 ) ;
2020-10-26 04:36:54 +11:00
obj . save ( ) . then ( function ( obj ) {
2016-01-28 10:58:12 -08:00
expect ( typeof obj . id ) . toBe ( 'string' ) ;
expect ( typeof obj . createdAt . toGMTString ( ) ) . toBe ( 'string' ) ;
done ( ) ;
2018-08-05 13:58:07 -04:00
} , done . fail ) ;
2016-01-28 10:58:12 -08:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'get a TestObject' , function ( done ) {
create ( { bloop : 'blarg' } , async function ( obj ) {
2018-02-17 09:55:30 -05:00
const t2 = new TestObject ( { objectId : obj . id } ) ;
2018-08-05 13:58:07 -04:00
const obj2 = await t2 . fetch ( ) ;
expect ( obj2 . get ( 'bloop' ) ) . toEqual ( 'blarg' ) ;
expect ( obj2 . id ) . toBeTruthy ( ) ;
expect ( obj2 . id ) . toEqual ( obj . id ) ;
done ( ) ;
2016-01-28 10:58:12 -08:00
} ) ;
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'create a valid parse user' , function ( done ) {
createTestUser ( ) . then ( function ( data ) {
2016-01-28 10:58:12 -08:00
expect ( data . id ) . not . toBeUndefined ( ) ;
expect ( data . getSessionToken ( ) ) . not . toBeUndefined ( ) ;
expect ( data . get ( 'password' ) ) . toBeUndefined ( ) ;
done ( ) ;
2018-08-05 13:58:07 -04:00
} , done . fail ) ;
2016-01-28 10:58:12 -08:00
} ) ;
2018-08-05 13:58:07 -04:00
it ( 'fail to create a duplicate username' , async ( ) => {
2021-03-13 09:05:22 -06:00
await reconfigureServer ( ) ;
2016-06-10 20:27:21 -07:00
let numFailed = 0 ;
2018-08-05 13:58:07 -04:00
let numCreated = 0 ;
2018-09-24 17:07:51 -04:00
const p1 = request ( {
method : 'POST' ,
url : Parse . serverURL + '/users' ,
body : {
password : 'asdf' ,
username : 'u1' ,
email : 'dupe@dupe.dupe' ,
} ,
headers ,
} ) . then (
( ) => {
numCreated ++ ;
expect ( numCreated ) . toEqual ( 1 ) ;
} ,
response => {
numFailed ++ ;
expect ( response . data . code ) . toEqual ( Parse . Error . USERNAME _TAKEN ) ;
}
) ;
2018-09-01 13:58:06 -04:00
2018-09-24 17:07:51 -04:00
const p2 = request ( {
method : 'POST' ,
url : Parse . serverURL + '/users' ,
body : {
password : 'otherpassword' ,
username : 'u1' ,
email : 'email@other.email' ,
} ,
headers ,
} ) . then (
( ) => {
numCreated ++ ;
} ,
( { data } ) => {
numFailed ++ ;
expect ( data . code ) . toEqual ( Parse . Error . USERNAME _TAKEN ) ;
}
) ;
2018-08-05 13:58:07 -04:00
2018-09-01 13:58:06 -04:00
await Promise . all ( [ p1 , p2 ] ) ;
2018-08-05 13:58:07 -04:00
expect ( numFailed ) . toEqual ( 1 ) ;
expect ( numCreated ) . toBe ( 1 ) ;
2016-06-10 20:27:21 -07:00
} ) ;
2018-08-05 13:58:07 -04:00
it ( 'ensure that email is uniquely indexed' , async ( ) => {
2021-03-13 09:05:22 -06:00
await reconfigureServer ( ) ;
2016-06-10 20:27:21 -07:00
let numFailed = 0 ;
2016-06-13 00:57:23 -07:00
let numCreated = 0 ;
2018-09-24 17:07:51 -04:00
const p1 = request ( {
method : 'POST' ,
url : Parse . serverURL + '/users' ,
body : {
password : 'asdf' ,
username : 'u1' ,
email : 'dupe@dupe.dupe' ,
} ,
headers ,
} ) . then (
( ) => {
numCreated ++ ;
expect ( numCreated ) . toEqual ( 1 ) ;
} ,
( { data } ) => {
numFailed ++ ;
expect ( data . code ) . toEqual ( Parse . Error . EMAIL _TAKEN ) ;
}
) ;
2018-09-01 13:58:06 -04:00
2018-09-24 17:07:51 -04:00
const p2 = request ( {
url : Parse . serverURL + '/users' ,
method : 'POST' ,
body : {
password : 'asdf' ,
username : 'u2' ,
email : 'dupe@dupe.dupe' ,
} ,
headers ,
} ) . then (
( ) => {
numCreated ++ ;
expect ( numCreated ) . toEqual ( 1 ) ;
} ,
( { data } ) => {
numFailed ++ ;
expect ( data . code ) . toEqual ( Parse . Error . EMAIL _TAKEN ) ;
}
) ;
2016-06-10 20:27:21 -07:00
2018-09-01 13:58:06 -04:00
await Promise . all ( [ p1 , p2 ] ) ;
2018-08-05 13:58:07 -04:00
expect ( numFailed ) . toEqual ( 1 ) ;
expect ( numCreated ) . toBe ( 1 ) ;
2016-06-10 20:27:21 -07:00
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( 'be1b9ac7-5e5f-4e91-b044-2bd8fb7622ad' ) ( it ) ( 'ensure that if people already have duplicate users, they can still sign up new users' , async done => {
2018-08-05 13:58:07 -04:00
try {
await Parse . User . logOut ( ) ;
2018-09-01 13:58:06 -04:00
} catch ( e ) {
/* ignore */
}
2017-10-23 08:43:05 -04:00
const config = Config . get ( 'test' ) ;
2016-06-10 20:27:21 -07:00
// Remove existing data to clear out unique index
2025-11-23 13:51:42 +01:00
destroyAllDataPermanently ( )
2021-03-10 13:31:35 -06:00
. then ( ( ) => config . database . adapter . performInitialization ( { VolatileClassesSchemas : [ ] } ) )
2017-06-20 09:15:26 -07:00
. then ( ( ) => config . database . adapter . createClass ( '_User' , userSchema ) )
2018-09-01 13:58:06 -04:00
. then ( ( ) =>
config . database . adapter
. createObject ( '_User' , userSchema , { objectId : 'x' , username : 'u' } )
. catch ( fail )
)
. then ( ( ) =>
config . database . adapter
. createObject ( '_User' , userSchema , { objectId : 'y' , username : 'u' } )
. catch ( fail )
)
// Create a new server to try to recreate the unique indexes
2017-06-20 09:15:26 -07:00
. then ( reconfigureServer )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . DUPLICATE _VALUE ) ;
const user = new Parse . User ( ) ;
user . setPassword ( 'asdf' ) ;
user . setUsername ( 'zxcv' ) ;
return user . signUp ( ) . catch ( fail ) ;
} )
. then ( ( ) => {
const user = new Parse . User ( ) ;
user . setPassword ( 'asdf' ) ;
user . setUsername ( 'u' ) ;
2018-09-01 13:58:06 -04:00
return user . signUp ( ) ;
2017-06-20 09:15:26 -07:00
} )
. then ( ( ) => {
fail ( 'should not have been able to sign up' ) ;
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . USERNAME _TAKEN ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} ) ;
2016-06-10 20:27:21 -07:00
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( 'd00f907e-41b9-40f6-8168-63e832199a8c' ) ( it ) ( 'ensure that if people already have duplicate emails, they can still sign up new users' , done => {
2017-10-23 08:43:05 -04:00
const config = Config . get ( 'test' ) ;
2016-05-27 19:41:09 -07:00
// Remove existing data to clear out unique index
2025-11-23 13:51:42 +01:00
destroyAllDataPermanently ( )
2021-03-10 13:31:35 -06:00
. then ( ( ) => config . database . adapter . performInitialization ( { VolatileClassesSchemas : [ ] } ) )
2017-06-20 09:15:26 -07:00
. then ( ( ) => config . database . adapter . createClass ( '_User' , userSchema ) )
2018-09-01 13:58:06 -04:00
. then ( ( ) =>
config . database . adapter . createObject ( '_User' , userSchema , {
objectId : 'x' ,
email : 'a@b.c' ,
} )
)
. then ( ( ) =>
config . database . adapter . createObject ( '_User' , userSchema , {
objectId : 'y' ,
email : 'a@b.c' ,
} )
)
2017-06-20 09:15:26 -07:00
. then ( reconfigureServer )
. catch ( ( ) => {
const user = new Parse . User ( ) ;
user . setPassword ( 'asdf' ) ;
user . setUsername ( 'qqq' ) ;
user . setEmail ( 'unique@unique.unique' ) ;
return user . signUp ( ) . catch ( fail ) ;
} )
. then ( ( ) => {
const user = new Parse . User ( ) ;
user . setPassword ( 'asdf' ) ;
user . setUsername ( 'www' ) ;
user . setEmail ( 'a@b.c' ) ;
2018-09-01 13:58:06 -04:00
return user . signUp ( ) ;
2017-06-20 09:15:26 -07:00
} )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . EMAIL _TAKEN ) ;
done ( ) ;
} ) ;
2016-05-27 19:41:09 -07:00
} ) ;
2021-03-13 09:05:22 -06:00
it ( 'ensure that if you try to sign up a user with a unique username and email, but duplicates in some other field that has a uniqueness constraint, you get a regular duplicate value error' , async done => {
await reconfigureServer ( ) ;
2017-10-23 08:43:05 -04:00
const config = Config . get ( 'test' ) ;
2018-09-01 13:58:06 -04:00
config . database . adapter
. addFieldIfNotExists ( '_User' , 'randomField' , { type : 'String' } )
2020-10-25 15:06:58 -05:00
. then ( ( ) => config . database . adapter . ensureUniqueness ( '_User' , userSchema , [ 'randomField' ] ) )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
const user = new Parse . User ( ) ;
user . setPassword ( 'asdf' ) ;
user . setUsername ( '1' ) ;
user . setEmail ( '1@b.c' ) ;
user . set ( 'randomField' , 'a' ) ;
2018-09-01 13:58:06 -04:00
return user . signUp ( ) ;
2017-06-20 09:15:26 -07:00
} )
. then ( ( ) => {
const user = new Parse . User ( ) ;
user . setPassword ( 'asdf' ) ;
user . setUsername ( '2' ) ;
user . setEmail ( '2@b.c' ) ;
user . set ( 'randomField' , 'a' ) ;
2018-09-01 13:58:06 -04:00
return user . signUp ( ) ;
2017-06-20 09:15:26 -07:00
} )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . DUPLICATE _VALUE ) ;
done ( ) ;
} ) ;
2016-05-27 19:41:09 -07:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'succeed in logging in' , function ( done ) {
createTestUser ( ) . then ( async function ( u ) {
2016-01-28 10:58:12 -08:00
expect ( typeof u . id ) . toEqual ( 'string' ) ;
2018-08-05 13:58:07 -04:00
const user = await Parse . User . logIn ( 'test' , 'moon-y' ) ;
expect ( typeof user . id ) . toEqual ( 'string' ) ;
expect ( user . get ( 'password' ) ) . toBeUndefined ( ) ;
expect ( user . getSessionToken ( ) ) . not . toBeUndefined ( ) ;
await Parse . User . logOut ( ) ;
done ( ) ;
2016-01-28 10:58:12 -08:00
} , fail ) ;
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( '33db6efe-7c02-496c-8595-0ef627a94103' ) ( it ) ( 'increment with a user object' , function ( done ) {
2018-09-01 13:58:06 -04:00
createTestUser ( )
. then ( user => {
user . increment ( 'foo' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
return Parse . User . logIn ( 'test' , 'moon-y' ) ;
} )
. then ( user => {
expect ( user . get ( 'foo' ) ) . toEqual ( 1 ) ;
user . increment ( 'foo' ) ;
return user . save ( ) ;
} )
. then ( ( ) => Parse . User . logOut ( ) )
2017-06-20 09:15:26 -07:00
. then ( ( ) => Parse . User . logIn ( 'test' , 'moon-y' ) )
2018-09-01 13:58:06 -04:00
. then (
user => {
expect ( user . get ( 'foo' ) ) . toEqual ( 2 ) ;
Parse . User . logOut ( ) . then ( done ) ;
} ,
error => {
fail ( JSON . stringify ( error ) ) ;
done ( ) ;
}
) ;
2016-01-28 10:58:12 -08:00
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( 'bef99522-bcfd-4f79-ba9e-3c3845550401' ) ( it ) ( 'save various data types' , function ( done ) {
2018-02-17 09:55:30 -05:00
const obj = new TestObject ( ) ;
2016-01-28 10:58:12 -08:00
obj . set ( 'date' , new Date ( ) ) ;
obj . set ( 'array' , [ 1 , 2 , 3 ] ) ;
2018-09-01 13:58:06 -04:00
obj . set ( 'object' , { one : 1 , two : 2 } ) ;
obj
. save ( )
. then ( ( ) => {
const obj2 = new TestObject ( { objectId : obj . id } ) ;
return obj2 . fetch ( ) ;
} )
. then ( obj2 => {
expect ( obj2 . get ( 'date' ) instanceof Date ) . toBe ( true ) ;
expect ( obj2 . get ( 'array' ) instanceof Array ) . toBe ( true ) ;
expect ( obj2 . get ( 'object' ) instanceof Array ) . toBe ( false ) ;
expect ( obj2 . get ( 'object' ) instanceof Object ) . toBe ( true ) ;
done ( ) ;
} ) ;
2016-01-28 10:58:12 -08:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'query with limit' , function ( done ) {
2018-02-17 09:55:30 -05:00
const baz = new TestObject ( { foo : 'baz' } ) ;
const qux = new TestObject ( { foo : 'qux' } ) ;
2018-09-01 13:58:06 -04:00
baz
. save ( )
. then ( ( ) => {
return qux . save ( ) ;
} )
. then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
query . limit ( 1 ) ;
return query . find ( ) ;
} )
. then (
results => {
expect ( results . length ) . toEqual ( 1 ) ;
done ( ) ;
} ,
error => {
fail ( JSON . stringify ( error ) ) ;
done ( ) ;
}
) ;
2016-01-28 10:58:12 -08:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'query without limit get default 100 records' , function ( done ) {
2018-02-17 09:55:30 -05:00
const objects = [ ] ;
2018-09-01 13:58:06 -04:00
for ( let i = 0 ; i < 150 ; i ++ ) {
objects . push ( new TestObject ( { name : 'name' + i } ) ) ;
2016-02-13 17:44:43 +09:00
}
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( objects )
. then ( ( ) => {
return new Parse . Query ( TestObject ) . find ( ) ;
} )
. then (
results => {
expect ( results . length ) . toEqual ( 100 ) ;
done ( ) ;
} ,
error => {
fail ( JSON . stringify ( error ) ) ;
done ( ) ;
}
) ;
2016-02-13 17:44:43 +09:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'basic saveAll' , function ( done ) {
2018-02-17 09:55:30 -05:00
const alpha = new TestObject ( { letter : 'alpha' } ) ;
const beta = new TestObject ( { letter : 'beta' } ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ alpha , beta ] )
. then ( ( ) => {
expect ( alpha . id ) . toBeTruthy ( ) ;
expect ( beta . id ) . toBeTruthy ( ) ;
return new Parse . Query ( TestObject ) . find ( ) ;
} )
. then (
results => {
expect ( results . length ) . toEqual ( 2 ) ;
done ( ) ;
} ,
error => {
fail ( error ) ;
done ( ) ;
}
) ;
2016-01-28 10:58:12 -08:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'test beforeSave set object acl success' , function ( done ) {
2018-02-17 09:55:30 -05:00
const acl = new Parse . ACL ( {
2018-09-01 13:58:06 -04:00
'*' : { read : true , write : false } ,
2016-05-13 18:17:22 -07:00
} ) ;
2020-10-26 04:36:54 +11:00
Parse . Cloud . beforeSave ( 'BeforeSaveAddACL' , function ( req ) {
2016-05-13 18:17:22 -07:00
req . object . setACL ( acl ) ;
} ) ;
2018-02-17 09:55:30 -05:00
const obj = new Parse . Object ( 'BeforeSaveAddACL' ) ;
2016-05-13 18:17:22 -07:00
obj . set ( 'lol' , true ) ;
2018-09-01 13:58:06 -04:00
obj . save ( ) . then (
2020-10-26 04:36:54 +11:00
function ( ) {
2018-09-01 13:58:06 -04:00
const query = new Parse . Query ( 'BeforeSaveAddACL' ) ;
query . get ( obj . id ) . then (
2020-10-26 04:36:54 +11:00
function ( objAgain ) {
2018-09-01 13:58:06 -04:00
expect ( objAgain . get ( 'lol' ) ) . toBeTruthy ( ) ;
expect ( objAgain . getACL ( ) . equals ( acl ) ) ;
done ( ) ;
} ,
2020-10-26 04:36:54 +11:00
function ( error ) {
2018-09-01 13:58:06 -04:00
fail ( error ) ;
done ( ) ;
}
) ;
} ,
error => {
fail ( JSON . stringify ( error ) ) ;
2016-05-13 18:17:22 -07:00
done ( ) ;
2018-09-01 13:58:06 -04:00
}
) ;
2016-05-13 18:17:22 -07:00
} ) ;
2016-06-17 09:59:16 -07:00
it ( 'object is set on create and update' , done => {
let triggerTime = 0 ;
// Register a mock beforeSave hook
2018-09-01 13:58:06 -04:00
Parse . Cloud . beforeSave ( 'GameScore' , req => {
2016-12-07 15:17:05 -08:00
const object = req . object ;
2016-06-17 09:59:16 -07:00
expect ( object instanceof Parse . Object ) . toBeTruthy ( ) ;
expect ( object . get ( 'fooAgain' ) ) . toEqual ( 'barAgain' ) ;
if ( triggerTime == 0 ) {
// Create
expect ( object . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
// No objectId/createdAt/updatedAt
expect ( object . id ) . toBeUndefined ( ) ;
expect ( object . createdAt ) . toBeUndefined ( ) ;
expect ( object . updatedAt ) . toBeUndefined ( ) ;
} else if ( triggerTime == 1 ) {
// Update
expect ( object . get ( 'foo' ) ) . toEqual ( 'baz' ) ;
expect ( object . id ) . not . toBeUndefined ( ) ;
expect ( object . createdAt ) . not . toBeUndefined ( ) ;
expect ( object . updatedAt ) . not . toBeUndefined ( ) ;
} else {
2018-08-06 17:39:38 -04:00
throw new Error ( ) ;
2016-06-17 09:59:16 -07:00
}
triggerTime ++ ;
2016-02-23 18:01:54 -08:00
} ) ;
2016-05-28 21:51:22 +05:30
2016-12-07 15:17:05 -08:00
const obj = new Parse . Object ( 'GameScore' ) ;
2016-06-17 09:59:16 -07:00
obj . set ( 'foo' , 'bar' ) ;
obj . set ( 'fooAgain' , 'barAgain' ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
. then ( ( ) => {
// We only update foo
obj . set ( 'foo' , 'baz' ) ;
return obj . save ( ) ;
} )
. then (
( ) => {
// Make sure the checking has been triggered
expect ( triggerTime ) . toBe ( 2 ) ;
done ( ) ;
} ,
error => {
fail ( error ) ;
done ( ) ;
}
) ;
2016-06-17 09:59:16 -07:00
} ) ;
it ( 'works when object is passed to success' , done => {
let triggerTime = 0 ;
// Register a mock beforeSave hook
2018-09-01 13:58:06 -04:00
Parse . Cloud . beforeSave ( 'GameScore' , req => {
2016-12-07 15:17:05 -08:00
const object = req . object ;
2016-06-17 09:59:16 -07:00
object . set ( 'foo' , 'bar' ) ;
triggerTime ++ ;
2018-08-06 17:39:38 -04:00
return object ;
2016-05-28 21:51:22 +05:30
} ) ;
2016-02-23 18:01:54 -08:00
2016-12-07 15:17:05 -08:00
const obj = new Parse . Object ( 'GameScore' ) ;
2016-06-17 09:59:16 -07:00
obj . set ( 'foo' , 'baz' ) ;
2018-09-01 13:58:06 -04:00
obj . save ( ) . then (
( ) => {
expect ( triggerTime ) . toBe ( 1 ) ;
expect ( obj . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
done ( ) ;
} ,
error => {
fail ( error ) ;
done ( ) ;
}
) ;
2016-06-17 09:59:16 -07:00
} ) ;
2016-02-23 22:01:12 -08:00
2016-06-17 09:59:16 -07:00
it ( 'original object is set on update' , done => {
let triggerTime = 0 ;
// Register a mock beforeSave hook
2018-09-01 13:58:06 -04:00
Parse . Cloud . beforeSave ( 'GameScore' , req => {
2016-12-07 15:17:05 -08:00
const object = req . object ;
2016-06-17 09:59:16 -07:00
expect ( object instanceof Parse . Object ) . toBeTruthy ( ) ;
expect ( object . get ( 'fooAgain' ) ) . toEqual ( 'barAgain' ) ;
2016-12-07 15:17:05 -08:00
const originalObject = req . original ;
2016-06-17 09:59:16 -07:00
if ( triggerTime == 0 ) {
// No id/createdAt/updatedAt
expect ( object . id ) . toBeUndefined ( ) ;
expect ( object . createdAt ) . toBeUndefined ( ) ;
expect ( object . updatedAt ) . toBeUndefined ( ) ;
// Create
expect ( object . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
// Check the originalObject is undefined
expect ( originalObject ) . toBeUndefined ( ) ;
} else if ( triggerTime == 1 ) {
// Update
expect ( object . id ) . not . toBeUndefined ( ) ;
expect ( object . createdAt ) . not . toBeUndefined ( ) ;
expect ( object . updatedAt ) . not . toBeUndefined ( ) ;
expect ( object . get ( 'foo' ) ) . toEqual ( 'baz' ) ;
// Check the originalObject
expect ( originalObject instanceof Parse . Object ) . toBeTruthy ( ) ;
expect ( originalObject . get ( 'fooAgain' ) ) . toEqual ( 'barAgain' ) ;
expect ( originalObject . id ) . not . toBeUndefined ( ) ;
expect ( originalObject . createdAt ) . not . toBeUndefined ( ) ;
expect ( originalObject . updatedAt ) . not . toBeUndefined ( ) ;
expect ( originalObject . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
} else {
2018-08-06 17:39:38 -04:00
throw new Error ( ) ;
2016-06-17 09:59:16 -07:00
}
triggerTime ++ ;
} ) ;
2016-12-07 15:17:05 -08:00
const obj = new Parse . Object ( 'GameScore' ) ;
2016-06-17 09:59:16 -07:00
obj . set ( 'foo' , 'bar' ) ;
obj . set ( 'fooAgain' , 'barAgain' ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
. then ( ( ) => {
// We only update foo
obj . set ( 'foo' , 'baz' ) ;
return obj . save ( ) ;
} )
. then (
( ) => {
// Make sure the checking has been triggered
expect ( triggerTime ) . toBe ( 2 ) ;
done ( ) ;
} ,
error => {
fail ( error ) ;
done ( ) ;
}
) ;
2016-06-17 09:59:16 -07:00
} ) ;
2016-02-23 23:48:45 -08:00
2016-06-17 09:59:16 -07:00
it ( 'pointer mutation properly saves object' , done => {
2016-12-07 15:17:05 -08:00
const className = 'GameScore' ;
2016-02-23 23:48:45 -08:00
2018-09-01 13:58:06 -04:00
Parse . Cloud . beforeSave ( className , req => {
2016-12-07 15:17:05 -08:00
const object = req . object ;
2016-06-17 09:59:16 -07:00
expect ( object instanceof Parse . Object ) . toBeTruthy ( ) ;
2016-02-23 23:48:45 -08:00
2016-12-07 15:17:05 -08:00
const child = object . get ( 'child' ) ;
2016-06-17 09:59:16 -07:00
expect ( child instanceof Parse . Object ) . toBeTruthy ( ) ;
child . set ( 'a' , 'b' ) ;
2018-08-06 17:39:38 -04:00
return child . save ( ) ;
2016-06-17 09:59:16 -07:00
} ) ;
2016-02-23 23:48:45 -08:00
2016-12-07 15:17:05 -08:00
const obj = new Parse . Object ( className ) ;
2016-06-17 09:59:16 -07:00
obj . set ( 'foo' , 'bar' ) ;
2016-02-23 23:48:45 -08:00
2016-12-07 15:17:05 -08:00
const child = new Parse . Object ( 'Child' ) ;
2018-09-01 13:58:06 -04:00
child
. save ( )
. then ( ( ) => {
obj . set ( 'child' , child ) ;
return obj . save ( ) ;
} )
. then ( ( ) => {
const query = new Parse . Query ( className ) ;
query . include ( 'child' ) ;
return query . get ( obj . id ) . then ( objAgain => {
expect ( objAgain . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
2016-01-28 10:58:12 -08:00
2018-09-01 13:58:06 -04:00
const childAgain = objAgain . get ( 'child' ) ;
expect ( childAgain instanceof Parse . Object ) . toBeTruthy ( ) ;
expect ( childAgain . get ( 'a' ) ) . toEqual ( 'b' ) ;
return Promise . resolve ( ) ;
} ) ;
} )
. then (
( ) => {
done ( ) ;
} ,
error => {
fail ( error ) ;
done ( ) ;
}
) ;
} ) ;
2016-04-04 14:27:11 -04:00
2018-09-01 13:58:06 -04:00
it ( 'pointer reassign is working properly (#1288)' , done => {
Parse . Cloud . beforeSave ( 'GameScore' , req => {
2018-02-17 09:55:30 -05:00
const obj = req . object ;
2016-04-04 14:27:11 -04:00
if ( obj . get ( 'point' ) ) {
2018-08-06 17:39:38 -04:00
return ;
2016-04-04 14:27:11 -04:00
}
2018-02-17 09:55:30 -05:00
const TestObject1 = Parse . Object . extend ( 'TestObject1' ) ;
2018-09-01 13:58:06 -04:00
const newObj = new TestObject1 ( { key1 : 1 } ) ;
2016-04-04 14:27:11 -04:00
2018-09-01 13:58:06 -04:00
return newObj . save ( ) . then ( newObj => {
obj . set ( 'point' , newObj ) ;
2016-11-24 15:47:41 -05:00
} ) ;
2016-04-04 14:27:11 -04:00
} ) ;
2018-02-17 09:55:30 -05:00
let pointId ;
const obj = new Parse . Object ( 'GameScore' ) ;
2016-04-04 14:27:11 -04:00
obj . set ( 'foo' , 'bar' ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
. then ( ( ) => {
expect ( obj . get ( 'point' ) ) . not . toBeUndefined ( ) ;
pointId = obj . get ( 'point' ) . id ;
expect ( pointId ) . not . toBeUndefined ( ) ;
obj . set ( 'foo' , 'baz' ) ;
return obj . save ( ) ;
} )
. then ( obj => {
expect ( obj . get ( 'point' ) . id ) . toEqual ( pointId ) ;
done ( ) ;
} ) ;
2016-04-04 14:27:11 -04:00
} ) ;
2021-05-26 01:33:40 +03:00
it _only _db ( 'mongo' ) ( 'pointer reassign on nested fields is working properly (#7391)' , async ( ) => {
const obj = new Parse . Object ( 'GameScore' ) ; // This object will include nested pointers
const ptr1 = new Parse . Object ( 'GameScore' ) ;
await ptr1 . save ( ) ; // Obtain a unique id
const ptr2 = new Parse . Object ( 'GameScore' ) ;
await ptr2 . save ( ) ; // Obtain a unique id
obj . set ( 'data' , { ptr : ptr1 } ) ;
await obj . save ( ) ;
obj . set ( 'data.ptr' , ptr2 ) ;
await obj . save ( ) ;
const obj2 = await new Parse . Query ( 'GameScore' ) . get ( obj . id ) ;
expect ( obj2 . get ( 'data' ) . ptr . id ) . toBe ( ptr2 . id ) ;
const query = new Parse . Query ( 'GameScore' ) ;
query . equalTo ( 'data.ptr' , ptr2 ) ;
const res = await query . find ( ) ;
expect ( res . length ) . toBe ( 1 ) ;
expect ( res [ 0 ] . get ( 'data' ) . ptr . id ) . toBe ( ptr2 . id ) ;
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'test afterSave get full object on create and update' , function ( done ) {
2018-02-17 09:55:30 -05:00
let triggerTime = 0 ;
2016-01-28 10:58:12 -08:00
// Register a mock beforeSave hook
2020-10-26 04:36:54 +11:00
Parse . Cloud . afterSave ( 'GameScore' , function ( req ) {
2018-02-17 09:55:30 -05:00
const object = req . object ;
2016-01-28 10:58:12 -08:00
expect ( object instanceof Parse . Object ) . toBeTruthy ( ) ;
expect ( object . id ) . not . toBeUndefined ( ) ;
expect ( object . createdAt ) . not . toBeUndefined ( ) ;
expect ( object . updatedAt ) . not . toBeUndefined ( ) ;
2016-02-22 19:33:27 -08:00
expect ( object . get ( 'fooAgain' ) ) . toEqual ( 'barAgain' ) ;
2016-01-28 10:58:12 -08:00
if ( triggerTime == 0 ) {
// Create
expect ( object . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
} else if ( triggerTime == 1 ) {
// Update
expect ( object . get ( 'foo' ) ) . toEqual ( 'baz' ) ;
} else {
2018-08-06 17:39:38 -04:00
throw new Error ( ) ;
2016-01-28 10:58:12 -08:00
}
triggerTime ++ ;
} ) ;
2018-02-17 09:55:30 -05:00
const obj = new Parse . Object ( 'GameScore' ) ;
2016-01-28 10:58:12 -08:00
obj . set ( 'foo' , 'bar' ) ;
obj . set ( 'fooAgain' , 'barAgain' ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
2020-10-26 04:36:54 +11:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
// We only update foo
obj . set ( 'foo' , 'baz' ) ;
return obj . save ( ) ;
} )
. then (
2020-10-26 04:36:54 +11:00
function ( ) {
2018-09-01 13:58:06 -04:00
// Make sure the checking has been triggered
expect ( triggerTime ) . toBe ( 2 ) ;
done ( ) ;
} ,
2020-10-26 04:36:54 +11:00
function ( error ) {
2018-09-01 13:58:06 -04:00
fail ( error ) ;
done ( ) ;
}
) ;
2016-01-28 10:58:12 -08:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'test afterSave get original object on update' , function ( done ) {
2018-02-17 09:55:30 -05:00
let triggerTime = 0 ;
2016-01-28 10:58:12 -08:00
// Register a mock beforeSave hook
2016-03-10 11:30:29 -08:00
2020-10-26 04:36:54 +11:00
Parse . Cloud . afterSave ( 'GameScore' , function ( req ) {
2018-02-17 09:55:30 -05:00
const object = req . object ;
2016-01-28 10:58:12 -08:00
expect ( object instanceof Parse . Object ) . toBeTruthy ( ) ;
expect ( object . get ( 'fooAgain' ) ) . toEqual ( 'barAgain' ) ;
expect ( object . id ) . not . toBeUndefined ( ) ;
expect ( object . createdAt ) . not . toBeUndefined ( ) ;
expect ( object . updatedAt ) . not . toBeUndefined ( ) ;
2018-02-17 09:55:30 -05:00
const originalObject = req . original ;
2016-01-28 10:58:12 -08:00
if ( triggerTime == 0 ) {
// Create
expect ( object . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
// Check the originalObject is undefined
expect ( originalObject ) . toBeUndefined ( ) ;
} else if ( triggerTime == 1 ) {
// Update
expect ( object . get ( 'foo' ) ) . toEqual ( 'baz' ) ;
// Check the originalObject
expect ( originalObject instanceof Parse . Object ) . toBeTruthy ( ) ;
expect ( originalObject . get ( 'fooAgain' ) ) . toEqual ( 'barAgain' ) ;
expect ( originalObject . id ) . not . toBeUndefined ( ) ;
expect ( originalObject . createdAt ) . not . toBeUndefined ( ) ;
expect ( originalObject . updatedAt ) . not . toBeUndefined ( ) ;
expect ( originalObject . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
} else {
2018-08-06 17:39:38 -04:00
throw new Error ( ) ;
2016-01-28 10:58:12 -08:00
}
triggerTime ++ ;
} ) ;
2018-02-17 09:55:30 -05:00
const obj = new Parse . Object ( 'GameScore' ) ;
2016-01-28 10:58:12 -08:00
obj . set ( 'foo' , 'bar' ) ;
obj . set ( 'fooAgain' , 'barAgain' ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
2020-10-26 04:36:54 +11:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
// We only update foo
obj . set ( 'foo' , 'baz' ) ;
return obj . save ( ) ;
} )
. then (
2020-10-26 04:36:54 +11:00
function ( ) {
2018-09-01 13:58:06 -04:00
// Make sure the checking has been triggered
expect ( triggerTime ) . toBe ( 2 ) ;
done ( ) ;
} ,
2020-10-26 04:36:54 +11:00
function ( error ) {
2018-09-01 13:58:06 -04:00
jfail ( error ) ;
done ( ) ;
}
) ;
2016-03-10 11:30:29 -08:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'test afterSave get full original object even req auth can not query it' , done => {
2018-02-17 09:55:30 -05:00
let triggerTime = 0 ;
2016-03-10 11:30:29 -08:00
// Register a mock beforeSave hook
2020-10-26 04:36:54 +11:00
Parse . Cloud . afterSave ( 'GameScore' , function ( req ) {
2018-02-17 09:55:30 -05:00
const object = req . object ;
const originalObject = req . original ;
2016-03-10 11:30:29 -08:00
if ( triggerTime == 0 ) {
// Create
} else if ( triggerTime == 1 ) {
// Update
expect ( object . get ( 'foo' ) ) . toEqual ( 'baz' ) ;
// Make sure we get the full originalObject
expect ( originalObject instanceof Parse . Object ) . toBeTruthy ( ) ;
expect ( originalObject . get ( 'fooAgain' ) ) . toEqual ( 'barAgain' ) ;
expect ( originalObject . id ) . not . toBeUndefined ( ) ;
expect ( originalObject . createdAt ) . not . toBeUndefined ( ) ;
expect ( originalObject . updatedAt ) . not . toBeUndefined ( ) ;
expect ( originalObject . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
} else {
2018-08-06 17:39:38 -04:00
throw new Error ( ) ;
2016-03-10 11:30:29 -08:00
}
triggerTime ++ ;
} ) ;
2018-02-17 09:55:30 -05:00
const obj = new Parse . Object ( 'GameScore' ) ;
2016-03-10 11:30:29 -08:00
obj . set ( 'foo' , 'bar' ) ;
obj . set ( 'fooAgain' , 'barAgain' ) ;
2018-02-17 09:55:30 -05:00
const acl = new Parse . ACL ( ) ;
2016-03-10 11:30:29 -08:00
// Make sure our update request can not query the object
acl . setPublicReadAccess ( false ) ;
acl . setPublicWriteAccess ( true ) ;
obj . setACL ( acl ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
2020-10-26 04:36:54 +11:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
// We only update foo
obj . set ( 'foo' , 'baz' ) ;
return obj . save ( ) ;
} )
. then (
2020-10-26 04:36:54 +11:00
function ( ) {
2018-09-01 13:58:06 -04:00
// Make sure the checking has been triggered
expect ( triggerTime ) . toBe ( 2 ) ;
done ( ) ;
} ,
2020-10-26 04:36:54 +11:00
function ( error ) {
2018-09-01 13:58:06 -04:00
jfail ( error ) ;
done ( ) ;
}
) ;
2016-01-28 10:58:12 -08:00
} ) ;
2016-03-02 18:20:02 -08:00
it ( 'afterSave flattens custom operations' , done => {
2018-02-17 09:55:30 -05:00
let triggerTime = 0 ;
2016-03-02 18:20:02 -08:00
// Register a mock beforeSave hook
2020-10-26 04:36:54 +11:00
Parse . Cloud . afterSave ( 'GameScore' , function ( req ) {
2016-12-07 15:17:05 -08:00
const object = req . object ;
2016-03-02 18:20:02 -08:00
expect ( object instanceof Parse . Object ) . toBeTruthy ( ) ;
2016-12-07 15:17:05 -08:00
const originalObject = req . original ;
2016-03-02 18:20:02 -08:00
if ( triggerTime == 0 ) {
// Create
expect ( object . get ( 'yolo' ) ) . toEqual ( 1 ) ;
} else if ( triggerTime == 1 ) {
// Update
expect ( object . get ( 'yolo' ) ) . toEqual ( 2 ) ;
// Check the originalObject
expect ( originalObject . get ( 'yolo' ) ) . toEqual ( 1 ) ;
} else {
2018-08-06 17:39:38 -04:00
throw new Error ( ) ;
2016-03-02 18:20:02 -08:00
}
triggerTime ++ ;
} ) ;
2018-02-17 09:55:30 -05:00
const obj = new Parse . Object ( 'GameScore' ) ;
2016-03-02 18:20:02 -08:00
obj . increment ( 'yolo' , 1 ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
. then ( ( ) => {
obj . increment ( 'yolo' , 1 ) ;
return obj . save ( ) ;
} )
. then (
( ) => {
// Make sure the checking has been triggered
expect ( triggerTime ) . toBe ( 2 ) ;
done ( ) ;
} ,
error => {
jfail ( error ) ;
done ( ) ;
}
) ;
2016-03-02 18:20:02 -08:00
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'beforeSave receives ACL' , done => {
2016-03-08 16:15:49 -08:00
let triggerTime = 0 ;
// Register a mock beforeSave hook
2020-10-26 04:36:54 +11:00
Parse . Cloud . beforeSave ( 'GameScore' , function ( req ) {
2016-12-07 15:17:05 -08:00
const object = req . object ;
2016-03-08 16:15:49 -08:00
if ( triggerTime == 0 ) {
2016-12-07 15:17:05 -08:00
const acl = object . getACL ( ) ;
2016-03-08 16:15:49 -08:00
expect ( acl . getPublicReadAccess ( ) ) . toBeTruthy ( ) ;
expect ( acl . getPublicWriteAccess ( ) ) . toBeTruthy ( ) ;
} else if ( triggerTime == 1 ) {
2016-12-07 15:17:05 -08:00
const acl = object . getACL ( ) ;
2016-03-08 16:15:49 -08:00
expect ( acl . getPublicReadAccess ( ) ) . toBeFalsy ( ) ;
expect ( acl . getPublicWriteAccess ( ) ) . toBeTruthy ( ) ;
} else {
2018-08-06 17:39:38 -04:00
throw new Error ( ) ;
2016-03-08 16:15:49 -08:00
}
triggerTime ++ ;
} ) ;
2016-12-07 15:17:05 -08:00
const obj = new Parse . Object ( 'GameScore' ) ;
const acl = new Parse . ACL ( ) ;
2016-03-08 16:15:49 -08:00
acl . setPublicReadAccess ( true ) ;
acl . setPublicWriteAccess ( true ) ;
obj . setACL ( acl ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
. then ( ( ) => {
acl . setPublicReadAccess ( false ) ;
obj . setACL ( acl ) ;
return obj . save ( ) ;
} )
. then (
( ) => {
// Make sure the checking has been triggered
expect ( triggerTime ) . toBe ( 2 ) ;
done ( ) ;
} ,
error => {
jfail ( error ) ;
done ( ) ;
}
) ;
2016-03-08 16:15:49 -08:00
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'afterSave receives ACL' , done => {
2016-03-08 16:15:49 -08:00
let triggerTime = 0 ;
// Register a mock beforeSave hook
2020-10-26 04:36:54 +11:00
Parse . Cloud . afterSave ( 'GameScore' , function ( req ) {
2016-12-07 15:17:05 -08:00
const object = req . object ;
2016-03-08 16:15:49 -08:00
if ( triggerTime == 0 ) {
2016-12-07 15:17:05 -08:00
const acl = object . getACL ( ) ;
2016-03-08 16:15:49 -08:00
expect ( acl . getPublicReadAccess ( ) ) . toBeTruthy ( ) ;
expect ( acl . getPublicWriteAccess ( ) ) . toBeTruthy ( ) ;
} else if ( triggerTime == 1 ) {
2016-12-07 15:17:05 -08:00
const acl = object . getACL ( ) ;
2016-03-08 16:15:49 -08:00
expect ( acl . getPublicReadAccess ( ) ) . toBeFalsy ( ) ;
expect ( acl . getPublicWriteAccess ( ) ) . toBeTruthy ( ) ;
} else {
2018-08-06 17:39:38 -04:00
throw new Error ( ) ;
2016-03-08 16:15:49 -08:00
}
triggerTime ++ ;
} ) ;
2016-12-07 15:17:05 -08:00
const obj = new Parse . Object ( 'GameScore' ) ;
const acl = new Parse . ACL ( ) ;
2016-03-08 16:15:49 -08:00
acl . setPublicReadAccess ( true ) ;
acl . setPublicWriteAccess ( true ) ;
obj . setACL ( acl ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
. then ( ( ) => {
acl . setPublicReadAccess ( false ) ;
obj . setACL ( acl ) ;
return obj . save ( ) ;
} )
. then (
( ) => {
// Make sure the checking has been triggered
expect ( triggerTime ) . toBe ( 2 ) ;
done ( ) ;
} ,
error => {
jfail ( error ) ;
done ( ) ;
}
) ;
2016-03-08 16:15:49 -08:00
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( 'e9e718a9-4465-4158-b13e-f146855a8892' ) ( it ) ( 'return the updated fields on PUT' , async ( ) => {
2016-12-07 15:17:05 -08:00
const obj = new Parse . Object ( 'GameScore' ) ;
2022-09-18 02:20:50 +10:00
const pointer = new Parse . Object ( 'Child' ) ;
await pointer . save ( ) ;
obj . set (
'point' ,
new Parse . GeoPoint ( {
latitude : 37.4848 ,
longitude : - 122.1483 ,
2018-09-01 13:58:06 -04:00
} )
2022-09-18 02:20:50 +10:00
) ;
obj . set ( 'array' , [ 'obj1' , 'obj2' ] ) ;
obj . set ( 'objects' , { a : 'b' } ) ;
obj . set ( 'string' , 'abc' ) ;
obj . set ( 'bool' , true ) ;
obj . set ( 'number' , 1 ) ;
obj . set ( 'date' , new Date ( ) ) ;
obj . set ( 'pointer' , pointer ) ;
const headers = {
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
'X-Parse-REST-API-Key' : 'rest' ,
'X-Parse-Installation-Id' : 'yolo' ,
} ;
const saveResponse = await request ( {
method : 'POST' ,
headers : headers ,
url : 'http://localhost:8378/1/classes/GameScore' ,
body : JSON . stringify ( {
a : 'hello' ,
c : 1 ,
d : [ '1' ] ,
e : [ '1' ] ,
f : [ '1' , '2' ] ,
... obj . toJSON ( ) ,
} ) ,
} ) ;
expect ( Object . keys ( saveResponse . data ) . sort ( ) ) . toEqual ( [ 'createdAt' , 'objectId' ] ) ;
obj . id = saveResponse . data . objectId ;
const response = await request ( {
method : 'PUT' ,
headers : headers ,
url : 'http://localhost:8378/1/classes/GameScore/' + obj . id ,
body : JSON . stringify ( {
a : 'b' ,
c : { _ _op : 'Increment' , amount : 2 } ,
d : { _ _op : 'Add' , objects : [ '2' ] } ,
e : { _ _op : 'AddUnique' , objects : [ '1' , '2' ] } ,
f : { _ _op : 'Remove' , objects : [ '2' ] } ,
selfThing : {
_ _type : 'Pointer' ,
className : 'GameScore' ,
objectId : obj . id ,
} ,
} ) ,
} ) ;
const body = response . data ;
expect ( Object . keys ( body ) . sort ( ) ) . toEqual ( [ 'c' , 'd' , 'e' , 'f' , 'updatedAt' ] ) ;
expect ( body . a ) . toBeUndefined ( ) ;
expect ( body . c ) . toEqual ( 3 ) ; // 2+1
expect ( body . d . length ) . toBe ( 2 ) ;
expect ( body . d . indexOf ( '1' ) > - 1 ) . toBe ( true ) ;
expect ( body . d . indexOf ( '2' ) > - 1 ) . toBe ( true ) ;
expect ( body . e . length ) . toBe ( 2 ) ;
expect ( body . e . indexOf ( '1' ) > - 1 ) . toBe ( true ) ;
expect ( body . e . indexOf ( '2' ) > - 1 ) . toBe ( true ) ;
expect ( body . f . length ) . toBe ( 1 ) ;
expect ( body . f . indexOf ( '1' ) > - 1 ) . toBe ( true ) ;
expect ( body . selfThing ) . toBeUndefined ( ) ;
expect ( body . updatedAt ) . not . toBeUndefined ( ) ;
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( 'ea358b59-03c0-45c9-abc7-1fdd67573029' ) ( it ) ( 'should response should not change with triggers' , async ( ) => {
2022-09-18 02:20:50 +10:00
const obj = new Parse . Object ( 'GameScore' ) ;
const pointer = new Parse . Object ( 'Child' ) ;
Parse . Cloud . beforeSave ( 'GameScore' , request => {
return request . object ;
} ) ;
Parse . Cloud . afterSave ( 'GameScore' , request => {
return request . object ;
} ) ;
await pointer . save ( ) ;
obj . set (
'point' ,
new Parse . GeoPoint ( {
latitude : 37.4848 ,
longitude : - 122.1483 ,
} )
) ;
obj . set ( 'array' , [ 'obj1' , 'obj2' ] ) ;
obj . set ( 'objects' , { a : 'b' } ) ;
obj . set ( 'string' , 'abc' ) ;
obj . set ( 'bool' , true ) ;
obj . set ( 'number' , 1 ) ;
obj . set ( 'date' , new Date ( ) ) ;
obj . set ( 'pointer' , pointer ) ;
const headers = {
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
'X-Parse-REST-API-Key' : 'rest' ,
'X-Parse-Installation-Id' : 'yolo' ,
} ;
const saveResponse = await request ( {
method : 'POST' ,
headers : headers ,
url : 'http://localhost:8378/1/classes/GameScore' ,
body : JSON . stringify ( {
a : 'hello' ,
c : 1 ,
d : [ '1' ] ,
e : [ '1' ] ,
f : [ '1' , '2' ] ,
... obj . toJSON ( ) ,
} ) ,
} ) ;
expect ( Object . keys ( saveResponse . data ) . sort ( ) ) . toEqual ( [ 'createdAt' , 'objectId' ] ) ;
obj . id = saveResponse . data . objectId ;
const response = await request ( {
method : 'PUT' ,
headers : headers ,
url : 'http://localhost:8378/1/classes/GameScore/' + obj . id ,
body : JSON . stringify ( {
a : 'b' ,
c : { _ _op : 'Increment' , amount : 2 } ,
d : { _ _op : 'Add' , objects : [ '2' ] } ,
e : { _ _op : 'AddUnique' , objects : [ '1' , '2' ] } ,
f : { _ _op : 'Remove' , objects : [ '2' ] } ,
selfThing : {
_ _type : 'Pointer' ,
className : 'GameScore' ,
objectId : obj . id ,
} ,
} ) ,
} ) ;
const body = response . data ;
expect ( Object . keys ( body ) . sort ( ) ) . toEqual ( [ 'c' , 'd' , 'e' , 'f' , 'updatedAt' ] ) ;
expect ( body . a ) . toBeUndefined ( ) ;
expect ( body . c ) . toEqual ( 3 ) ; // 2+1
expect ( body . d . length ) . toBe ( 2 ) ;
expect ( body . d . indexOf ( '1' ) > - 1 ) . toBe ( true ) ;
expect ( body . d . indexOf ( '2' ) > - 1 ) . toBe ( true ) ;
expect ( body . e . length ) . toBe ( 2 ) ;
expect ( body . e . indexOf ( '1' ) > - 1 ) . toBe ( true ) ;
expect ( body . e . indexOf ( '2' ) > - 1 ) . toBe ( true ) ;
expect ( body . f . length ) . toBe ( 1 ) ;
expect ( body . f . indexOf ( '1' ) > - 1 ) . toBe ( true ) ;
expect ( body . selfThing ) . toBeUndefined ( ) ;
expect ( body . updatedAt ) . not . toBeUndefined ( ) ;
2018-09-01 13:58:06 -04:00
} ) ;
2016-03-16 19:33:04 -04:00
2018-09-01 13:58:06 -04:00
it ( 'test cloud function error handling' , done => {
2016-01-28 10:58:12 -08:00
// Register a function which will fail
2018-08-06 17:39:38 -04:00
Parse . Cloud . define ( 'willFail' , ( ) => {
throw new Error ( 'noway' ) ;
2016-01-28 10:58:12 -08:00
} ) ;
2018-09-01 13:58:06 -04:00
Parse . Cloud . run ( 'willFail' ) . then (
( ) => {
fail ( 'Should not have succeeded.' ) ;
done ( ) ;
} ,
e => {
2021-10-19 05:19:47 +11:00
expect ( e . code ) . toEqual ( Parse . Error . SCRIPT _FAILED ) ;
2018-09-01 13:58:06 -04:00
expect ( e . message ) . toEqual ( 'noway' ) ;
done ( ) ;
}
) ;
2016-01-28 10:58:12 -08:00
} ) ;
2016-02-17 20:43:09 +00:00
2018-09-01 13:58:06 -04:00
it ( 'test cloud function error handling with custom error code' , done => {
2016-06-01 10:28:06 -04:00
// Register a function which will fail
2018-08-06 17:39:38 -04:00
Parse . Cloud . define ( 'willFail' , ( ) => {
throw new Parse . Error ( 999 , 'noway' ) ;
2016-06-01 10:28:06 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
Parse . Cloud . run ( 'willFail' ) . then (
( ) => {
fail ( 'Should not have succeeded.' ) ;
done ( ) ;
} ,
e => {
expect ( e . code ) . toEqual ( 999 ) ;
expect ( e . message ) . toEqual ( 'noway' ) ;
done ( ) ;
}
) ;
2016-06-01 10:28:06 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'test cloud function error handling with standard error code' , done => {
2016-06-01 10:28:06 -04:00
// Register a function which will fail
2018-08-06 17:39:38 -04:00
Parse . Cloud . define ( 'willFail' , ( ) => {
throw new Error ( 'noway' ) ;
2016-06-01 10:28:06 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
Parse . Cloud . run ( 'willFail' ) . then (
( ) => {
fail ( 'Should not have succeeded.' ) ;
done ( ) ;
} ,
e => {
expect ( e . code ) . toEqual ( Parse . Error . SCRIPT _FAILED ) ;
expect ( e . message ) . toEqual ( 'noway' ) ;
done ( ) ;
}
) ;
2016-06-01 10:28:06 -04:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'test beforeSave/afterSave get installationId' , function ( done ) {
2016-03-02 20:59:45 -08:00
let triggerTime = 0 ;
2020-10-26 04:36:54 +11:00
Parse . Cloud . beforeSave ( 'GameScore' , function ( req ) {
2016-03-02 20:59:45 -08:00
triggerTime ++ ;
expect ( triggerTime ) . toEqual ( 1 ) ;
expect ( req . installationId ) . toEqual ( 'yolo' ) ;
} ) ;
2020-10-26 04:36:54 +11:00
Parse . Cloud . afterSave ( 'GameScore' , function ( req ) {
2016-03-02 20:59:45 -08:00
triggerTime ++ ;
expect ( triggerTime ) . toEqual ( 2 ) ;
expect ( req . installationId ) . toEqual ( 'yolo' ) ;
} ) ;
2018-02-17 09:55:30 -05:00
const headers = {
2016-03-02 20:59:45 -08:00
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
'X-Parse-REST-API-Key' : 'rest' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Installation-Id' : 'yolo' ,
2016-03-02 20:59:45 -08:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
headers : headers ,
url : 'http://localhost:8378/1/classes/GameScore' ,
body : JSON . stringify ( { a : 'b' } ) ,
} ) . then ( ( ) => {
expect ( triggerTime ) . toEqual ( 2 ) ;
done ( ) ;
} ) ;
2016-03-02 20:59:45 -08:00
} ) ;
2020-10-26 04:36:54 +11:00
it ( 'test beforeDelete/afterDelete get installationId' , function ( done ) {
2016-03-02 20:59:45 -08:00
let triggerTime = 0 ;
2020-10-26 04:36:54 +11:00
Parse . Cloud . beforeDelete ( 'GameScore' , function ( req ) {
2016-03-02 20:59:45 -08:00
triggerTime ++ ;
expect ( triggerTime ) . toEqual ( 1 ) ;
expect ( req . installationId ) . toEqual ( 'yolo' ) ;
} ) ;
2020-10-26 04:36:54 +11:00
Parse . Cloud . afterDelete ( 'GameScore' , function ( req ) {
2016-03-02 20:59:45 -08:00
triggerTime ++ ;
expect ( triggerTime ) . toEqual ( 2 ) ;
expect ( req . installationId ) . toEqual ( 'yolo' ) ;
} ) ;
2018-02-17 09:55:30 -05:00
const headers = {
2016-03-02 20:59:45 -08:00
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
'X-Parse-REST-API-Key' : 'rest' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Installation-Id' : 'yolo' ,
2016-03-02 20:59:45 -08:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
headers : headers ,
url : 'http://localhost:8378/1/classes/GameScore' ,
body : JSON . stringify ( { a : 'b' } ) ,
} ) . then ( response => {
request ( {
method : 'DELETE' ,
2016-03-02 20:59:45 -08:00
headers : headers ,
2020-10-25 15:06:58 -05:00
url : 'http://localhost:8378/1/classes/GameScore/' + response . data . objectId ,
2018-09-24 17:07:51 -04:00
} ) . then ( ( ) => {
expect ( triggerTime ) . toEqual ( 2 ) ;
done ( ) ;
} ) ;
} ) ;
2016-03-02 20:59:45 -08:00
} ) ;
2018-06-28 16:31:22 -04:00
it ( 'test beforeDelete with locked down ACL' , async ( ) => {
let called = false ;
2018-08-06 17:39:38 -04:00
Parse . Cloud . beforeDelete ( 'GameScore' , ( ) => {
2018-06-28 16:31:22 -04:00
called = true ;
} ) ;
const object = new Parse . Object ( 'GameScore' ) ;
object . setACL ( new Parse . ACL ( ) ) ;
await object . save ( ) ;
const objects = await new Parse . Query ( 'GameScore' ) . find ( ) ;
expect ( objects . length ) . toBe ( 0 ) ;
try {
await object . destroy ( ) ;
2018-09-01 13:58:06 -04:00
} catch ( e ) {
2018-06-28 16:31:22 -04:00
expect ( e . code ) . toBe ( Parse . Error . OBJECT _NOT _FOUND ) ;
}
expect ( called ) . toBe ( false ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'test cloud function query parameters' , done => {
Parse . Cloud . define ( 'echoParams' , req => {
2018-08-06 17:39:38 -04:00
return req . params ;
2016-02-15 22:18:19 -05:00
} ) ;
2018-02-17 09:55:30 -05:00
const headers = {
2016-02-15 22:18:19 -05:00
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Javascript-Key' : 'test' ,
2016-02-15 22:18:19 -05:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
headers : headers ,
url : 'http://localhost:8378/1/functions/echoParams' , //?option=1&other=2
qs : {
option : 1 ,
other : 2 ,
2016-02-15 22:18:19 -05:00
} ,
2018-09-24 17:07:51 -04:00
body : '{"foo":"bar", "other": 1}' ,
} ) . then ( response => {
const res = response . data . result ;
expect ( res . option ) . toEqual ( '1' ) ;
// Make sure query string params override body params
expect ( res . other ) . toEqual ( '2' ) ;
expect ( res . foo ) . toEqual ( 'bar' ) ;
done ( ) ;
} ) ;
2016-02-03 20:52:35 +00:00
} ) ;
2024-01-15 17:02:57 +02:00
it ( 'test cloud function query parameters with array of pointers' , async ( ) => {
Parse . Cloud . define ( 'echoParams' , req => {
return req . params ;
} ) ;
const headers = {
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
'X-Parse-Javascript-Key' : 'test' ,
} ;
const response = await request ( {
method : 'POST' ,
headers : headers ,
url : 'http://localhost:8378/1/functions/echoParams' ,
2025-12-12 20:46:35 +01:00
body : '{"arr": [{ "__type": "Pointer", "className": "PointerTest", "objectId": "test123" }]}' ,
2024-01-15 17:02:57 +02:00
} ) ;
const res = response . data . result ;
expect ( res . arr . length ) . toEqual ( 1 ) ;
} ) ;
2016-05-10 10:43:02 -07:00
it ( 'can handle null params in cloud functions (regression test for #1742)' , done => {
2018-09-01 13:58:06 -04:00
Parse . Cloud . define ( 'func' , request => {
2016-05-10 10:43:02 -07:00
expect ( request . params . nullParam ) . toEqual ( null ) ;
2018-08-06 17:39:38 -04:00
return 'yay' ;
2016-05-10 10:43:02 -07:00
} ) ;
2018-09-01 13:58:06 -04:00
Parse . Cloud . run ( 'func' , { nullParam : null } ) . then (
( ) => {
done ( ) ;
} ,
( ) => {
2017-06-20 09:15:26 -07:00
fail ( 'cloud code call failed' ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
}
) ;
2016-05-10 10:43:02 -07:00
} ) ;
2016-07-19 02:14:32 -04:00
it ( 'can handle date params in cloud functions (#2214)' , done => {
2016-12-07 15:17:05 -08:00
const date = new Date ( ) ;
2018-09-01 13:58:06 -04:00
Parse . Cloud . define ( 'dateFunc' , request => {
2016-07-19 02:14:32 -04:00
expect ( request . params . date . _ _type ) . toEqual ( 'Date' ) ;
expect ( request . params . date . iso ) . toEqual ( date . toISOString ( ) ) ;
2018-08-06 17:39:38 -04:00
return 'yay' ;
2016-07-19 02:14:32 -04:00
} ) ;
2018-09-01 13:58:06 -04:00
Parse . Cloud . run ( 'dateFunc' , { date : date } ) . then (
( ) => {
done ( ) ;
} ,
( ) => {
2017-06-20 09:15:26 -07:00
fail ( 'cloud code call failed' ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
}
) ;
2016-07-19 02:14:32 -04:00
} ) ;
2016-01-28 10:58:12 -08:00
it ( 'fails on invalid client key' , done => {
2018-02-17 09:55:30 -05:00
const headers = {
2016-01-28 10:58:12 -08:00
'Content-Type' : 'application/octet-stream' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Client-Key' : 'notclient' ,
2016-01-28 10:58:12 -08:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
headers : headers ,
url : 'http://localhost:8378/1/classes/TestObject' ,
} ) . then ( fail , response => {
const b = response . data ;
expect ( b . error ) . toEqual ( 'unauthorized' ) ;
done ( ) ;
} ) ;
2016-01-28 10:58:12 -08:00
} ) ;
it ( 'fails on invalid windows key' , done => {
2018-02-17 09:55:30 -05:00
const headers = {
2016-01-28 10:58:12 -08:00
'Content-Type' : 'application/octet-stream' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Windows-Key' : 'notwindows' ,
2016-01-28 10:58:12 -08:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
headers : headers ,
url : 'http://localhost:8378/1/classes/TestObject' ,
} ) . then ( fail , response => {
const b = response . data ;
expect ( b . error ) . toEqual ( 'unauthorized' ) ;
done ( ) ;
} ) ;
2016-01-28 10:58:12 -08:00
} ) ;
it ( 'fails on invalid javascript key' , done => {
2018-02-17 09:55:30 -05:00
const headers = {
2016-01-28 10:58:12 -08:00
'Content-Type' : 'application/octet-stream' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Javascript-Key' : 'notjavascript' ,
2016-01-28 10:58:12 -08:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
headers : headers ,
url : 'http://localhost:8378/1/classes/TestObject' ,
} ) . then ( fail , response => {
const b = response . data ;
expect ( b . error ) . toEqual ( 'unauthorized' ) ;
done ( ) ;
} ) ;
2016-01-28 10:58:12 -08:00
} ) ;
it ( 'fails on invalid rest api key' , done => {
2018-02-17 09:55:30 -05:00
const headers = {
2016-01-28 10:58:12 -08:00
'Content-Type' : 'application/octet-stream' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-REST-API-Key' : 'notrest' ,
2016-01-28 10:58:12 -08:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
headers : headers ,
url : 'http://localhost:8378/1/classes/TestObject' ,
} ) . then ( fail , response => {
const b = response . data ;
expect ( b . error ) . toEqual ( 'unauthorized' ) ;
done ( ) ;
} ) ;
2016-01-28 10:58:12 -08:00
} ) ;
2016-02-03 21:21:30 +00:00
it ( 'fails on invalid function' , done => {
2018-09-01 13:58:06 -04:00
Parse . Cloud . run ( 'somethingThatDoesDefinitelyNotExist' ) . then (
( ) => {
fail ( 'This should have never suceeded' ) ;
done ( ) ;
} ,
e => {
expect ( e . code ) . toEqual ( Parse . Error . SCRIPT _FAILED ) ;
2020-10-25 15:06:58 -05:00
expect ( e . message ) . toEqual ( 'Invalid function: "somethingThatDoesDefinitelyNotExist"' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
}
) ;
2016-02-03 21:21:30 +00:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'dedupes an installation properly and returns updatedAt' , done => {
2016-12-07 15:17:05 -08:00
const headers = {
2016-03-02 14:14:12 -08:00
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-REST-API-Key' : 'rest' ,
2016-03-02 14:14:12 -08:00
} ;
2016-12-07 15:17:05 -08:00
const data = {
2018-09-01 13:58:06 -04:00
installationId : 'lkjsahdfkjhsdfkjhsdfkjhsdf' ,
deviceType : 'embedded' ,
2016-03-02 14:14:12 -08:00
} ;
2016-12-07 15:17:05 -08:00
const requestOptions = {
2016-03-02 14:14:12 -08:00
headers : headers ,
2018-09-24 17:07:51 -04:00
method : 'POST' ,
2016-03-02 14:14:12 -08:00
url : 'http://localhost:8378/1/installations' ,
2018-09-01 13:58:06 -04:00
body : JSON . stringify ( data ) ,
2016-03-02 14:14:12 -08:00
} ;
2018-09-24 17:07:51 -04:00
request ( requestOptions ) . then ( response => {
const b = response . data ;
2016-03-02 14:14:12 -08:00
expect ( typeof b . objectId ) . toEqual ( 'string' ) ;
2018-09-24 17:07:51 -04:00
request ( requestOptions ) . then ( response => {
const b = response . data ;
2016-03-02 14:14:12 -08:00
expect ( typeof b . updatedAt ) . toEqual ( 'string' ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'android login providing empty authData block works' , done => {
2016-12-07 15:17:05 -08:00
const headers = {
2016-03-06 01:03:51 -08:00
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-REST-API-Key' : 'rest' ,
2016-03-06 01:03:51 -08:00
} ;
2016-12-07 15:17:05 -08:00
const data = {
2016-03-06 01:03:51 -08:00
username : 'pulse1989' ,
password : 'password1234' ,
2018-09-01 13:58:06 -04:00
authData : { } ,
2016-03-06 01:03:51 -08:00
} ;
2016-12-07 15:17:05 -08:00
const requestOptions = {
2018-09-24 17:07:51 -04:00
method : 'POST' ,
2016-03-06 01:03:51 -08:00
headers : headers ,
url : 'http://localhost:8378/1/users' ,
2018-09-01 13:58:06 -04:00
body : JSON . stringify ( data ) ,
2016-03-06 01:03:51 -08:00
} ;
2018-09-24 17:07:51 -04:00
request ( requestOptions ) . then ( ( ) => {
2016-03-06 01:03:51 -08:00
requestOptions . url = 'http://localhost:8378/1/login' ;
2018-09-24 17:07:51 -04:00
request ( requestOptions ) . then ( response => {
const b = response . data ;
2016-03-06 01:03:51 -08:00
expect ( typeof b [ 'sessionToken' ] ) . toEqual ( 'string' ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'gets relation fields' , done => {
2016-12-07 15:17:05 -08:00
const object = new Parse . Object ( 'AnObject' ) ;
const relatedObject = new Parse . Object ( 'RelatedObject' ) ;
2018-09-01 13:58:06 -04:00
Parse . Object . saveAll ( [ object , relatedObject ] )
. then ( ( ) => {
object . relation ( 'related' ) . add ( relatedObject ) ;
return object . save ( ) ;
} )
. then ( ( ) => {
const headers = {
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
'X-Parse-REST-API-Key' : 'rest' ,
} ;
const requestOptions = {
headers : headers ,
url : 'http://localhost:8378/1/classes/AnObject' ,
json : true ,
} ;
2018-09-24 17:07:51 -04:00
request ( requestOptions ) . then ( res => {
const body = res . data ;
2018-09-01 13:58:06 -04:00
expect ( body . results . length ) . toBe ( 1 ) ;
const result = body . results [ 0 ] ;
expect ( result . related ) . toEqual ( {
_ _type : 'Relation' ,
className : 'RelatedObject' ,
} ) ;
done ( ) ;
} ) ;
} )
. catch ( err => {
jfail ( err ) ;
2016-04-08 07:42:02 -04:00
done ( ) ;
} ) ;
2016-04-20 21:51:48 -04:00
} ) ;
2016-04-25 12:52:21 -07:00
2024-08-13 22:13:19 +02:00
it _id ( 'b2cd9cf2-13fa-4acd-aaa9-6f81fc1858db' ) ( it ) ( 'properly returns incremented values (#1554)' , done => {
2016-12-07 15:17:05 -08:00
const headers = {
2016-11-24 15:47:41 -05:00
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-REST-API-Key' : 'rest' ,
2016-11-24 15:47:41 -05:00
} ;
2016-12-07 15:17:05 -08:00
const requestOptions = {
2016-11-24 15:47:41 -05:00
headers : headers ,
url : 'http://localhost:8378/1/classes/AnObject' ,
2018-09-01 13:58:06 -04:00
json : true ,
2016-11-24 15:47:41 -05:00
} ;
2016-12-07 15:17:05 -08:00
const object = new Parse . Object ( 'AnObject' ) ;
2016-04-25 12:52:21 -07:00
2016-11-24 15:47:41 -05:00
function runIncrement ( amount ) {
2016-12-07 15:17:05 -08:00
const options = Object . assign ( { } , requestOptions , {
2016-11-24 15:47:41 -05:00
body : {
2018-09-01 13:58:06 -04:00
key : {
2016-04-25 12:52:21 -07:00
_ _op : 'Increment' ,
2018-09-01 13:58:06 -04:00
amount : amount ,
} ,
2016-11-24 15:47:41 -05:00
} ,
2018-09-01 13:58:06 -04:00
url : 'http://localhost:8378/1/classes/AnObject/' + object . id ,
2018-09-24 17:07:51 -04:00
method : 'PUT' ,
2018-09-01 13:58:06 -04:00
} ) ;
2018-09-24 17:07:51 -04:00
return request ( options ) . then ( res => res . data ) ;
2016-11-24 15:47:41 -05:00
}
2018-09-01 13:58:06 -04:00
object
. save ( )
. then ( ( ) => {
return runIncrement ( 1 ) ;
} )
. then ( res => {
expect ( res . key ) . toBe ( 1 ) ;
return runIncrement ( - 1 ) ;
} )
. then ( res => {
expect ( res . key ) . toBe ( 0 ) ;
done ( ) ;
} ) ;
} ) ;
2016-04-08 07:42:02 -04:00
2018-09-01 13:58:06 -04:00
it ( 'ignores _RevocableSession "header" send by JS SDK' , done => {
2016-12-07 15:17:05 -08:00
const object = new Parse . Object ( 'AnObject' ) ;
2016-04-25 12:52:21 -07:00
object . set ( 'a' , 'b' ) ;
object . save ( ) . then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
url : 'http://localhost:8378/1/classes/AnObject' ,
body : {
_method : 'GET' ,
_ApplicationId : 'test' ,
_JavaScriptKey : 'test' ,
_ClientVersion : 'js1.8.3' ,
_InstallationId : 'iid' ,
_RevocableSession : '1' ,
2016-04-25 12:52:21 -07:00
} ,
2018-09-24 17:07:51 -04:00
} ) . then ( res => {
const body = res . data ;
expect ( body . error ) . toBeUndefined ( ) ;
expect ( body . results ) . not . toBeUndefined ( ) ;
expect ( body . results . length ) . toBe ( 1 ) ;
const result = body . results [ 0 ] ;
expect ( result . a ) . toBe ( 'b' ) ;
done ( ) ;
} ) ;
2016-04-25 12:52:21 -07:00
} ) ;
} ) ;
2016-05-12 08:24:15 +08:00
2016-05-18 18:14:54 -07:00
it ( 'doesnt convert interior keys of objects that use special names' , done => {
2016-12-07 15:17:05 -08:00
const obj = new Parse . Object ( 'Obj' ) ;
2016-05-18 18:14:54 -07:00
obj . set ( 'val' , { createdAt : 'a' , updatedAt : 1 } ) ;
2018-09-01 13:58:06 -04:00
obj
. save ( )
2017-06-20 09:15:26 -07:00
. then ( obj => new Parse . Query ( 'Obj' ) . get ( obj . id ) )
. then ( obj => {
expect ( obj . get ( 'val' ) . createdAt ) . toEqual ( 'a' ) ;
expect ( obj . get ( 'val' ) . updatedAt ) . toEqual ( 1 ) ;
done ( ) ;
} ) ;
2016-05-18 18:14:54 -07:00
} ) ;
2016-10-31 21:41:21 +05:30
it ( 'bans interior keys containing . or $' , done => {
2018-09-01 13:58:06 -04:00
new Parse . Object ( 'Obj' )
. save ( { innerObj : { 'key with a $' : 'fails' } } )
. then (
( ) => {
fail ( 'should not succeed' ) ;
} ,
error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _NESTED _KEY ) ;
return new Parse . Object ( 'Obj' ) . save ( {
innerObj : { 'key with a .' : 'fails' } ,
} ) ;
}
)
. then (
( ) => {
fail ( 'should not succeed' ) ;
} ,
error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _NESTED _KEY ) ;
return new Parse . Object ( 'Obj' ) . save ( {
innerObj : { innerInnerObj : { 'key with $' : 'fails' } } ,
} ) ;
}
)
. then (
( ) => {
fail ( 'should not succeed' ) ;
} ,
error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _NESTED _KEY ) ;
return new Parse . Object ( 'Obj' ) . save ( {
innerObj : { innerInnerObj : { 'key with .' : 'fails' } } ,
} ) ;
}
)
. then (
( ) => {
fail ( 'should not succeed' ) ;
done ( ) ;
} ,
error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _NESTED _KEY ) ;
done ( ) ;
}
) ;
2016-05-18 18:14:54 -07:00
} ) ;
2016-05-23 16:31:51 -07:00
2016-08-15 16:48:39 -04:00
it ( 'does not change inner object keys named _auth_data_something' , done => {
2018-09-01 13:58:06 -04:00
new Parse . Object ( 'O' )
. save ( { innerObj : { _auth _data _facebook : 7 } } )
2017-06-20 09:15:26 -07:00
. then ( object => new Parse . Query ( 'O' ) . get ( object . id ) )
. then ( object => {
2018-09-01 13:58:06 -04:00
expect ( object . get ( 'innerObj' ) ) . toEqual ( { _auth _data _facebook : 7 } ) ;
2017-06-20 09:15:26 -07:00
done ( ) ;
} ) ;
2016-05-23 16:31:51 -07:00
} ) ;
it ( 'does not change inner object key names _p_somethign' , done => {
2018-09-01 13:58:06 -04:00
new Parse . Object ( 'O' )
. save ( { innerObj : { _p _data : 7 } } )
2017-06-20 09:15:26 -07:00
. then ( object => new Parse . Query ( 'O' ) . get ( object . id ) )
. then ( object => {
2018-09-01 13:58:06 -04:00
expect ( object . get ( 'innerObj' ) ) . toEqual ( { _p _data : 7 } ) ;
2017-06-20 09:15:26 -07:00
done ( ) ;
} ) ;
2016-05-23 16:31:51 -07:00
} ) ;
it ( 'does not change inner object key names _rperm, _wperm' , done => {
2018-09-01 13:58:06 -04:00
new Parse . Object ( 'O' )
. save ( { innerObj : { _rperm : 7 , _wperm : 8 } } )
2017-06-20 09:15:26 -07:00
. then ( object => new Parse . Query ( 'O' ) . get ( object . id ) )
. then ( object => {
2018-09-01 13:58:06 -04:00
expect ( object . get ( 'innerObj' ) ) . toEqual ( { _rperm : 7 , _wperm : 8 } ) ;
2017-06-20 09:15:26 -07:00
done ( ) ;
} ) ;
2016-05-23 16:31:51 -07:00
} ) ;
2016-08-20 16:07:48 -04:00
it ( 'does not change inner objects if the key has the same name as a geopoint field on the class, and the value is an array of length 2, or if the key has the same name as a file field on the class, and the value is a string' , done => {
2016-12-07 15:17:05 -08:00
const file = new Parse . File ( 'myfile.txt' , { base64 : 'eAo=' } ) ;
2018-09-01 13:58:06 -04:00
file
. save ( )
2017-06-20 09:15:26 -07:00
. then ( f => {
const obj = new Parse . Object ( 'O' ) ;
obj . set ( 'fileField' , f ) ;
obj . set ( 'geoField' , new Parse . GeoPoint ( 0 , 0 ) ) ;
obj . set ( 'innerObj' , {
2018-09-01 13:58:06 -04:00
fileField : 'data' ,
geoField : [ 1 , 2 ] ,
2017-06-20 09:15:26 -07:00
} ) ;
return obj . save ( ) ;
} )
. then ( object => object . fetch ( ) )
. then ( object => {
expect ( object . get ( 'innerObj' ) ) . toEqual ( {
2018-09-01 13:58:06 -04:00
fileField : 'data' ,
geoField : [ 1 , 2 ] ,
2017-06-20 09:15:26 -07:00
} ) ;
done ( ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( e => {
2017-06-20 09:15:26 -07:00
jfail ( e ) ;
done ( ) ;
2016-05-23 16:31:51 -07:00
} ) ;
} ) ;
2016-06-15 06:52:49 +08:00
2024-08-13 22:13:19 +02:00
it _id ( '8f99ee20-3da7-45ec-b867-ea0eb87524a9' ) ( it ) ( 'purge all objects in class' , done => {
2016-12-07 15:17:05 -08:00
const object = new Parse . Object ( 'TestObject' ) ;
2016-06-15 06:52:49 +08:00
object . set ( 'foo' , 'bar' ) ;
2016-12-07 15:17:05 -08:00
const object2 = new Parse . Object ( 'TestObject' ) ;
2016-06-15 06:52:49 +08:00
object2 . set ( 'alice' , 'wonderland' ) ;
Parse . Object . saveAll ( [ object , object2 ] )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2016-12-07 15:17:05 -08:00
const query = new Parse . Query ( TestObject ) ;
2018-09-01 13:58:06 -04:00
return query . count ( ) ;
} )
. then ( count => {
2017-06-20 09:15:26 -07:00
expect ( count ) . toBe ( 2 ) ;
const headers = {
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Master-Key' : 'test' ,
2017-06-20 09:15:26 -07:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'DELETE' ,
headers : headers ,
url : 'http://localhost:8378/1/purge/TestObject' ,
} ) . then ( ( ) => {
const query = new Parse . Query ( TestObject ) ;
return query . count ( ) . then ( count => {
expect ( count ) . toBe ( 0 ) ;
done ( ) ;
} ) ;
} ) ;
2016-06-15 06:52:49 +08:00
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'fail on purge all objects in class without master key' , done => {
2025-11-23 13:51:42 +01:00
const logger = require ( '../lib/logger' ) . default ;
const loggerErrorSpy = spyOn ( logger , 'error' ) . and . callThrough ( ) ;
2016-12-07 15:17:05 -08:00
const headers = {
2016-06-15 06:52:49 +08:00
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-REST-API-Key' : 'rest' ,
2016-06-15 06:52:49 +08:00
} ;
2025-11-23 13:51:42 +01:00
loggerErrorSpy . calls . reset ( ) ;
2018-09-24 17:07:51 -04:00
request ( {
2016-06-15 06:52:49 +08:00
method : 'DELETE' ,
headers : headers ,
2018-09-24 17:07:51 -04:00
url : 'http://localhost:8378/1/purge/TestObject' ,
2018-09-01 13:58:06 -04:00
} )
. then ( ( ) => {
fail ( 'Should not succeed' ) ;
} )
2018-09-24 17:07:51 -04:00
. catch ( response => {
2025-11-23 13:51:42 +01:00
expect ( response . data . error ) . toEqual ( 'Permission denied' ) ;
expect ( loggerErrorSpy ) . toHaveBeenCalledWith ( 'Sanitized error:' , jasmine . stringContaining ( 'unauthorized: master key is required' ) ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-06-15 06:52:49 +08:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'purge all objects in _Role also purge cache' , done => {
2016-12-07 15:17:05 -08:00
const headers = {
2016-06-15 06:52:49 +08:00
'Content-Type' : 'application/json' ,
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-Master-Key' : 'test' ,
2016-06-15 06:52:49 +08:00
} ;
2018-02-17 09:55:30 -05:00
let user , object ;
2018-09-01 13:58:06 -04:00
createTestUser ( )
. then ( x => {
user = x ;
const acl = new Parse . ACL ( ) ;
acl . setPublicReadAccess ( true ) ;
acl . setPublicWriteAccess ( false ) ;
const role = new Parse . Object ( '_Role' ) ;
role . set ( 'name' , 'TestRole' ) ;
role . setACL ( acl ) ;
const users = role . relation ( 'users' ) ;
users . add ( user ) ;
return role . save ( { } , { useMasterKey : true } ) ;
} )
. then ( ( ) => {
const query = new Parse . Query ( '_Role' ) ;
return query . find ( { useMasterKey : true } ) ;
} )
. then ( x => {
expect ( x . length ) . toEqual ( 1 ) ;
const relation = x [ 0 ] . relation ( 'users' ) . query ( ) ;
return relation . first ( { useMasterKey : true } ) ;
} )
. then ( x => {
expect ( x . id ) . toEqual ( user . id ) ;
object = new Parse . Object ( 'TestObject' ) ;
const acl = new Parse . ACL ( ) ;
acl . setPublicReadAccess ( false ) ;
acl . setPublicWriteAccess ( false ) ;
acl . setRoleReadAccess ( 'TestRole' , true ) ;
acl . setRoleWriteAccess ( 'TestRole' , true ) ;
object . setACL ( acl ) ;
return object . save ( ) ;
} )
. then ( ( ) => {
const query = new Parse . Query ( 'TestObject' ) ;
return query . find ( { sessionToken : user . getSessionToken ( ) } ) ;
} )
. then ( x => {
expect ( x . length ) . toEqual ( 1 ) ;
2018-09-24 17:07:51 -04:00
return request ( {
2018-09-01 13:58:06 -04:00
method : 'DELETE' ,
headers : headers ,
2018-09-24 17:07:51 -04:00
url : 'http://localhost:8378/1/purge/_Role' ,
2018-09-01 13:58:06 -04:00
json : true ,
} ) ;
} )
. then ( ( ) => {
const query = new Parse . Query ( 'TestObject' ) ;
return query . get ( object . id , { sessionToken : user . getSessionToken ( ) } ) ;
} )
. then (
( ) => {
fail ( 'Should not succeed' ) ;
} ,
e => {
expect ( e . code ) . toEqual ( Parse . Error . OBJECT _NOT _FOUND ) ;
done ( ) ;
}
) ;
2016-06-15 06:52:49 +08:00
} ) ;
2016-09-09 14:41:03 -04:00
2018-09-01 13:58:06 -04:00
it ( 'purge empty class' , done => {
2018-03-25 08:41:25 -05:00
const testSchema = new Parse . Schema ( 'UnknownClass' ) ;
2020-10-26 04:36:54 +11:00
testSchema . purge ( ) . then ( done ) . catch ( done . fail ) ;
2018-03-25 08:41:25 -05:00
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'should not update schema beforeSave #2672' , done => {
Parse . Cloud . beforeSave ( 'MyObject' , request => {
2016-09-09 14:41:03 -04:00
if ( request . object . get ( 'secret' ) ) {
2018-08-06 17:39:38 -04:00
throw 'cannot set secret here' ;
2016-09-09 14:41:03 -04:00
}
} ) ;
2016-12-07 15:17:05 -08:00
const object = new Parse . Object ( 'MyObject' ) ;
2016-09-09 14:41:03 -04:00
object . set ( 'key' , 'value' ) ;
2018-09-01 13:58:06 -04:00
object
. save ( )
. then ( ( ) => {
return object . save ( { secret : 'should not update schema' } ) ;
} )
. then (
( ) => {
fail ( ) ;
done ( ) ;
2016-09-09 14:41:03 -04:00
} ,
2018-09-01 13:58:06 -04:00
( ) => {
2018-09-24 17:07:51 -04:00
return request ( {
2018-09-01 13:58:06 -04:00
method : 'GET' ,
headers : {
'X-Parse-Application-Id' : 'test' ,
'X-Parse-Master-Key' : 'test' ,
} ,
2018-09-24 17:07:51 -04:00
url : 'http://localhost:8378/1/schemas/MyObject' ,
2018-09-01 13:58:06 -04:00
json : true ,
} ) ;
}
)
. then (
res => {
2018-09-24 17:07:51 -04:00
const fields = res . data . fields ;
2018-09-01 13:58:06 -04:00
expect ( fields . secret ) . toBeUndefined ( ) ;
done ( ) ;
} ,
err => {
jfail ( err ) ;
done ( ) ;
}
) ;
2016-09-09 14:41:03 -04:00
} ) ;
2016-08-20 16:07:48 -04:00
} ) ;
2016-08-12 16:15:55 -04:00
2016-08-20 16:07:48 -04:00
describe _only _db ( 'mongo' ) ( 'legacy _acl' , ( ) => {
2018-09-01 13:58:06 -04:00
it ( 'should have _acl when locking down (regression for #2465)' , done => {
2016-12-07 15:17:05 -08:00
const headers = {
2016-08-12 16:15:55 -04:00
'X-Parse-Application-Id' : 'test' ,
2018-09-01 13:58:06 -04:00
'X-Parse-REST-API-Key' : 'rest' ,
2018-09-24 17:07:51 -04:00
'Content-Type' : 'application/json' ,
2018-09-01 13:58:06 -04:00
} ;
2018-09-24 17:07:51 -04:00
request ( {
2016-11-24 15:47:41 -05:00
method : 'POST' ,
headers : headers ,
2018-09-24 17:07:51 -04:00
url : 'http://localhost:8378/1/classes/Report' ,
2016-11-24 15:47:41 -05:00
body : {
ACL : { } ,
2018-09-01 13:58:06 -04:00
name : 'My Report' ,
2016-11-24 15:47:41 -05:00
} ,
2018-09-01 13:58:06 -04:00
json : true ,
} )
. then ( ( ) => {
const config = Config . get ( 'test' ) ;
const adapter = config . database . adapter ;
2020-10-25 15:06:58 -05:00
return adapter . _adaptiveCollection ( 'Report' ) . then ( collection => collection . find ( { } ) ) ;
2018-09-01 13:58:06 -04:00
} )
. then ( results => {
expect ( results . length ) . toBe ( 1 ) ;
const result = results [ 0 ] ;
expect ( result . name ) . toEqual ( 'My Report' ) ;
expect ( result . _wperm ) . toEqual ( [ ] ) ;
expect ( result . _rperm ) . toEqual ( [ ] ) ;
expect ( result . _acl ) . toEqual ( { } ) ;
done ( ) ;
} )
. catch ( err => {
fail ( JSON . stringify ( err ) ) ;
done ( ) ;
} ) ;
2016-08-12 16:15:55 -04:00
} ) ;
2016-01-28 10:58:12 -08:00
} ) ;