mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 06:37:23 +01:00
* update API comments to for `username` restrictions and to use Login Name terminology We use "login name" rather than "username" in user-visible text on the website and (usually) when communicating with users because "username" could be confused with "profile name". Using it in the docs allows you to search for that term. * add alphanumeric and length validation for creating new login name (username) The 'en-US' locale is specified explicitly to ensure we never use another locale. The point of this change is to limit the character set to prevent login names being used to send spam in the Welcome emails, such as Chinese language spam we've had trouble with. * add error messages for bad login names * allow login name to also contain hyphens This is because our automated tests generate user accounts using: let username = generateUUID(); * allow login names to be up to 36 characters long because we use UUIDs as login names in our tests * revert back to using max 20 characters and only a-z, 0-9 for login name. It's been decided to change the username generation in the tests instead. * disable test that is failing because it's redundant Spaces are now prohibited by other code. We can probably delete this test later. I don't want to delete it now, but instead give us time to think about that. * fix typos * revert to login name restrictions that allow us to keep using our existing test code I'm really not comfortable changing our test suite in ways that aren't essential, especially since we're working in a hurry with a larger chance than normal of breaking things. The 36 character length is larger than we initially decided but not so much larger that it's a huge problem. We can reduce it to 20 when we have more time. * limit username length to 20 chars * fix tests
167 lines
6.2 KiB
JavaScript
167 lines
6.2 KiB
JavaScript
import {
|
|
generateUser,
|
|
generateGroup,
|
|
generateChallenge,
|
|
translate as t,
|
|
} from '../../../../helpers/api-v3-integration.helper';
|
|
import { v4 as generateUUID } from 'uuid';
|
|
|
|
describe('GET /challenges/:challengeId/members', () => {
|
|
let user;
|
|
|
|
beforeEach(async () => {
|
|
user = await generateUser();
|
|
});
|
|
|
|
it('validates optional req.query.lastId to be an UUID', async () => {
|
|
await expect(user.get(`/challenges/${generateUUID()}/members?lastId=invalidUUID`)).to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('invalidReqParams'),
|
|
});
|
|
});
|
|
|
|
it('fails if challenge doesn\'t exists', async () => {
|
|
await expect(user.get(`/challenges/${generateUUID()}/members`)).to.eventually.be.rejected.and.eql({
|
|
code: 404,
|
|
error: 'NotFound',
|
|
message: t('challengeNotFound'),
|
|
});
|
|
});
|
|
|
|
it('fails if user doesn\'t have access to the challenge', async () => {
|
|
let group = await generateGroup(user);
|
|
let challenge = await generateChallenge(user, group);
|
|
let anotherUser = await generateUser();
|
|
|
|
await expect(anotherUser.get(`/challenges/${challenge._id}/members`)).to.eventually.be.rejected.and.eql({
|
|
code: 404,
|
|
error: 'NotFound',
|
|
message: t('challengeNotFound'),
|
|
});
|
|
});
|
|
|
|
it('works with challenges belonging to public guild', async () => {
|
|
let leader = await generateUser({balance: 4});
|
|
let group = await generateGroup(leader, {type: 'guild', privacy: 'public', name: generateUUID()});
|
|
let challenge = await generateChallenge(leader, group);
|
|
let res = await user.get(`/challenges/${challenge._id}/members`);
|
|
expect(res[0]).to.eql({
|
|
_id: leader._id,
|
|
id: leader._id,
|
|
profile: {name: leader.profile.name},
|
|
});
|
|
expect(res[0]).to.have.all.keys(['_id', 'id', 'profile']);
|
|
expect(res[0].profile).to.have.all.keys(['name']);
|
|
});
|
|
|
|
it('populates only some fields', async () => {
|
|
let anotherUser = await generateUser({balance: 3});
|
|
let group = await generateGroup(anotherUser, {type: 'guild', privacy: 'public', name: generateUUID()});
|
|
let challenge = await generateChallenge(anotherUser, group);
|
|
let res = await user.get(`/challenges/${challenge._id}/members`);
|
|
expect(res[0]).to.eql({
|
|
_id: anotherUser._id,
|
|
id: anotherUser._id,
|
|
profile: {name: anotherUser.profile.name},
|
|
});
|
|
expect(res[0]).to.have.all.keys(['_id', 'id', 'profile']);
|
|
expect(res[0].profile).to.have.all.keys(['name']);
|
|
});
|
|
|
|
it('returns only first 30 members if req.query.includeAllMembers is not true', async () => {
|
|
let group = await generateGroup(user, {type: 'party', name: generateUUID()});
|
|
let challenge = await generateChallenge(user, group);
|
|
|
|
let usersToGenerate = [];
|
|
for (let i = 0; i < 31; i++) {
|
|
usersToGenerate.push(generateUser({challenges: [challenge._id]}));
|
|
}
|
|
await Promise.all(usersToGenerate);
|
|
|
|
let res = await user.get(`/challenges/${challenge._id}/members?includeAllMembers=not-true`);
|
|
expect(res.length).to.equal(30);
|
|
res.forEach(member => {
|
|
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
|
expect(member.profile).to.have.all.keys(['name']);
|
|
});
|
|
});
|
|
|
|
it('returns only first 30 members if req.query.includeAllMembers is not defined', async () => {
|
|
let group = await generateGroup(user, {type: 'party', name: generateUUID()});
|
|
let challenge = await generateChallenge(user, group);
|
|
|
|
let usersToGenerate = [];
|
|
for (let i = 0; i < 31; i++) {
|
|
usersToGenerate.push(generateUser({challenges: [challenge._id]}));
|
|
}
|
|
await Promise.all(usersToGenerate);
|
|
|
|
let res = await user.get(`/challenges/${challenge._id}/members`);
|
|
expect(res.length).to.equal(30);
|
|
res.forEach(member => {
|
|
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
|
expect(member.profile).to.have.all.keys(['name']);
|
|
});
|
|
});
|
|
|
|
it('returns all members if req.query.includeAllMembers is true', async () => {
|
|
let group = await generateGroup(user, {type: 'party', name: generateUUID()});
|
|
let challenge = await generateChallenge(user, group);
|
|
|
|
let usersToGenerate = [];
|
|
for (let i = 0; i < 31; i++) {
|
|
usersToGenerate.push(generateUser({challenges: [challenge._id]}));
|
|
}
|
|
await Promise.all(usersToGenerate);
|
|
|
|
let res = await user.get(`/challenges/${challenge._id}/members?includeAllMembers=true`);
|
|
expect(res.length).to.equal(32);
|
|
res.forEach(member => {
|
|
expect(member).to.have.all.keys(['_id', 'id', 'profile']);
|
|
expect(member.profile).to.have.all.keys(['name']);
|
|
});
|
|
});
|
|
|
|
it('supports using req.query.lastId to get more members', async () => {
|
|
let group = await generateGroup(user, {type: 'party', name: generateUUID()});
|
|
let challenge = await generateChallenge(user, group);
|
|
|
|
let usersToGenerate = [];
|
|
for (let i = 0; i < 57; i++) {
|
|
usersToGenerate.push(generateUser({challenges: [challenge._id]}));
|
|
}
|
|
let generatedUsers = await Promise.all(usersToGenerate); // Group has 59 members (1 is the leader)
|
|
let expectedIds = [user._id].concat(generatedUsers.map(generatedUser => generatedUser._id));
|
|
|
|
let res = await user.get(`/challenges/${challenge._id}/members`);
|
|
expect(res.length).to.equal(30);
|
|
let res2 = await user.get(`/challenges/${challenge._id}/members?lastId=${res[res.length - 1]._id}`);
|
|
expect(res2.length).to.equal(28);
|
|
|
|
let resIds = res.concat(res2).map(member => member._id);
|
|
expect(resIds).to.eql(expectedIds.sort());
|
|
});
|
|
|
|
it('supports using req.query.search to get search members', async () => {
|
|
let group = await generateGroup(user, {type: 'party', name: generateUUID()});
|
|
let challenge = await generateChallenge(user, group);
|
|
|
|
let usersToGenerate = [];
|
|
for (let i = 0; i < 3; i++) {
|
|
usersToGenerate.push(generateUser({
|
|
challenges: [challenge._id],
|
|
'profile.name': `${i}profilename`,
|
|
}));
|
|
}
|
|
let generatedUsers = await Promise.all(usersToGenerate);
|
|
let profileNames = generatedUsers.map(generatedUser => generatedUser.profile.name);
|
|
|
|
let firstProfileName = profileNames[0];
|
|
let nameToSearch = firstProfileName.substring(0, 4);
|
|
|
|
let response = await user.get(`/challenges/${challenge._id}/members?search=${nameToSearch}`);
|
|
expect(response[0].profile.name).to.eql(firstProfileName);
|
|
});
|
|
});
|