mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
@@ -6,7 +6,7 @@ import {
|
||||
describe('DELETE /tasks/:id', () => {
|
||||
let user;
|
||||
|
||||
before(async () => {
|
||||
beforeEach(async () => {
|
||||
user = await generateUser();
|
||||
});
|
||||
|
||||
@@ -17,6 +17,7 @@ describe('DELETE /tasks/:id', () => {
|
||||
task = await user.post('/tasks/user', {
|
||||
text: 'test habit',
|
||||
type: 'habit',
|
||||
alias: 'task-to-be-deleted',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,6 +30,16 @@ describe('DELETE /tasks/:id', () => {
|
||||
message: t('taskNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('can use a alias to delete a task', async () => {
|
||||
await user.del(`/tasks/${task.alias}`);
|
||||
|
||||
await expect(user.get(`/tasks/${task._id}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('taskNotFound'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('task cannot be deleted', () => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { v4 as generateUUID } from 'uuid';
|
||||
describe('GET /tasks/:id', () => {
|
||||
let user;
|
||||
|
||||
before(async () => {
|
||||
beforeEach(async () => {
|
||||
user = await generateUser();
|
||||
});
|
||||
|
||||
@@ -18,11 +18,19 @@ describe('GET /tasks/:id', () => {
|
||||
task = await user.post('/tasks/user', {
|
||||
text: 'test habit',
|
||||
type: 'habit',
|
||||
alias: 'alias',
|
||||
});
|
||||
});
|
||||
|
||||
it('gets specified task', async () => {
|
||||
let getTask = await user.get(`/tasks/${task._id}`);
|
||||
|
||||
expect(getTask).to.eql(task);
|
||||
});
|
||||
|
||||
it('can use alias to retrieve task', async () => {
|
||||
let getTask = await user.get(`/tasks/${task.alias}`);
|
||||
|
||||
expect(getTask).to.eql(task);
|
||||
});
|
||||
|
||||
|
||||
@@ -14,12 +14,28 @@ describe('POST /tasks/:id/score/:direction', () => {
|
||||
});
|
||||
|
||||
context('all', () => {
|
||||
it('requires a task id', async () => {
|
||||
await expect(user.post('/tasks/123/score/up')).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
it('can use an id to identify the task', async () => {
|
||||
let todo = await user.post('/tasks/user', {
|
||||
text: 'test todo',
|
||||
type: 'todo',
|
||||
alias: 'alias',
|
||||
});
|
||||
|
||||
let res = await user.post(`/tasks/${todo._id}/score/up`);
|
||||
|
||||
expect(res).to.be.ok;
|
||||
});
|
||||
|
||||
it('can use a alias in place of the id', async () => {
|
||||
let todo = await user.post('/tasks/user', {
|
||||
text: 'test todo',
|
||||
type: 'todo',
|
||||
alias: 'alias',
|
||||
});
|
||||
|
||||
let res = await user.post(`/tasks/${todo.alias}/score/up`);
|
||||
|
||||
expect(res).to.be.ok;
|
||||
});
|
||||
|
||||
it('requires a task direction', async () => {
|
||||
|
||||
@@ -11,14 +11,6 @@ describe('POST /tasks/:taskId/move/to/:position', () => {
|
||||
user = await generateUser();
|
||||
});
|
||||
|
||||
it('requires a valid taskId', async () => {
|
||||
await expect(user.post('/tasks/123/move/to/1')).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
});
|
||||
|
||||
it('requires a numeric position parameter', async () => {
|
||||
await expect(user.post(`/tasks/${generateUUID()}/move/to/notANumber`)).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
@@ -53,6 +45,24 @@ describe('POST /tasks/:taskId/move/to/:position', () => {
|
||||
expect(newOrder.length).to.equal(5);
|
||||
});
|
||||
|
||||
it('can move task to new position using alias', async () => {
|
||||
let tasks = await user.post('/tasks/user', [
|
||||
{type: 'habit', text: 'habit 1'},
|
||||
{type: 'habit', text: 'habit 2', alias: 'move'},
|
||||
{type: 'daily', text: 'daily 1'},
|
||||
{type: 'habit', text: 'habit 3'},
|
||||
{type: 'habit', text: 'habit 4'},
|
||||
{type: 'todo', text: 'todo 1'},
|
||||
{type: 'habit', text: 'habit 5'},
|
||||
]);
|
||||
|
||||
let taskToMove = tasks[1];
|
||||
expect(taskToMove.text).to.equal('habit 2');
|
||||
let newOrder = await user.post(`/tasks/${taskToMove.alias}/move/to/3`);
|
||||
expect(newOrder[3]).to.equal(taskToMove._id);
|
||||
expect(newOrder.length).to.equal(5);
|
||||
});
|
||||
|
||||
it('can\'t move completed todo', async () => {
|
||||
let task = await user.post('/tasks/user', {type: 'todo', text: 'todo 1'});
|
||||
await user.post(`/tasks/${task._id}/score/up`);
|
||||
|
||||
@@ -57,7 +57,7 @@ describe('POST /tasks/user', () => {
|
||||
let originalHabitsOrder = (await user.get('/user')).tasksOrder.habits;
|
||||
await expect(user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
})).to.eventually.be.rejected.and.eql({ // this block is necessary
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'habit validation failed',
|
||||
@@ -72,7 +72,7 @@ describe('POST /tasks/user', () => {
|
||||
await expect(user.post('/tasks/user', [
|
||||
{type: 'habit'}, // Missing text
|
||||
{type: 'habit', text: 'valid'}, // Valid
|
||||
])).to.eventually.be.rejected.and.eql({ // this block is necessary
|
||||
])).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'habit validation failed',
|
||||
@@ -87,7 +87,7 @@ describe('POST /tasks/user', () => {
|
||||
await expect(user.post('/tasks/user', [
|
||||
{type: 'habit'}, // Missing text
|
||||
{type: 'habit', text: 'valid'}, // Valid
|
||||
])).to.eventually.be.rejected.and.eql({ // this block is necessary
|
||||
])).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'habit validation failed',
|
||||
@@ -142,6 +142,67 @@ describe('POST /tasks/user', () => {
|
||||
|
||||
expect(task).not.to.have.property('notValid');
|
||||
});
|
||||
|
||||
it('errors if alias already exists on another task', async () => {
|
||||
await user.post('/tasks/user', { // first task that will succeed
|
||||
type: 'habit',
|
||||
text: 'todo text',
|
||||
alias: 'alias',
|
||||
});
|
||||
|
||||
await expect(user.post('/tasks/user', {
|
||||
type: 'todo',
|
||||
text: 'todo text',
|
||||
alias: 'alias',
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'todo validation failed',
|
||||
});
|
||||
});
|
||||
|
||||
it('errors if alias contains invalid values', async () => {
|
||||
await expect(user.post('/tasks/user', {
|
||||
type: 'todo',
|
||||
text: 'todo text',
|
||||
alias: 'short name!',
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'todo validation failed',
|
||||
});
|
||||
});
|
||||
|
||||
it('errors if alias is a valid uuid', async () => {
|
||||
await expect(user.post('/tasks/user', {
|
||||
type: 'todo',
|
||||
text: 'todo text',
|
||||
alias: generateUUID(),
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'todo validation failed',
|
||||
});
|
||||
});
|
||||
|
||||
it('errors if the same shortname is used on 2 or more tasks', async () => {
|
||||
await expect(user.post('/tasks/user', [{
|
||||
type: 'habit',
|
||||
text: 'habit text',
|
||||
alias: 'alias',
|
||||
}, {
|
||||
type: 'todo',
|
||||
text: 'todo text',
|
||||
}, {
|
||||
type: 'todo',
|
||||
text: 'todo text',
|
||||
alias: 'alias',
|
||||
}])).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('taskAliasAlreadyUsed'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('all types', () => {
|
||||
@@ -163,6 +224,16 @@ describe('POST /tasks/user', () => {
|
||||
expect(task.reminders[0].startDate).to.be.a('string'); // json doesn't have dates
|
||||
expect(task.reminders[0].time).to.be.a('string');
|
||||
});
|
||||
|
||||
it('can create a task with a alias', async () => {
|
||||
let task = await user.post('/tasks/user', {
|
||||
text: 'test habit',
|
||||
type: 'habit',
|
||||
alias: 'a_alias012',
|
||||
});
|
||||
|
||||
expect(task.alias).to.eql('a_alias012');
|
||||
});
|
||||
});
|
||||
|
||||
context('habits', () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { v4 as generateUUID } from 'uuid';
|
||||
describe('PUT /tasks/:id', () => {
|
||||
let user;
|
||||
|
||||
before(async () => {
|
||||
beforeEach(async () => {
|
||||
user = await generateUser();
|
||||
});
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('PUT /tasks/:id', () => {
|
||||
expect(savedTask.notValid).to.be.undefined;
|
||||
});
|
||||
|
||||
it(`only allows setting streak, reminders, checklist, notes, attribute, tags
|
||||
it(`only allows setting streak, alias, reminders, checklist, notes, attribute, tags
|
||||
fields for challenge tasks owned by a user`, async () => {
|
||||
let guild = await generateGroup(user);
|
||||
let challenge = await generateChallenge(user, guild);
|
||||
@@ -87,6 +87,7 @@ describe('PUT /tasks/:id', () => {
|
||||
_id: 123,
|
||||
type: 'daily',
|
||||
userId: 123,
|
||||
alias: 'a-short-task-name',
|
||||
history: [123],
|
||||
createdAt: 'yesterday',
|
||||
updatedAt: 'tomorrow',
|
||||
@@ -176,6 +177,44 @@ describe('PUT /tasks/:id', () => {
|
||||
expect(savedDaily.reminders[0].id).to.equal(id1);
|
||||
expect(savedDaily.reminders[1].id).to.equal(id2);
|
||||
});
|
||||
|
||||
it('can set a alias if no other task has that alias', async () => {
|
||||
let savedDaily = await user.put(`/tasks/${daily._id}`, {
|
||||
alias: 'alias',
|
||||
});
|
||||
|
||||
expect(savedDaily.alias).to.eql('alias');
|
||||
});
|
||||
|
||||
it('does not set alias to a alias that is already in use', async () => {
|
||||
await user.post('/tasks/user', {
|
||||
type: 'todo',
|
||||
text: 'a todo',
|
||||
alias: 'some-alias',
|
||||
});
|
||||
|
||||
await expect(user.put(`/tasks/${daily._id}`, {
|
||||
alias: 'some-alias',
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'daily validation failed',
|
||||
});
|
||||
});
|
||||
|
||||
it('can use alias to update a task', async () => {
|
||||
daily = await user.put(`/tasks/${daily._id}`, {
|
||||
alias: 'alias',
|
||||
});
|
||||
|
||||
await user.put(`/tasks/${daily.alias}`, {
|
||||
text: 'saved',
|
||||
});
|
||||
|
||||
let fetchedDaily = await user.get(`/tasks/${daily._id}`);
|
||||
|
||||
expect(fetchedDaily.text).to.eql('saved');
|
||||
});
|
||||
});
|
||||
|
||||
context('habits', () => {
|
||||
|
||||
@@ -49,6 +49,18 @@ describe('POST /tasks/challenge/:challengeId', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error when user tries to create task with a alias', async () => {
|
||||
await expect(user.post(`/tasks/challenge/${challenge._id}`, {
|
||||
text: 'test habit',
|
||||
type: 'habit',
|
||||
alias: 'a-alias',
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'habit validation failed',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error when non leader tries to edit challenge', async () => {
|
||||
let userThatIsNotLeaderOfChallenge = await generateUser({
|
||||
challenges: [challenge._id],
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
generateGroup,
|
||||
generateChallenge,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-integration/v3';
|
||||
} from '../../../../../helpers/api-integration/v3';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
|
||||
describe('PUT /tasks/:id', () => {
|
||||
@@ -54,6 +54,16 @@ describe('PUT /tasks/:id', () => {
|
||||
message: t('onlyChalLeaderEditTasks'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error when user attempts to update task with a alias', async () => {
|
||||
await expect(user.put(`/tasks/${task._id}`, {
|
||||
alias: 'a-alias',
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'habit validation failed',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('validates params', () => {
|
||||
@@ -25,6 +25,21 @@ describe('DELETE /tasks/:taskId/checklist/:itemId', () => {
|
||||
expect(savedTask.checklist.length).to.equal(0);
|
||||
});
|
||||
|
||||
it('deletes a checklist item using task alias', async () => {
|
||||
let task = await user.post('/tasks/user', {
|
||||
type: 'daily',
|
||||
text: 'Daily with checklist',
|
||||
alias: 'daily-with-alias',
|
||||
});
|
||||
|
||||
let savedTask = await user.post(`/tasks/${task._id}/checklist`, {text: 'Checklist Item 1', completed: false});
|
||||
|
||||
await user.del(`/tasks/${task.alias}/checklist/${savedTask.checklist[0].id}`);
|
||||
savedTask = await user.get(`/tasks/${task._id}`);
|
||||
|
||||
expect(savedTask.checklist.length).to.equal(0);
|
||||
});
|
||||
|
||||
it('does not work with habits', async () => {
|
||||
let habit = await user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
|
||||
@@ -31,6 +31,27 @@ describe('POST /tasks/:taskId/checklist/', () => {
|
||||
expect(savedTask.checklist[0].ignored).to.be.an('undefined');
|
||||
});
|
||||
|
||||
it('can use a alias to add checklist', async () => {
|
||||
let task = await user.post('/tasks/user', {
|
||||
type: 'daily',
|
||||
text: 'Daily with checklist',
|
||||
alias: 'task-with-shortname',
|
||||
});
|
||||
|
||||
let savedTask = await user.post(`/tasks/${task.alias}/checklist`, {
|
||||
text: 'Checklist Item 1',
|
||||
ignored: false,
|
||||
_id: 123,
|
||||
});
|
||||
|
||||
expect(savedTask.checklist.length).to.equal(1);
|
||||
expect(savedTask.checklist[0].text).to.equal('Checklist Item 1');
|
||||
expect(savedTask.checklist[0].completed).to.equal(false);
|
||||
expect(savedTask.checklist[0].id).to.be.a('string');
|
||||
expect(savedTask.checklist[0].id).to.not.equal('123');
|
||||
expect(savedTask.checklist[0].ignored).to.be.an('undefined');
|
||||
});
|
||||
|
||||
it('does not add a checklist to habits', async () => {
|
||||
let habit = await user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
|
||||
@@ -28,6 +28,24 @@ describe('POST /tasks/:taskId/checklist/:itemId/score', () => {
|
||||
expect(savedTask.checklist[0].completed).to.equal(true);
|
||||
});
|
||||
|
||||
it('can use a alias to score a checklist item', async () => {
|
||||
let task = await user.post('/tasks/user', {
|
||||
type: 'daily',
|
||||
text: 'Daily with checklist',
|
||||
alias: 'daily-with-shortname',
|
||||
});
|
||||
|
||||
let savedTask = await user.post(`/tasks/${task._id}/checklist`, {
|
||||
text: 'Checklist Item 1',
|
||||
completed: false,
|
||||
});
|
||||
|
||||
savedTask = await user.post(`/tasks/${task.alias}/checklist/${savedTask.checklist[0].id}/score`);
|
||||
|
||||
expect(savedTask.checklist.length).to.equal(1);
|
||||
expect(savedTask.checklist[0].completed).to.equal(true);
|
||||
});
|
||||
|
||||
it('fails on habits', async () => {
|
||||
let habit = await user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
|
||||
@@ -34,6 +34,30 @@ describe('PUT /tasks/:taskId/checklist/:itemId', () => {
|
||||
expect(savedTask.checklist[0].id).to.not.equal('123');
|
||||
});
|
||||
|
||||
it('updates a checklist item using task alias', async () => {
|
||||
let task = await user.post('/tasks/user', {
|
||||
type: 'daily',
|
||||
text: 'Daily with checklist',
|
||||
alias: 'daily-with-shortname',
|
||||
});
|
||||
|
||||
let savedTask = await user.post(`/tasks/${task._id}/checklist`, {
|
||||
text: 'Checklist Item 1',
|
||||
completed: false,
|
||||
});
|
||||
|
||||
savedTask = await user.put(`/tasks/${task.alias}/checklist/${savedTask.checklist[0].id}`, {
|
||||
text: 'updated',
|
||||
completed: true,
|
||||
_id: 123, // ignored
|
||||
});
|
||||
|
||||
expect(savedTask.checklist.length).to.equal(1);
|
||||
expect(savedTask.checklist[0].text).to.equal('updated');
|
||||
expect(savedTask.checklist[0].completed).to.equal(true);
|
||||
expect(savedTask.checklist[0].id).to.not.equal('123');
|
||||
});
|
||||
|
||||
it('fails on habits', async () => {
|
||||
let habit = await user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
|
||||
@@ -27,6 +27,23 @@ describe('DELETE /tasks/:taskId/tags/:tagId', () => {
|
||||
expect(updatedTask.tags.length).to.equal(0);
|
||||
});
|
||||
|
||||
it('removes a tag from a task using task short name', async () => {
|
||||
let task = await user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
text: 'Task with tag',
|
||||
alias: 'habit-with-alias',
|
||||
});
|
||||
|
||||
let tag = await user.post('/tags', {name: 'Tag 1'});
|
||||
|
||||
await user.post(`/tasks/${task._id}/tags/${tag.id}`);
|
||||
await user.del(`/tasks/${task.alias}/tags/${tag.id}`);
|
||||
|
||||
let updatedTask = await user.get(`/tasks/${task._id}`);
|
||||
|
||||
expect(updatedTask.tags.length).to.equal(0);
|
||||
});
|
||||
|
||||
it('only deletes existing tags', async () => {
|
||||
let createdTask = await user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
|
||||
@@ -23,6 +23,19 @@ describe('POST /tasks/:taskId/tags/:tagId', () => {
|
||||
expect(savedTask.tags[0]).to.equal(tag.id);
|
||||
});
|
||||
|
||||
it('adds a tag to a task with alias', async () => {
|
||||
let task = await user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
text: 'Task with tag',
|
||||
alias: 'habit-with-alias',
|
||||
});
|
||||
|
||||
let tag = await user.post('/tags', {name: 'Tag 1'});
|
||||
let savedTask = await user.post(`/tasks/${task.alias}/tags/${tag.id}`);
|
||||
|
||||
expect(savedTask.tags[0]).to.equal(tag.id);
|
||||
});
|
||||
|
||||
it('does not add a tag to a task twice', async () => {
|
||||
let task = await user.post('/tasks/user', {
|
||||
type: 'habit',
|
||||
|
||||
Reference in New Issue
Block a user