diff --git a/libs/tasks/application/src/lib/user-tasks.service.ts b/libs/tasks/application/src/lib/user-tasks.service.ts index 01940b7..793b87e 100644 --- a/libs/tasks/application/src/lib/user-tasks.service.ts +++ b/libs/tasks/application/src/lib/user-tasks.service.ts @@ -1,11 +1,10 @@ import { Injectable } from '@nestjs/common'; -import { UserTask } from '@tasks/domain'; @Injectable() export class UserTasksService { async findMany( userId: string, - ): Promise { + ): Promise<[]> { // TODO: Implement this return []; } diff --git a/libs/tasks/domain/src/lib/entities/task.entity.spec.ts b/libs/tasks/domain/src/lib/entities/task.entity.spec.ts index f86601b..8f940d1 100644 --- a/libs/tasks/domain/src/lib/entities/task.entity.spec.ts +++ b/libs/tasks/domain/src/lib/entities/task.entity.spec.ts @@ -1,39 +1,35 @@ import { Task } from './task.entity'; describe('Task', () => { - it('should create a task with all properties', () => { - const task = new Task( - 'test-id', - 'Test Title', - 'Test Description', - ['category1', 'category2'] - ); + describe('create', () => { + it('should create a new task', () => { + const task = Task.create('id', 'Test Task', 'Test Description', [ + 'category1', + 'category2', + ]); - expect(task.id).toBe('test-id'); - expect(task.title).toBe('Test Title'); - expect(task.description).toBe('Test Description'); - expect(task.categories).toEqual(['category1', 'category2']); - }); + expect(task.id).toBe('id'); + expect(task.title).toBe('Test Task'); + expect(task.description).toBe('Test Description'); + expect(task.categories).toEqual(['category1', 'category2']); + }); - it('should allow null description', () => { - const task = new Task( - 'test-id', - 'Test Title', - null, - ['category1'] - ); + it('should create a task with null description', () => { + const task = Task.create('id', 'Test Task', null, ['category1']); - expect(task.description).toBeNull(); - }); + expect(task.id).toBe('id'); + expect(task.title).toBe('Test Task'); + expect(task.description).toBeNull(); + expect(task.categories).toEqual(['category1']); + }); - it('should create a task with empty categories array', () => { - const task = new Task( - 'test-id', - 'Test Title', - 'Test Description', - [] - ); + it('should create a task with empty categories', () => { + const task = Task.create('id', 'Test Task', 'Test Description', []); - expect(task.categories).toEqual([]); + expect(task.id).toBe('id'); + expect(task.title).toBe('Test Task'); + expect(task.description).toBe('Test Description'); + expect(task.categories).toEqual([]); + }); }); }); diff --git a/libs/tasks/domain/src/lib/entities/task.entity.ts b/libs/tasks/domain/src/lib/entities/task.entity.ts index 430a6d5..ee85587 100644 --- a/libs/tasks/domain/src/lib/entities/task.entity.ts +++ b/libs/tasks/domain/src/lib/entities/task.entity.ts @@ -1,8 +1,20 @@ export class Task { - constructor( + private constructor( public readonly id: string, public readonly title: string, public readonly description: string | null, public readonly categories: string[], ) {} + + /** + * Creates a new task + */ + static create( + id: string, + title: string, + description: string | null, + categories: string[], + ): Task { + return new Task(id, title, description, categories); + } } diff --git a/libs/tasks/domain/src/lib/entities/user-task.entity.spec.ts b/libs/tasks/domain/src/lib/entities/user-task.entity.spec.ts index c02282d..c587c9d 100644 --- a/libs/tasks/domain/src/lib/entities/user-task.entity.spec.ts +++ b/libs/tasks/domain/src/lib/entities/user-task.entity.spec.ts @@ -1,30 +1,53 @@ -import { User } from '@users/domain'; -import { Task } from './task.entity'; +import { TaskStatusEnum } from '../value-objects/task-status.enum'; import { UserTask } from './user-task.entity'; describe('UserTask', () => { - it('should create a user task instance', () => { - const task = new Task('task-1', 'Test Task', 'Description', ['category1']); - const user = new User('user-1', 'test@example.com', null, null); - const now = new Date(); - - const userTask = new UserTask( - 'user-task-1', - now, - null, - 'task-1', - task, - 'user-1', - user, - ); - - expect(userTask).toBeDefined(); - expect(userTask.id).toBe('user-task-1'); - expect(userTask.createdAt).toBe(now); - expect(userTask.updatedAt).toBeNull(); - expect(userTask.taskId).toBe('task-1'); - expect(userTask.task).toBe(task); - expect(userTask.userId).toBe('user-1'); - expect(userTask.user).toBe(user); + describe('create', () => { + it('should create a new user task with TODO status', () => { + const task = UserTask.create('id', 'userId', 'taskId'); + + expect(task.id).toBe('id'); + expect(task.userId).toBe('userId'); + expect(task.taskId).toBe('taskId'); + expect(task.status).toBe(TaskStatusEnum.TODO); + expect(task.updatedAt).toBeNull(); + expect(task.createdAt).toBeInstanceOf(Date); + }); + }); + + describe('markAsInProgress', () => { + it('should mark task as in progress', () => { + const task = UserTask.create('id', 'userId', 'taskId'); + const inProgressTask = task.markAsInProgress(); + + expect(inProgressTask.status).toBe(TaskStatusEnum.IN_PROGRESS); + expect(inProgressTask.updatedAt).toBeInstanceOf(Date); + }); + + it('should return same instance if already in progress', () => { + const task = UserTask.create('id', 'userId', 'taskId'); + const inProgressTask = task.markAsInProgress(); + const sameTask = inProgressTask.markAsInProgress(); + + expect(sameTask).toBe(inProgressTask); + }); + }); + + describe('markAsDone', () => { + it('should mark task as done', () => { + const task = UserTask.create('id', 'userId', 'taskId'); + const doneTask = task.markAsDone(); + + expect(doneTask.status).toBe(TaskStatusEnum.DONE); + expect(doneTask.updatedAt).toBeInstanceOf(Date); + }); + + it('should return same instance if already done', () => { + const task = UserTask.create('id', 'userId', 'taskId'); + const doneTask = task.markAsDone(); + const sameTask = doneTask.markAsDone(); + + expect(sameTask).toBe(doneTask); + }); }); }); diff --git a/libs/tasks/domain/src/lib/entities/user-task.entity.ts b/libs/tasks/domain/src/lib/entities/user-task.entity.ts index de62bf6..6d53d95 100644 --- a/libs/tasks/domain/src/lib/entities/user-task.entity.ts +++ b/libs/tasks/domain/src/lib/entities/user-task.entity.ts @@ -1,15 +1,60 @@ -import { User } from '@users/domain'; - -import { Task } from './task.entity'; +import { TaskStatus, TaskStatusEnum } from '../value-objects/task-status.enum'; export class UserTask { - constructor( + private constructor( public readonly id: string, + public readonly userId: string, + public readonly taskId: string, public readonly createdAt: Date, public readonly updatedAt: Date | null, - public readonly taskId: string, - public readonly task: Task | null, - public readonly userId: string, - public readonly user: User | null, + public readonly status: TaskStatus, ) {} + + /** + * Creates a new user task + */ + static create(id: string, userId: string, taskId: string): UserTask { + return new UserTask( + id, + userId, + taskId, + new Date(), + null, + TaskStatusEnum.TODO, + ); + } + + /** + * Marks the task as in progress + */ + markAsInProgress(): UserTask { + if (this.status === TaskStatusEnum.IN_PROGRESS) { + return this; + } + return new UserTask( + this.id, + this.userId, + this.taskId, + this.createdAt, + new Date(), + TaskStatusEnum.IN_PROGRESS, + ); + } + + /** + * Marks the task as done + */ + markAsDone(): UserTask { + if (this.status === TaskStatusEnum.DONE) { + return this; + } + return new UserTask( + this.id, + this.userId, + this.taskId, + this.createdAt, + new Date(), + TaskStatusEnum.DONE, + ); + } }