diff --git a/src/Cloud.js b/src/Cloud.js
index 612cf02c8..0a5015e0d 100644
--- a/src/Cloud.js
+++ b/src/Cloud.js
@@ -57,6 +57,9 @@ export function run(
if (options.sessionToken) {
requestOptions.sessionToken = options.sessionToken;
}
+ if (options.context && typeof options.context === 'object') {
+ requestOptions.context = options.context;
+ }
return CoreManager.getCloudController().run(name, data, requestOptions);
}
diff --git a/src/ParseObject.js b/src/ParseObject.js
index 5f78cb191..3ae07cc78 100644
--- a/src/ParseObject.js
+++ b/src/ParseObject.js
@@ -1084,6 +1084,7 @@ class ParseObject {
* behalf of a specific user.
*
include: The name(s) of the key(s) to include. Can be a string, an array of strings,
* or an array of array of strings.
+ * context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
*
* @return {Promise} A promise that is fulfilled when the fetch
* completes.
@@ -1097,6 +1098,9 @@ class ParseObject {
if (options.hasOwnProperty('sessionToken')) {
fetchOptions.sessionToken = options.sessionToken;
}
+ if (options.hasOwnProperty('context') && typeof options.context === 'object') {
+ fetchOptions.context = options.context;
+ }
if (options.hasOwnProperty('include')) {
fetchOptions.include = [];
if (Array.isArray(options.include)) {
@@ -1273,6 +1277,7 @@ class ParseObject {
* be used for this request.
* sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
+ * context: A dictionary that is accessible in Cloud Code `beforeDelete` and `afterDelete` triggers.
*
* @return {Promise} A promise that is fulfilled when the destroy
* completes.
@@ -1286,6 +1291,9 @@ class ParseObject {
if (options.hasOwnProperty('sessionToken')) {
destroyOptions.sessionToken = options.sessionToken;
}
+ if (options.hasOwnProperty('context') && typeof options.context === 'object') {
+ destroyOptions.context = options.context;
+ }
if (!this.id) {
return Promise.resolve();
}
@@ -1631,6 +1639,7 @@ class ParseObject {
* sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* batchSize: Number of objects to process per request
+ * context: A dictionary that is accessible in Cloud Code `beforeDelete` and `afterDelete` triggers.
*
* @return {Promise} A promise that is fulfilled when the destroyAll
* completes.
@@ -1646,6 +1655,9 @@ class ParseObject {
if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') {
destroyOptions.batchSize = options.batchSize;
}
+ if (options.hasOwnProperty('context') && typeof options.context === 'object') {
+ destroyOptions.context = options.context;
+ }
return CoreManager.getObjectController().destroy(
list,
destroyOptions
@@ -1674,6 +1686,7 @@ class ParseObject {
* sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* batchSize: Number of objects to process per request
+ * context: A dictionary that is accessible in Cloud Code `beforeSave` and `afterSave` triggers.
*
*/
static saveAll(list: Array, options: RequestOptions = {}) {
@@ -1687,6 +1700,9 @@ class ParseObject {
if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') {
saveOptions.batchSize = options.batchSize;
}
+ if (options.hasOwnProperty('context') && typeof options.context === 'object') {
+ saveOptions.context = options.context;
+ }
return CoreManager.getObjectController().save(
list,
saveOptions
diff --git a/src/ParseQuery.js b/src/ParseQuery.js
index 10666034f..1e2be576a 100644
--- a/src/ParseQuery.js
+++ b/src/ParseQuery.js
@@ -564,6 +564,7 @@ class ParseQuery {
* be used for this request.
* sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
+ * context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
*
*
* @return {Promise} A promise that is resolved with the result when
@@ -579,6 +580,9 @@ class ParseQuery {
if (options && options.hasOwnProperty('sessionToken')) {
firstOptions.sessionToken = options.sessionToken;
}
+ if (options && options.hasOwnProperty('context') && typeof options.context === 'object') {
+ firstOptions.context = options.context;
+ }
return this.first(firstOptions).then((response) => {
if (response) {
@@ -604,6 +608,7 @@ class ParseQuery {
* be used for this request.
* sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
+ * context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
*
*
* @return {Promise} A promise that is resolved with the results when
@@ -619,6 +624,9 @@ class ParseQuery {
if (options.hasOwnProperty('sessionToken')) {
findOptions.sessionToken = options.sessionToken;
}
+ if (options.hasOwnProperty('context') && typeof options.context === 'object') {
+ findOptions.context = options.context;
+ }
this._setRequestTask(findOptions);
const controller = CoreManager.getQueryController();
@@ -799,6 +807,7 @@ class ParseQuery {
* be used for this request.
* sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
+ * context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
*
*
* @return {Promise} A promise that is resolved with the object when
@@ -814,6 +823,9 @@ class ParseQuery {
if (options.hasOwnProperty('sessionToken')) {
findOptions.sessionToken = options.sessionToken;
}
+ if (options.hasOwnProperty('context') && typeof options.context === 'object') {
+ findOptions.context = options.context;
+ }
this._setRequestTask(findOptions);
const controller = CoreManager.getQueryController();
@@ -871,6 +883,7 @@ class ParseQuery {
* be used for this request.
* sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
+ * context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
*
* @return {Promise} A promise that will be fulfilled once the
* iteration has completed.
@@ -921,6 +934,9 @@ class ParseQuery {
if (options.hasOwnProperty('sessionToken')) {
findOptions.sessionToken = options.sessionToken;
}
+ if (options.hasOwnProperty('context') && typeof options.context === 'object') {
+ findOptions.context = options.context;
+ }
let finished = false;
let previousResults = [];
diff --git a/src/__tests__/Cloud-test.js b/src/__tests__/Cloud-test.js
index 2a5b9bfda..b6f7b98ab 100644
--- a/src/__tests__/Cloud-test.js
+++ b/src/__tests__/Cloud-test.js
@@ -205,4 +205,21 @@ describe('CloudController', () => {
expect(CoreManager.getRESTController().request.mock.calls[0])
.toEqual(['GET', 'cloud_code/jobs/data', null, { useMasterKey: true }]);
});
+
+ it('accepts context on cloud function call', async () => {
+ const request = jest.fn();
+ request.mockReturnValue(Promise.resolve(undefined));
+
+ const ajax = jest.fn();
+ CoreManager.setRESTController({ request: request, ajax: ajax });
+
+ // Spy on REST controller
+ const controller = CoreManager.getRESTController();
+ jest.spyOn(controller, 'request');
+ // Save object
+ const context = {a: "a"};
+ await Cloud.run('myfunction', {}, { context: context });
+ // Validate
+ expect(controller.request.mock.calls[0][3].context).toEqual(context);
+ });
});
diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js
index e055a9d0e..d487e9148 100644
--- a/src/__tests__/ParseObject-test.js
+++ b/src/__tests__/ParseObject-test.js
@@ -1566,6 +1566,49 @@ describe('ParseObject', () => {
await result;
});
+ it('accepts context on saveAll', async () => {
+ // Mock XHR
+ CoreManager.getRESTController()._setXHR(
+ mockXHR([{
+ status: 200,
+ response: [{}]
+ }])
+ );
+ // Spy on REST controller
+ const controller = CoreManager.getRESTController();
+ jest.spyOn(controller, 'ajax');
+ // Save object
+ const context = {a: "a"};
+ const obj = new ParseObject('Item');
+ obj.id = 'pid';
+ obj.set('test', 'value');
+ await ParseObject.saveAll([obj], {context})
+ // Validate
+ const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]);
+ expect(jsonBody._context).toEqual(context);
+ });
+
+ it('accepts context on destroyAll', async () => {
+ // Mock XHR
+ CoreManager.getRESTController()._setXHR(
+ mockXHR([{
+ status: 200,
+ response: [{}]
+ }])
+ );
+ // Spy on REST controller
+ const controller = CoreManager.getRESTController();
+ jest.spyOn(controller, 'ajax');
+ // Save object
+ const context = {a: "a"};
+ const obj = new ParseObject('Item');
+ obj.id = 'pid';
+ await ParseObject.destroyAll([obj], { context: context })
+ // Validate
+ const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]);
+ expect(jsonBody._context).toEqual(context);
+ });
+
it('can save a chain of unsaved objects', async () => {
const xhrs = [];
RESTController._setXHR(function() {
@@ -1734,6 +1777,27 @@ describe('ParseObject', () => {
await result;
});
+ it('accepts context on destroy', async () => {
+ // Mock XHR
+ CoreManager.getRESTController()._setXHR(
+ mockXHR([{
+ status: 200,
+ response: {}
+ }])
+ );
+ // Spy on REST controller
+ const controller = CoreManager.getRESTController();
+ jest.spyOn(controller, 'ajax');
+ // Save object
+ const context = {a: "a"};
+ const obj = new ParseObject('Item');
+ obj.id = 'pid';
+ await obj.destroy({context});
+ // Validate
+ const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]);
+ expect(jsonBody._context).toEqual(context);
+ });
+
it('can save an array of objects', async (done) => {
const xhr = {
setRequestHeader: jest.fn(),
@@ -1980,6 +2044,27 @@ describe('ObjectController', () => {
jest.runAllTicks();
});
+ it('accepts context on fetch', async () => {
+ // Mock XHR
+ CoreManager.getRESTController()._setXHR(
+ mockXHR([{
+ status: 200,
+ response: {}
+ }])
+ );
+ // Spy on REST controller
+ const controller = CoreManager.getRESTController();
+ jest.spyOn(controller, 'ajax');
+ // Save object
+ const context = {a: "a"};
+ const obj = new ParseObject('Item');
+ obj.id = 'pid';
+ await obj.fetch({context});
+ // Validate
+ const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]);
+ expect(jsonBody._context).toEqual(context);
+ });
+
it('can fetch an array of objects', (done) => {
const objectController = CoreManager.getObjectController();
const objects = [];
diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js
index 66c907785..abe148f4c 100644
--- a/src/__tests__/ParseQuery-test.js
+++ b/src/__tests__/ParseQuery-test.js
@@ -1295,6 +1295,7 @@ describe('ParseQuery', () => {
});
it('can pass options to a get() query', (done) => {
+ const context = {a: "a"};
CoreManager.setQueryController({
aggregate() {},
find(className, params, options) {
@@ -1307,6 +1308,7 @@ describe('ParseQuery', () => {
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
+ expect(options.context).toEqual(context);
return Promise.resolve({
results: [
{ objectId: 'I27', size: 'large', name: 'Product 27' }
@@ -1318,7 +1320,8 @@ describe('ParseQuery', () => {
const q = new ParseQuery('Item');
q.get('I27', {
useMasterKey: true,
- sessionToken: '1234'
+ sessionToken: '1234',
+ context: context
}).then(() => {
done();
});
@@ -1437,6 +1440,7 @@ describe('ParseQuery', () => {
});
it('can pass options to find()', (done) => {
+ const context = {a: "a"};
CoreManager.setQueryController({
aggregate() {},
find(className, params, options) {
@@ -1450,6 +1454,7 @@ describe('ParseQuery', () => {
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
+ expect(options.context).toEqual(context);
return Promise.resolve({
results: []
});
@@ -1460,7 +1465,8 @@ describe('ParseQuery', () => {
q.containedIn('size', ['small', 'medium'])
.find({
useMasterKey: true,
- sessionToken: '1234'
+ sessionToken: '1234',
+ context: context
})
.then((objs) => {
expect(objs).toEqual([]);
@@ -1692,6 +1698,7 @@ describe('ParseQuery', () => {
});
it('can pass options to each()', (done) => {
+ const context = {a: "a"};
CoreManager.setQueryController({
aggregate() {},
find(className, params, options) {
@@ -1709,6 +1716,7 @@ describe('ParseQuery', () => {
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
+ expect(options.context).toEqual(context);
return Promise.resolve({
results: [
{ objectId: 'I55', size: 'medium', name: 'Product 55' },
@@ -1729,7 +1737,8 @@ describe('ParseQuery', () => {
calls++;
}, {
useMasterKey: true,
- sessionToken: '1234'
+ sessionToken: '1234',
+ context: context
}).then(() => {
expect(calls).toBe(3);
done();
@@ -1738,6 +1747,7 @@ describe('ParseQuery', () => {
it('can pass options to each() with hint', (done) => {
+ const context = {a: "a"};
CoreManager.setQueryController({
aggregate() {},
find(className, params, options) {
@@ -1756,6 +1766,7 @@ describe('ParseQuery', () => {
});
expect(options.useMasterKey).toEqual(true);
expect(options.sessionToken).toEqual('1234');
+ expect(options.context).toEqual(context);
return Promise.resolve({
results: [
{ objectId: 'I55', size: 'medium', name: 'Product 55' },
@@ -1777,7 +1788,8 @@ describe('ParseQuery', () => {
calls++;
}, {
useMasterKey: true,
- sessionToken: '1234'
+ sessionToken: '1234',
+ context: context
}).then(() => {
expect(calls).toBe(3);
done();