Skip to content

Pass context in destroy, saveAll, get, find hooks. #1159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
3 changes: 3 additions & 0 deletions src/Cloud.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
16 changes: 16 additions & 0 deletions src/ParseObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@ class ParseObject {
* behalf of a specific user.
* <li>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.
* <li>context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
* </ul>
* @return {Promise} A promise that is fulfilled when the fetch
* completes.
Expand All @@ -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)) {
Expand Down Expand Up @@ -1273,6 +1277,7 @@ class ParseObject {
* be used for this request.
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* <li>context: A dictionary that is accessible in Cloud Code `beforeDelete` and `afterDelete` triggers.
* </ul>
* @return {Promise} A promise that is fulfilled when the destroy
* completes.
Expand All @@ -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();
}
Expand Down Expand Up @@ -1631,6 +1639,7 @@ class ParseObject {
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* <li>batchSize: Number of objects to process per request
* <li>context: A dictionary that is accessible in Cloud Code `beforeDelete` and `afterDelete` triggers.
* </ul>
* @return {Promise} A promise that is fulfilled when the destroyAll
* completes.
Expand All @@ -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
Expand Down Expand Up @@ -1674,6 +1686,7 @@ class ParseObject {
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* <li>batchSize: Number of objects to process per request
* <li>context: A dictionary that is accessible in Cloud Code `beforeSave` and `afterSave` triggers.
* </ul>
*/
static saveAll(list: Array<ParseObject>, options: RequestOptions = {}) {
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions src/ParseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ class ParseQuery {
* be used for this request.
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* <li>context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
* </ul>
*
* @return {Promise} A promise that is resolved with the result when
Expand All @@ -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) {
Expand All @@ -604,6 +608,7 @@ class ParseQuery {
* be used for this request.
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* <li>context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
* </ul>
*
* @return {Promise} A promise that is resolved with the results when
Expand All @@ -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();
Expand Down Expand Up @@ -799,6 +807,7 @@ class ParseQuery {
* be used for this request.
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* <li>context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
* </ul>
*
* @return {Promise} A promise that is resolved with the object when
Expand All @@ -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();
Expand Down Expand Up @@ -871,6 +883,7 @@ class ParseQuery {
* be used for this request.
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* <li>context: A dictionary that is accessible in Cloud Code `beforeFind` trigger.
* </ul>
* @return {Promise} A promise that will be fulfilled once the
* iteration has completed.
Expand Down Expand Up @@ -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 = [];
Expand Down
17 changes: 17 additions & 0 deletions src/__tests__/Cloud-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
85 changes: 85 additions & 0 deletions src/__tests__/ParseObject-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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 = [];
Expand Down
20 changes: 16 additions & 4 deletions src/__tests__/ParseQuery-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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' }
Expand All @@ -1318,7 +1320,8 @@ describe('ParseQuery', () => {
const q = new ParseQuery('Item');
q.get('I27', {
useMasterKey: true,
sessionToken: '1234'
sessionToken: '1234',
context: context
}).then(() => {
done();
});
Expand Down Expand Up @@ -1437,6 +1440,7 @@ describe('ParseQuery', () => {
});

it('can pass options to find()', (done) => {
const context = {a: "a"};
CoreManager.setQueryController({
aggregate() {},
find(className, params, options) {
Expand All @@ -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: []
});
Expand All @@ -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([]);
Expand Down Expand Up @@ -1692,6 +1698,7 @@ describe('ParseQuery', () => {
});

it('can pass options to each()', (done) => {
const context = {a: "a"};
CoreManager.setQueryController({
aggregate() {},
find(className, params, options) {
Expand All @@ -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' },
Expand All @@ -1729,7 +1737,8 @@ describe('ParseQuery', () => {
calls++;
}, {
useMasterKey: true,
sessionToken: '1234'
sessionToken: '1234',
context: context
}).then(() => {
expect(calls).toBe(3);
done();
Expand All @@ -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) {
Expand All @@ -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' },
Expand All @@ -1777,7 +1788,8 @@ describe('ParseQuery', () => {
calls++;
}, {
useMasterKey: true,
sessionToken: '1234'
sessionToken: '1234',
context: context
}).then(() => {
expect(calls).toBe(3);
done();
Expand Down