Skip to content

Commit

Permalink
Implement DELETE /users
Browse files Browse the repository at this point in the history
 (#115)
  • Loading branch information
kimurash committed Nov 3, 2024
1 parent c350ef6 commit 429cb6a
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 26 deletions.
36 changes: 35 additions & 1 deletion backend/src/api/user.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { SelectUser, userTable } from '@/drizzle/schema';
import { zValidator } from '@hono/zod-validator';
import { and, asc, eq, like } from 'drizzle-orm';
import { and, asc, eq, inArray, like } from 'drizzle-orm';
import { drizzle } from 'drizzle-orm/d1';
import { Hono } from 'hono';
import {
createUserBody,
deleteUserParams,
deleteUsersBody,
getUserParams,
getUserResponse,
getUsersQueryParams,
Expand Down Expand Up @@ -151,6 +152,39 @@ app.post(
},
);

app.delete(
'/',
zValidator('json', deleteUsersBody, (result, ctx) => {
if (!result.success) {
return ctx.json(
{
message: 'Request Body Validation Error',
error: result.error,
},
400,
);
}
}),
async (ctx) => {
const authed = await isLoggedIn(ctx);
if (!authed) {
return ctx.json(
{
message: 'Unauthorized',
},
401,
);
}

const { userIdList } = ctx.req.valid('json');

const db = drizzle(ctx.env.DB);
await db.delete(userTable).where(inArray(userTable.id, userIdList));

return ctx.body(null, 204);
},
);

app.get(
'/:userId',
zValidator('param', getUserParams, (result, ctx) => {
Expand Down
49 changes: 26 additions & 23 deletions backend/test/api/books.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,34 +320,37 @@ describe('DELETE /books', () => {
bookFactory.resetSequenceNumber();
});

loggedInTest('should delete books', async ({ currentUser, sessionToken }) => {
const before = await db.select({ count: count() }).from(bookTable);
loggedInTest(
'should delete books successfully',
async ({ currentUser, sessionToken }) => {
const before = await db.select({ count: count() }).from(bookTable);

const bookIdList = [1, 2];
const bookIdList = [1, 2];

const response = await app.request(
'/books',
{
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
Cookie: [
`__Secure-user_id=${currentUser.id}`,
`__Secure-session_token=${sessionToken}`,
].join('; '),
const response = await app.request(
'/books',
{
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
Cookie: [
`__Secure-user_id=${currentUser.id}`,
`__Secure-session_token=${sessionToken}`,
].join('; '),
},
body: JSON.stringify({ bookIdList: bookIdList }),
},
body: JSON.stringify({ bookIdList: bookIdList }),
},
env,
);
env,
);

// ステータスコード
expect(response.status).toBe(204);
// ステータスコード
expect(response.status).toBe(204);

// データベースから書籍が削除されていることを確認する
const after = await db.select({ count: count() }).from(bookTable);
expect(after[0].count).toBe(before[0].count - bookIdList.length);
});
// データベースから書籍が削除されていることを確認する
const after = await db.select({ count: count() }).from(bookTable);
expect(after[0].count).toBe(before[0].count - bookIdList.length);
},
);

it('should return 400 when bookIdList is not array', async () => {
const response = await app.request(
Expand Down
80 changes: 79 additions & 1 deletion backend/test/api/users.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe('GET /users', () => {
describe('POST /users', () => {
const db = drizzle(env.DB);

afterAll(() => {
afterAll(async () => {
userFactory.resetSequenceNumber();
});

Expand Down Expand Up @@ -327,3 +327,81 @@ describe('POST /users', () => {
},
);
});

describe('DELETE /users', () => {
const db = drizzle(env.DB);

beforeAll(async () => {
const users = userFactory.buildList(5);
await db.insert(userTable).values(users);
});

afterAll(async () => {
await db.delete(userTable);
userFactory.resetSequenceNumber();
});

loggedInTest(
'should delete users successfully',
async ({ currentUser, sessionToken }) => {
const before = await db.select({ count: count() }).from(userTable);

const userIdList = [1, 2];

const response = await app.request(
'/users',
{
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
Cookie: [
`__Secure-user_id=${currentUser.id}`,
`__Secure-session_token=${sessionToken}`,
].join('; '),
},
body: JSON.stringify({ userIdList: userIdList }),
},
env,
);

// ステータスコード
expect(response.status).toBe(204);

// データベースからユーザが削除されていることを確認する
const after = await db.select({ count: count() }).from(userTable);
expect(after[0].count).toBe(before[0].count - userIdList.length);
},
);

it('should return 400 when userIdList is not array', async () => {
const response = await app.request(
'/users',
{
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ userIdList: 1 }),
},
env,
);

expect(response.status).toBe(400);
});

it('should return 401 when not logged in', async () => {
const response = await app.request(
'/users',
{
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ userIdList: [1] }),
},
env,
);

expect(response.status).toBe(401);
});
});
3 changes: 2 additions & 1 deletion backend/test/context/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ export const loggedInTest = test.extend({
const db = drizzle(env.DB);
const sessionToken = crypto.randomUUID();

const { id, ...rest } = user;
const insertUser = await db
.insert(userTable)
.values({
...user,
...rest,
sessionToken,
})
.returning();
Expand Down

0 comments on commit 429cb6a

Please sign in to comment.