* feat: Add alias property to task model
This commit is contained in:
Blade Barringer
2016-06-16 12:28:45 -05:00
committed by GitHub
parent c34c21192b
commit b7b61e6251
21 changed files with 536 additions and 97 deletions

View File

@@ -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', () => {

View File

@@ -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);
});

View File

@@ -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 () => {

View File

@@ -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`);

View File

@@ -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', () => {

View File

@@ -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', () => {

View File

@@ -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],

View File

@@ -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', () => {

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',