Skip to content

Commit

Permalink
feat: implement new use case
Browse files Browse the repository at this point in the history
As a student, I want to delete a registered task so that I can remove it from my tasks list.

This commit includes:

- Implementation of the use case for deleting a task
- Implementation of unit tests related to the use case and adapters
  • Loading branch information
Leonardo Giraldi Moreno Giuranno committed May 19, 2024
1 parent 57932ab commit 554947d
Show file tree
Hide file tree
Showing 25 changed files with 236 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
interface DeleteTaskControllerInputBoundary {
delete(id: string): Promise<void>;
}

export { DeleteTaskControllerInputBoundary };
1 change: 1 addition & 0 deletions src/adapters/task/deleteTask/boundaries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./deleteTask.controller.input.boundary";
16 changes: 16 additions & 0 deletions src/adapters/task/deleteTask/controllers/deleteTask.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { DeleteTaskControllerInputBoundary } from "..";
import { DeleteTaskInputBoundary } from "@/useCases/task";

class DeleteTaskController implements DeleteTaskControllerInputBoundary {
private inputBoundary: DeleteTaskInputBoundary;

constructor(inputBoundary: DeleteTaskInputBoundary) {
this.inputBoundary = inputBoundary;
}

async delete(id: string): Promise<void> {
return await this.inputBoundary.delete(id);
}
}

export { DeleteTaskController };
1 change: 1 addition & 0 deletions src/adapters/task/deleteTask/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./deleteTask.controller";
3 changes: 3 additions & 0 deletions src/adapters/task/deleteTask/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./boundaries";
export * from "./controllers";
export * from "./presenters";
17 changes: 17 additions & 0 deletions src/adapters/task/deleteTask/presenters/deleteTask.presenters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ResourceNotFoundException } from "@/adapters/exceptions";
import {
DeleteTaskNotFoundException,
DeleteTaskOutputBoundary,
} from "@/useCases/task";

class DeleteTaskPresenter implements DeleteTaskOutputBoundary {
presentSuccess() {
return;
}

presentDeleteTaskNotFound(error: DeleteTaskNotFoundException) {
throw new ResourceNotFoundException(error.message);
}
}

export { DeleteTaskPresenter };
1 change: 1 addition & 0 deletions src/adapters/task/deleteTask/presenters/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./deleteTask.presenters";
1 change: 1 addition & 0 deletions src/adapters/task/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./createTask";
export * from "./listTaskById";
export * from "./updateTask";
export * from "./deleteTask";
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { deleteTaskInputBoundaryMock } from "@/tests/unit/mocks/task";

import { DeleteTaskController } from "@/adapters/task";

describe("DeleteTaskController", () => {
let controller: DeleteTaskController;

beforeEach(() => {
jest.clearAllMocks();

controller = new DeleteTaskController(deleteTaskInputBoundaryMock);
});

describe("delete", () => {
it("should return undefined", async () => {
expect(await controller.delete("1")).toBeUndefined();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { DeleteTaskPresenter } from "@/adapters/task";
import { ResourceNotFoundException } from "@/adapters/exceptions";

import { DeleteTaskNotFoundException } from "@/useCases/task";

describe("DeleteTaskPresenter", () => {
let presenter: DeleteTaskPresenter;

beforeEach(() => {
jest.clearAllMocks();

presenter = new DeleteTaskPresenter();
});

describe("presentSuccess", () => {
it("should return undefined", async () => {
expect(presenter.presentSuccess()).toBeUndefined();
});
});

describe("presentDeleteTaskNotFound", () => {
it("should throw ResourceNotFoundException", async () => {
const error = new DeleteTaskNotFoundException("Task not found");

expect(() => presenter.presentDeleteTaskNotFound(error)).toThrow(
new ResourceNotFoundException(error.message)
);
});
});
});
6 changes: 6 additions & 0 deletions src/tests/unit/mocks/task/deleteTask.ds.gateway.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const deleteTaskDsGatewayMock = {
existsById: jest.fn(),
remove: jest.fn(),
};

export { deleteTaskDsGatewayMock };
5 changes: 5 additions & 0 deletions src/tests/unit/mocks/task/deleteTask.input.boundary.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const deleteTaskInputBoundaryMock = {
delete: jest.fn(),
};

export { deleteTaskInputBoundaryMock };
6 changes: 6 additions & 0 deletions src/tests/unit/mocks/task/deleteTask.output.boundary.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const deleteTaskOutputBoundaryMock = {
presentSuccess: jest.fn(),
presentDeleteTaskNotFound: jest.fn(),
};

export { deleteTaskOutputBoundaryMock };
3 changes: 3 additions & 0 deletions src/tests/unit/mocks/task/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ export * from "./listTaskById.input.boundary.mock";
export * from "./updateTask.ds.gateway.mock";
export * from "./updateTask.output.boundary.mock";
export * from "./updateTask.input.boundary.mock";
export * from "./deleteTask.ds.gateway.mock";
export * from "./deleteTask.output.boundary.mock";
export * from "./deleteTask.input.boundary.mock";
48 changes: 48 additions & 0 deletions src/tests/unit/useCases/task/deleteTask.interactor.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
deleteTaskDsGatewayMock,
deleteTaskOutputBoundaryMock,
} from "@/tests/unit/mocks/task";

import { DeleteTaskInteractor } from "@/useCases/task";

describe("DeleteTaskInteractor", () => {
let interactor: DeleteTaskInteractor;

beforeEach(() => {
jest.clearAllMocks();

interactor = new DeleteTaskInteractor(
deleteTaskDsGatewayMock,
deleteTaskOutputBoundaryMock
);
});

describe("delete", () => {
beforeEach(() => {
deleteTaskDsGatewayMock.existsById.mockResolvedValue(true);
deleteTaskDsGatewayMock.remove.mockResolvedValue(undefined);
deleteTaskOutputBoundaryMock.presentSuccess.mockReturnValue(
undefined
);
deleteTaskOutputBoundaryMock.presentDeleteTaskNotFound.mockImplementation(
() => {
throw new Error("Task not found");
}
);
});

it("should return success", async () => {
const result = await interactor.delete("1");

expect(result).toBeUndefined();
});

it("should return exception when task is not found", async () => {
deleteTaskDsGatewayMock.existsById.mockResolvedValue(false);

await expect(interactor.delete("1")).rejects.toThrow(
"Task not found"
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
interface DeleteTaskInputBoundary {
delete(id: string): Promise<void>;
}

export { DeleteTaskInputBoundary };
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { DeleteTaskNotFoundException } from "..";

interface DeleteTaskOutputBoundary {
presentSuccess(): void;

presentDeleteTaskNotFound(error: DeleteTaskNotFoundException): void;
}

export { DeleteTaskOutputBoundary };
2 changes: 2 additions & 0 deletions src/useCases/task/deleteTask/boundaries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./deleteTask.input.boundary";
export * from "./deleteTask.output.boundary";
36 changes: 36 additions & 0 deletions src/useCases/task/deleteTask/deleteTask.interactor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
DeleteTaskDsGateway,
DeleteTaskInputBoundary,
DeleteTaskNotFoundException,
DeleteTaskOutputBoundary,
} from ".";

class DeleteTaskInteractor implements DeleteTaskInputBoundary {
private dsGateway: DeleteTaskDsGateway;

private outputBoundary: DeleteTaskOutputBoundary;

constructor(
dsGateway: DeleteTaskDsGateway,
outputBoundary: DeleteTaskOutputBoundary
) {
this.dsGateway = dsGateway;
this.outputBoundary = outputBoundary;
}

async delete(id: string): Promise<void> {
if (!(await this.dsGateway.existsById(id))) {
return this.outputBoundary.presentDeleteTaskNotFound(
new DeleteTaskNotFoundException(
`Tarefa com id ${id} não encontrada`
)
);
}

await this.dsGateway.remove(id);

return this.outputBoundary.presentSuccess();
}
}

export { DeleteTaskInteractor };
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class DeleteTaskNotFoundException extends Error {
constructor(message: string) {
super(message);
this.name = "DeleteTaskNotFoundException";
}
}

export { DeleteTaskNotFoundException };
1 change: 1 addition & 0 deletions src/useCases/task/deleteTask/exceptions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./deleteTask.notFound.exception";
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
interface DeleteTaskDsGateway {
existsById(id: string): Promise<boolean>;

remove(id: string): Promise<void>;
}

export { DeleteTaskDsGateway };
1 change: 1 addition & 0 deletions src/useCases/task/deleteTask/gateways/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./deleteTask.ds.gateway";
4 changes: 4 additions & 0 deletions src/useCases/task/deleteTask/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./boundaries";
export * from "./exceptions";
export * from "./gateways";
export * from "./deleteTask.interactor";
1 change: 1 addition & 0 deletions src/useCases/task/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./createTask";
export * from "./listTaskById";
export * from "./updateTask";
export * from "./deleteTask";

0 comments on commit 554947d

Please sign in to comment.