Parse.Query unable to find objects when called within Parse.Cloud code - parse-platform

I'm struggling to figure out why my queries will not work when called from Parse.Cloud triggers.
I want to define some logic after an object of particular class was saved (the class is 'Message' in my case).
I'm testing the following simple code in my cloud/main.js:
const conversationQuery = new Parse.Query('Conversation');
conversationQuery.get('myIdHere', { useMasterKey: true })
.then(conversation => {
console.log('### Conversation is', conversation);
})
.catch(err => {
console.log('### Error is', err);
});
Parse.Cloud.afterSave('Message', req => {
const conversationQuery1 = new Parse.Query('Conversation');
conversationQuery1.get('myIdHere', { useMasterKey: true })
.then(conversation => {
console.log('>>> Conversation is', conversation);
})
.catch(err => {
console.log('>>> Error is', err);
});
});
And when I start my instance of parse-server, the following is logged to the console:
### Conversation is { myObjectHere }
However, when I save any object of 'Message' class, I get an error:
>>> Error is { Error: Object not found. <stacktrace here>, message: 'Object not found.', code: 101 }
I'd expect it to log the very same object that was retreived when the server started but instead, it returns a '101 object not found' error.
I think I configured everything according to the documentation but there's a possibility I just missed something.
I'm using Parse Server 3.1.3 and Parse JS SDK 2.1.0

https://github.com/parse-community/parse-server#logging it depends on how you start your parse server, but generally something like: VERBOSE="1" parse-server

Related

Unexpected error during jasmine test (with observable)

I wrote a test for the following method:
private _segmentationStatus$: Subject<string> = new Subject();
public readonly segmentationStatus: Observable<string> = this._segmentationStatus$.asObservable();
/**
* Get the status from the segmentation service.
*/
public getStatus() {
const segmentationId: string = this._segmentationIdService.segmentationId;
const segmentationStatusUrl = `${this.getSegmentationStatusUrl}/${segmentationId}/status`;
this._http
.get(segmentationStatusUrl, { responseType: 'text' })
.subscribe({
next: () => {
this._loggerService.trackTrace(`Segmentation status: ${status}`, LogSeverity.Verbose);
this._segmentationStatus$.next(status);
},
error: (error) => {
this._messageService.emitMessage(new Message(MessageCode.ErrorGetStatus, error));
this._loggerService.trackException(error);
this._segmentationStatus$.error(error);
}
});
}
To test the method I started to write a test as below:
fit('should emit a message if the request failed', done => {
let messageReceived: Message;
spyOn((service as any)._messageService, 'emitMessage').and.callFake(message => {
messageReceived = message;
});
service.segmentationStatus.subscribe({
error: () => {
expect(messageReceived.messageCode).toBe(MessageCode.ErrorGetStatus);
done();
}
});
spyOnProperty(
(service as any)._segmentationIdService,
'segmentationId',
'get'
).and.returnValue('id');
service.getStatus();
httpTestingController
.expectOne(`${service.getSegmentationStatusUrl}/id/status`)
.flush('{}', { status: 500, statusText: 'status' });
});
If I use the debugger the flow of the program and test is as expected. I see the emitted message and the error handler in the unit test is called. However, after the error handler in the unit test completes the line this._segmentationStatus$.error(error); in the productive code throws another error, which is not handled. Thus the tests fails with the message Uncaught [object Object] thrown.
I`ve read the RxJS documentation and googled the problem, but was not able to figure out what I need to do pass the test. Any help to point out where I did the mistake would be highly appreciated.
I've found the problem; there was another subscriber to segmentationStatus which did not handle the error. As nobody "trapped" the exception it bubbled up and was re-thrown. As explained in On The Subject Of Subjects (in RxJS).

Apollo Client on React - How to retrieve the error message fomated?

I can't find info about it in anywhere...
Consider this very simple scenario...
<Mutation mutation={LOGIN_MUTATION}>
{(login, { data, loading, error }) => {
if (error) {
console.log(error)
}
I am receiving a string error message like...
Error: GraphQL error: ERROR_INVALID_LOGIN_PROVIDER
at new ApolloError (bundle.umd.js:92)
at MutationData.onMutationCompleted (react-hooks.cjs.js:636)
at react-hooks.cjs.js:559
at tryCallOne (core.js:37)
at core.js:123
at JSTimers.js:289
at _callTimer (JSTimers.js:146)
at _callImmediatesPass (JSTimers.js:194)
at Object.callImmediates (JSTimers.js:458)
at MessageQueue.__callImmediates (MessageQueue.js:366)
I can't take actions based on the error message formated in this way. ERROR_INVALID_LOGIN_PROVIDER could be ERROR_INVALID_PASSWORD, for example...
I need to take decisions based on the error messages. but I just receive a string containing the graphql error, the modules inside the js and a lot of information that's not important. Is there any way to receive the error message formatted imn a way that I can extract only the server error ?
This should be possible
error in your example should be an ApolloError with the possible GraphQLErrors or a NetworkError
(login, { data, loading, error }) => {
if (error) {
if (error.graphQlErrors && error.graphQLErrors.length > 0) {
// There are graphQL errors and there may be multiple but its always an array.
// You should handle it properly
const { message } = error.graphQLErrors[0]
console.log(message) // e.g. ERROR_INVALID_LOGIN_PROVIDER
} else if (error.networkError) {
// There may be a network error
const { message } = error.networkError
console.log(message) // e.g. NetworkError when attempting to fetch resource.
}
}

How to test RxDB in Redux-saga with Jest?

I am trying to cover redux-saga that gets data from RxDB with Jest tests.
export function* checkUnsavedData(action) {
const { tab } = action;
try {
const db = yield getDB().catch(e => {
throw new Error(e);
});
const currentUser = yield select(makeSelectCurrentUser());
const unsavedData = yield db[USER_COLLECTION].findOne(currentUser)
.exec()
.then(data => data && data.unsavedData)
.catch(e => {
throw new Error(e);
});
} catch (error) {
yield showError(error);
}
}
Everything is fine in live run. But testing the generator I get:
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Error: RxError:
RxDatabase.create(): Adapter not added. Use RxDB.plugin(require('pouchdb-adapter-[adaptername]');
Given parameters: {
adapter:"idb"}
If anyone has done this, please, tell me how to test such cases with RxDB in redux-saga with Jest.
It looks like you did non add the adapter to RxDB. Can you paste the code where you create the database? This would help more in finding the error.
When running tests, you should not use the idb-adapter. Use the in-memory-adapter, it's faster and also you can be sure that you start on a clean state on each testrun.

Angular 2 HttpClient error body

I'm using the new (4.3) HttpClient in angular to POST data to my backend server:
this.httpClient.post<View>(`/path`, data).subscribe(
(view: View) => console.log("Success"),
(error: HttpErrorResponse) => {
console.log(error)
this.errorMessage = <any>error.error;
});
);
This call generates an (expected) error (409), but for some reason, the logged error does not contain the body of the error sent from the server. I can see the status code, but the error.error field, which should contain the response body is missing. Anyone have any ideas what could be wrong?
I've tested the backend call using curl, and can see the response body from the server.
Is your error body coming back as JSON or un-formatted text/other? I had a similar problem until i realized the body returned with the error result was a simple string. I had to change the call to something similar to this (forgive the lack of type-safety here):
this.http.post('http://address', body, { responseType: 'text' })
.subscribe(data => {
this.result = data['value'];
this.router.navigate(['/route']);
}, (error: HttpErrorResponse) => {
this.error = error.error;
this.router.navigate(['/error']);
});
This is a known bug in angular which is throwing an exception during the json parsing and not populating the error field:
https://github.com/angular/angular/pull/18466

Cloud Code Error in Saving user

I have a function in my cloud code, which works, but I'm not sure how to fix a problem related to it.
Original Problem:
Parse.Cloud.define("assignTokenToUser", function(request, response) {
console.log("Inside assignTokenToUser");
var token = Math.random().toString(30).substring(7);
query = new Parse.Query("User"),
email = request.params.email;
query.equalTo("username", email);
query.find({ useMasterKey: true }).then(function(results) {
query.first({
success: function(user) {
// Successfully retrieved the object.
user.set("emailToken", token);
user.save();
console.log("success...");
response.success(token);
},
error: function(error) {
console.log("error 1...");
response.error(error);
}
});
}, function(error) {
console.log("error 2...");
response.error(error);
});
});
This seemed to be a common problem after scanning the internet, and my analysis is that the useMasterKey needs to be passed each time we use the query object. Correspondingly, my log file shows that when trying to save the user, it gives a Code 206 error.
Log file output:
Inside assignTokenToUser
success...
^[[32minfo^[[39m: Ran cloud function assignTokenToUser for user undefined with:
Input: {"email":"maryam.zafar#emumba.com"}
Result: "p66qm34jd80p0j6ne03fe1q7f" functionName=assignTokenToUser, email=maryam.zafar#emumba.com, user=undefined
going to send an email... with result: p66qm34jd80p0j6ne03fe1q7f
fullLink: https://beatthegym.com/emailVerified?username=maryam.zafar#emumba.com&token=p66qm34jd80p0j6ne03fe1q7f
^[[31merror^[[39m: Error generating response. ParseError { code: 206, message: 'Cannot modify user 4m0VZFsKVt.' } code=206, message=Cannot modify user 4m0VZFsKVt.
[object Object]
So I went on to change my code to the following:
Code:
Parse.Cloud.define("assignTokenToUser", function(request, response) {
console.log("Inside assignTokenToUser");
var token = Math.random().toString(30).substring(7);
query = new Parse.Query("User"),
email = request.params.email;
query.equalTo("username", email);
query.find({ useMasterKey: true }).then(function(results) {
console.log("inside query.find...");
query.first(null, { useMasterKey: true }).then(function(user) {
console.log("inside query.first...");
// Successfully retrieved the object.
user.set("emailToken", token);
user.save(null, { useMasterKey: true }).then(function() {
console.log("inside user.save...");
response.success();
}, function(error) {
response.error(error);
});
response.success(token);
},
function(error) {
console.log("error 1...");
response.error(error);
});
}, function(error) {
console.log("error 2...");
response.error(error);
});
});
Log file:
Inside assignTokenToUser
inside query.find...
inside query.first...
^[[32minfo^[[39m: Ran cloud function assignTokenToUser for user undefined with:
Input: {"email":"maryam.zafar#emumba.com"}
Result: "tqc8m9lo2tcsrqn69c3q0e1q7f" functionName=assignTokenToUser, email=maryam.zafar#emumba.com, user=undefined
inside user.save...
^[[32minfo^[[39m: Ran cloud function assignTokenToUser for user undefined with:
Input: {"email":"maryam.zafar#emumba.com"}
Result: undefined functionName=assignTokenToUser, email=maryam.zafar#emumba.com, user=undefined
[object Object]
Now, the log file gives me a user as "undefined", and the call to the function gives me a pending status in the Chrome Network tab in the Inspector tool, until it turns into 502, and then the request is auto generated by the browser again. All other requests get a correct 200 response.
However, the data seems to be saved.. the record against this email address saves the token generated correctly. But the request from the browser fails and the user is "undefined" while in the original log file, I see the correct user Id... everytime it fails, the function automatically runs again (because the browser is generating another request everytime it gets a 502) and since it is actually supposed to send an email, it's running again and again keeps on generating infinate emails...
Thank you in advance..
Understood this finally:
The user will remain undefined until and unlesss I obtain it using the Parse.User.current() method. The data does save into the database because it is a forced update to the record, however until the user is aunthenticated using the current() method, it will remain undefined.
I see this is an old post but I spotted clear error in the code:
query = new Parse.Query("User")
Should be:
query = new Parse.Query(Parse.User)
Or at least:
query = new Parse.Query("_User")
As User is a predefined class in Parse.

Resources