Skip to content
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

test: improve transaction tests to use async/await #7759

Merged
merged 10 commits into from
Jan 3, 2022
321 changes: 109 additions & 212 deletions spec/ParseServerRESTController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,18 @@ describe('ParseServerRESTController', () => {
);
});

it('should handle a get request', done => {
RESTController.request('GET', '/classes/MyObject').then(
res => {
expect(res.results.length).toBe(0);
done();
},
err => {
console.log(err);
jfail(err);
done();
}
);
it('should handle a get request', async () => {
const res = await RESTController.request('GET', '/classes/MyObject');
expect(res.results.length).toBe(0);
});

it('should handle a get request with full serverURL mount path', done => {
RESTController.request('GET', '/1/classes/MyObject').then(
res => {
expect(res.results.length).toBe(0);
done();
},
err => {
jfail(err);
done();
}
);
it('should handle a get request with full serverURL mount path', async () => {
const res = await RESTController.request('GET', '/1/classes/MyObject');
expect(res.results.length).toBe(0);
});

it('should handle a POST batch without transaction', done => {
RESTController.request('POST', 'batch', {
it('should handle a POST batch without transaction', async () => {
const res = await RESTController.request('POST', 'batch', {
requests: [
{
method: 'GET',
Expand All @@ -59,20 +42,12 @@ describe('ParseServerRESTController', () => {
path: '/classes/MyObject',
},
],
}).then(
res => {
expect(res.length).toBe(3);
done();
},
err => {
jfail(err);
done();
}
);
});
expect(res.length).toBe(3);
});

it('should handle a POST batch with transaction=false', done => {
RESTController.request('POST', 'batch', {
it('should handle a POST batch with transaction=false', async () => {
const res = await RESTController.request('POST', 'batch', {
requests: [
{
method: 'GET',
Expand All @@ -89,16 +64,8 @@ describe('ParseServerRESTController', () => {
},
],
transaction: false,
}).then(
res => {
expect(res.length).toBe(3);
done();
},
err => {
jfail(err);
done();
}
);
});
expect(res.length).toBe(3);
});

it('should handle response status', async () => {
Expand Down Expand Up @@ -186,54 +153,43 @@ describe('ParseServerRESTController', () => {
}
});

it('should handle a batch request with transaction = true', async done => {
await reconfigureServer();
it('should handle a batch request with transaction = true', async () => {
const myObject = new Parse.Object('MyObject'); // This is important because transaction only works on pre-existing collections
myObject
.save()
.then(() => {
return myObject.destroy();
})
.then(() => {
spyOn(databaseAdapter, 'createObject').and.callThrough();

return RESTController.request('POST', 'batch', {
requests: [
{
method: 'POST',
path: '/1/classes/MyObject',
body: { key: 'value1' },
},
{
method: 'POST',
path: '/1/classes/MyObject',
body: { key: 'value2' },
},
],
transaction: true,
}).then(response => {
expect(response.length).toEqual(2);
expect(response[0].success.objectId).toBeDefined();
expect(response[0].success.createdAt).toBeDefined();
expect(response[1].success.objectId).toBeDefined();
expect(response[1].success.createdAt).toBeDefined();
const query = new Parse.Query('MyObject');
return query.find().then(results => {
expect(databaseAdapter.createObject.calls.count() % 2).toBe(0);
for (let i = 0; i + 1 < databaseAdapter.createObject.calls.length; i = i + 2) {
expect(databaseAdapter.createObject.calls.argsFor(i)[3]).toBe(
databaseAdapter.createObject.calls.argsFor(i + 1)[3]
);
}
expect(results.map(result => result.get('key')).sort()).toEqual([
'value1',
'value2',
]);
done();
});
});
})
.catch(done.fail);
await myObject.save();
await myObject.destroy();
spyOn(databaseAdapter, 'createObject').and.callThrough();
const response = await RESTController.request('POST', 'batch', {
requests: [
{
method: 'POST',
path: '/1/classes/MyObject',
body: { key: 'value1' },
},
{
method: 'POST',
path: '/1/classes/MyObject',
body: { key: 'value2' },
},
],
transaction: true,
});
expect(response.length).toEqual(2);
expect(response[0].success.objectId).toBeDefined();
expect(response[0].success.createdAt).toBeDefined();
expect(response[1].success.objectId).toBeDefined();
expect(response[1].success.createdAt).toBeDefined();
const query = new Parse.Query('MyObject');
const results = await query.find();
expect(databaseAdapter.createObject.calls.count() % 2).toBe(0);
for (let i = 0; i + 1 < databaseAdapter.createObject.calls.length; i = i + 2) {
expect(databaseAdapter.createObject.calls.argsFor(i)[3]).toBe(
databaseAdapter.createObject.calls.argsFor(i + 1)[3]
);
}
expect(results.map(result => result.get('key')).sort()).toEqual([
'value1',
'value2',
]);
});

it('should not save anything when one operation fails in a transaction', async () => {
Expand Down Expand Up @@ -560,21 +516,11 @@ describe('ParseServerRESTController', () => {
});
}

it('should handle a POST request', done => {
RESTController.request('POST', '/classes/MyObject', { key: 'value' })
.then(() => {
return RESTController.request('GET', '/classes/MyObject');
})
.then(res => {
expect(res.results.length).toBe(1);
expect(res.results[0].key).toEqual('value');
done();
})
.catch(err => {
console.log(err);
jfail(err);
done();
});
it('should handle a POST request', async () => {
await RESTController.request('POST', '/classes/MyObject', { key: 'value' });
const res = await RESTController.request('GET', '/classes/MyObject');
expect(res.results.length).toBe(1);
expect(res.results[0].key).toEqual('value');
});

it('should handle a POST request with context', async () => {
Expand All @@ -593,125 +539,76 @@ describe('ParseServerRESTController', () => {
);
});

it('ensures sessionTokens are properly handled', done => {
let userId;
Parse.User.signUp('user', 'pass')
.then(user => {
userId = user.id;
const sessionToken = user.getSessionToken();
return RESTController.request('GET', '/users/me', undefined, {
sessionToken,
});
})
.then(res => {
// Result is in JSON format
expect(res.objectId).toEqual(userId);
done();
})
.catch(err => {
console.log(err);
jfail(err);
done();
});
it('ensures sessionTokens are properly handled', async () => {
const user = await Parse.User.signUp('user', 'pass');
const sessionToken = user.getSessionToken();
const res = await RESTController.request('GET', '/users/me', undefined, {
sessionToken,
});
// Result is in JSON format
expect(res.objectId).toEqual(user.id);
});

it('ensures masterKey is properly handled', done => {
let userId;
Parse.User.signUp('user', 'pass')
.then(user => {
userId = user.id;
return Parse.User.logOut().then(() => {
return RESTController.request('GET', '/classes/_User', undefined, {
useMasterKey: true,
});
});
})
.then(
res => {
expect(res.results.length).toBe(1);
expect(res.results[0].objectId).toEqual(userId);
done();
},
err => {
jfail(err);
done();
}
);
it('ensures masterKey is properly handled', async () => {
const user = await Parse.User.signUp('user', 'pass');
const userId = user.id;
await Parse.User.logOut();
const res = await RESTController.request('GET', '/classes/_User', undefined, {
useMasterKey: true,
});
expect(res.results.length).toBe(1);
expect(res.results[0].objectId).toEqual(userId);
});

it('ensures no user is created when passing an empty username', done => {
RESTController.request('POST', '/classes/_User', {
username: '',
password: 'world',
}).then(
() => {
jfail(new Error('Success callback should not be called when passing an empty username.'));
done();
},
err => {
expect(err.code).toBe(Parse.Error.USERNAME_MISSING);
expect(err.message).toBe('bad or missing username');
done();
}
);
it('ensures no user is created when passing an empty username', async () => {
try {
await RESTController.request('POST', '/classes/_User', {
username: '',
password: 'world',
});
fail('Success callback should not be called when passing an empty username.');
} catch (err) {
expect(err.code).toBe(Parse.Error.USERNAME_MISSING);
expect(err.message).toBe('bad or missing username');
}
});

it('ensures no user is created when passing an empty password', done => {
RESTController.request('POST', '/classes/_User', {
username: 'hello',
password: '',
}).then(
() => {
jfail(new Error('Success callback should not be called when passing an empty password.'));
done();
},
err => {
expect(err.code).toBe(Parse.Error.PASSWORD_MISSING);
expect(err.message).toBe('password is required');
done();
}
);
it('ensures no user is created when passing an empty password', async () => {
try {
await RESTController.request('POST', '/classes/_User', {
username: 'hello',
password: '',
});
fail('Success callback should not be called when passing an empty password.');
} catch (err) {
expect(err.code).toBe(Parse.Error.PASSWORD_MISSING);
expect(err.message).toBe('password is required');
}
});

it('ensures no session token is created on creating users', done => {
RESTController.request('POST', '/classes/_User', {
it('ensures no session token is created on creating users', async () => {
const user = await RESTController.request('POST', '/classes/_User', {
username: 'hello',
password: 'world',
})
.then(user => {
expect(user.sessionToken).toBeUndefined();
const query = new Parse.Query('_Session');
return query.find({ useMasterKey: true });
})
.then(sessions => {
expect(sessions.length).toBe(0);
done();
}, done.fail);
});
expect(user.sessionToken).toBeUndefined();
const query = new Parse.Query('_Session');
const sessions = await query.find({ useMasterKey: true });
expect(sessions.length).toBe(0);
});

it('ensures a session token is created when passing installationId != cloud', done => {
RESTController.request(
it('ensures a session token is created when passing installationId != cloud', async () => {
const user = await RESTController.request(
'POST',
'/classes/_User',
{ username: 'hello', password: 'world' },
{ installationId: 'my-installation' }
)
.then(user => {
expect(user.sessionToken).not.toBeUndefined();
const query = new Parse.Query('_Session');
return query.find({ useMasterKey: true });
})
.then(
sessions => {
expect(sessions.length).toBe(1);
expect(sessions[0].get('installationId')).toBe('my-installation');
done();
},
err => {
jfail(err);
done();
}
);
);
expect(user.sessionToken).not.toBeUndefined();
const query = new Parse.Query('_Session');
const sessions = await query.find({ useMasterKey: true });
expect(sessions.length).toBe(1);
expect(sessions[0].get('installationId')).toBe('my-installation');
});

it('ensures logIn is saved with installationId', async () => {
Expand Down
Loading