Skip to content

Commit

Permalink
refactor: Refactor custom-widget deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
alepefe committed Nov 13, 2024
1 parent 51efe94 commit 5235af0
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 20 deletions.
7 changes: 2 additions & 5 deletions api/src/modules/widgets/custom-widgets.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,8 @@ export class CustomWidgetsController {
public async deleteCustomWidget(): Promise<ControllerResponse> {
return tsRestHandler(c.deleteCustomWidget, async ({ params }) => {
const { userId, id } = params;
const data = await this.customWidgetsService.deleteCustomWidget(
userId,
id,
);
return { body: { data }, status: 200 };
await this.customWidgetsService.deleteCustomWidget(userId, id);
return { body: null, status: 204 };
});
}
}
15 changes: 4 additions & 11 deletions api/src/modules/widgets/custom-widgets.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,26 +190,19 @@ export class CustomWidgetService extends AppBaseService<
id: number,
info?: AppInfoDTO,
) {
const customWidget = await this.customWidgetRepository.findOneBy({
const result = await this.customWidgetRepository.delete({
id,
user: { id: userId },
});
if (customWidget === null) {

if (result.affected === 0) {
const exception = new NotFoundException('CustomWidget not found');
this.logger.error(
`CustomWidget with id ${id} not found`,
`CustomWidget with id ${id} for user ${info.authenticatedUser.id} not found`,
null,
exception.stack,
);
throw exception;
}

// TODO: There are differences between remove() and delete() methods of the repository. Main differences:
// 1- similarly as save() vs insert(), remove first loads the entity, effectively making two queries, while delete does not.
// 2- it has it's usages (you can check), but I don't see any reasons right now to use remove right now. I am not saying we should not use it here
// I just want you to be aware of the differences.
// 3- Following the previous point, remove mutates the original object, removing the id field, so we should be careful with the mutability
// 4- Last point, we should not return to the consumer the deleted entity, as it is not available anymore. Right now there is no usage for that
return this.customWidgetRepository.remove(customWidget);
}
}
14 changes: 12 additions & 2 deletions api/test/e2e/users/custom-widgets/custom-widget-crud.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataSourceManager } from '@api/infrastructure/data-source-manager';
import { User } from '@shared/dto/users/user.entity';
import { BaseWidget } from '@shared/dto/widgets/base-widget.entity';
import { CustomWidget } from '@shared/dto/widgets/custom-widget.entity';
import { TestManager } from 'api/test/utils/test-manager';

describe('Custom Widgets API', () => {
Expand Down Expand Up @@ -429,8 +430,17 @@ describe('Custom Widgets API', () => {
.set('Authorization', `Bearer ${authToken}`);

// Then
expect(res.status).toBe(200);
expect(res.body.data.name).toBe(customWidget.name);
expect(res.status).toBe(204);
const customWidgetRepository = testManager
.getDataSource()
.getRepository(CustomWidget);

expect(
await customWidgetRepository.findOneBy({
id: customWidget.id,
user: { id: customWidget.user.id },
}),
).toBe(null);
});

it("Shouldn't allow authenticated users to delete other user's custom widgets", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const DeleteVisualizationButton: FC<{ id: number }> = ({ id }) => {
},
});

if (response.status === 200) {
if (response.status === 204) {
queryClient.invalidateQueries(
queryKeys.users.userCharts(session?.user.id as string, {}).queryKey,
{
Expand Down
2 changes: 1 addition & 1 deletion shared/contracts/users.contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export const usersContract = contract.router({
pathParams: z.object({ userId: z.string().uuid(), id: z.coerce.number() }),
body: null,
responses: {
200: contract.type<ApiResponse<CustomWidget>>(),
204: contract.type<null>(),
400: contract.type<JSONAPIError>(),
404: contract.type<JSONAPIError>(),
500: contract.type<JSONAPIError>(),
Expand Down

0 comments on commit 5235af0

Please sign in to comment.