Skip to content

Commit 0c8a65d

Browse files
authored
Merge pull request #61 from boostcampwm-2022/feat/#51-S
Feat/#51-S : ํŠน์ • ์›Œํฌ์ŠคํŽ˜์ด์Šค์˜ ๋ฉค๋ฒ„, ํšŒ์˜๋ก ๋ชฉ๋ก ์กฐํšŒํ•˜๊ธฐ API ๊ตฌ์ถ•
2 parents 36ff386 + b606559 commit 0c8a65d

File tree

6 files changed

+112
-4
lines changed

6 files changed

+112
-4
lines changed

โ€Žserver/apis/user/model.tsโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Schema } from 'mongoose';
22
import mongoose from '@db';
33

4-
interface User {
4+
export interface User {
55
id: number;
66
name: string;
77
avatarUrl: string;

โ€Žserver/apis/workspace/controller.tsโ€Ž

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,23 @@ import asyncWrapper from '@utils/async-wrapper';
33
import jwtAuthenticator from '@middlewares/jwt-authenticator';
44
import * as workspaceService from './service';
55
import { CREATED } from '@constants/http-status';
6-
import { PostParams, PostJoinParams } from '@params/workspace';
6+
import { PostParams, PostJoinParams, GetInfoParams } from '@params/workspace';
77

88
const router = express.Router();
99

10+
/* POST: ์›Œํฌ์ŠคํŽ˜์ด์Šค ์ƒ์„ฑ */
1011
router.post(
1112
'/',
1213
asyncWrapper(async (req: Request<PostParams>, res: Response) => {
1314
const { name } = req.body;
1415

1516
const workspace = await workspaceService.create(name);
1617

17-
res.status(CREATED).send({ ...workspace });
18+
res.status(CREATED).send(workspace);
1819
}),
1920
);
2021

22+
/* POST: ์›Œํฌ์ŠคํŽ˜์ด์Šค ์ฐธ์—ฌ */
2123
router.post(
2224
'/join',
2325
jwtAuthenticator,
@@ -30,4 +32,17 @@ router.post(
3032
}),
3133
);
3234

35+
/* GET: ํŠน์ • ์›Œํฌ์ŠคํŽ˜์ด์Šค์˜ ๋ฉค๋ฒ„, ํšŒ์˜๋ก ๋ชฉ๋ก */
36+
router.get(
37+
'/:id',
38+
jwtAuthenticator,
39+
asyncWrapper(async (req: Request<GetInfoParams>, res: Response) => {
40+
const { id: workspaceId } = req.params;
41+
42+
const workspaceInfo = await workspaceService.info(Number(workspaceId));
43+
44+
res.send(workspaceInfo);
45+
}),
46+
);
47+
3348
export default router;

โ€Žserver/apis/workspace/service.test.tsโ€Ž

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
const workspaceModel = require('./model');
22
const workspaceService = require('./service');
33
const { default: InvalidJoinError } = require('@errors/invalid-join-error');
4+
const {
5+
default: InvalidWorkspaceError,
6+
} = require('@errors/invalid-workspace-error');
47

58
jest.mock('./model', () => {
69
return {
@@ -12,10 +15,15 @@ jest.mock('./model', () => {
1215

1316
jest.mock('@apis/user/model', () => {
1417
return {
18+
find: jest.fn(),
1519
updateOne: jest.fn(),
1620
};
1721
});
1822

23+
jest.mock('@apis/mom/model', () => {
24+
return { find: jest.fn() };
25+
});
26+
1927
const VALID_CODE = 'wab-0000-0000-0000';
2028

2129
jest.mock('uuid', () => {
@@ -91,4 +99,49 @@ describe('join', () => {
9199
});
92100
});
93101

102+
describe('info', () => {
103+
const WORKSPACE_ID = 1;
104+
const INVALID_WORKSPACE_ID = -1;
105+
106+
it('์›Œํฌ์ŠคํŽ˜์ด์Šค ID๊ฐ€ DB์— ์กด์žฌํ•  ๊ฒฝ์šฐ ์กฐํšŒ์— ์„ฑ๊ณตํ•œ๋‹ค.', async () => {
107+
const WORKSPACE_NAME = 'Wab';
108+
109+
workspaceModel.findOne.mockResolvedValueOnce({
110+
id: WORKSPACE_ID,
111+
name: WORKSPACE_NAME,
112+
code: VALID_CODE,
113+
users: [],
114+
moms: [],
115+
});
116+
117+
expect(workspaceService.info(WORKSPACE_ID)).resolves.toEqual({
118+
name: WORKSPACE_NAME,
119+
users: [],
120+
moms: [],
121+
});
122+
});
123+
124+
it('์›Œํฌ์ŠคํŽ˜์ด์Šค Id๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์‹คํŒจํ•œ๋‹ค.', async () => {
125+
expect(() => workspaceService.info()).rejects.toThrow(
126+
InvalidWorkspaceError,
127+
);
128+
});
129+
130+
it('์›Œํฌ์ŠคํŽ˜์ด์Šค Id๊ฐ€ DB์— ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์‹คํŒจํ•œ๋‹ค.', async () => {
131+
workspaceModel.findOne.mockResolvedValueOnce(null);
132+
133+
expect(() => workspaceService.info(INVALID_WORKSPACE_ID)).rejects.toThrow(
134+
InvalidWorkspaceError,
135+
);
136+
});
137+
138+
it('์›Œํฌ์ŠคํŽ˜์ด์Šค ์ •๋ณด ํš๋“ ์‹คํŒจ ์‹œ ์—๋Ÿฌ๋ฅผ ๋˜์ง„๋‹ค.', async () => {
139+
workspaceModel.findOne.mockRejectedValueOnce(
140+
new Error('Some error in database operation'),
141+
);
142+
143+
expect(() => workspaceService.info(WORKSPACE_ID)).rejects.toThrow();
144+
});
145+
});
146+
94147
export {};

โ€Žserver/apis/workspace/service.tsโ€Ž

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { v4 as uuidv4 } from 'uuid';
22
import workspaceModel from './model';
3-
import userModel from '@apis/user/model';
3+
import userModel, { User } from '@apis/user/model';
4+
import momModel from '@apis/mom/model';
45
import AuthorizationError from '@errors/authorization-error';
56
import InvalidJoinError from '@errors/invalid-join-error';
7+
import InvalidWorkspaceError from '@errors/invalid-workspace-error';
68

79
export const create = async (name: string) => {
810
if (!name) throw new Error('์›Œํฌ์ŠคํŽ˜์ด์Šค ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š” ^^');
@@ -30,3 +32,27 @@ export const join = async (userId: number, code: string) => {
3032

3133
return { id, name, code };
3234
};
35+
36+
export const info = async (workspaceId: number) => {
37+
if (!workspaceId) throw new InvalidWorkspaceError('์ž˜๋ชป๋œ ์ ‘๊ทผ์ด์—์š” ^^');
38+
39+
const workspace = await workspaceModel.findOne({ id: workspaceId });
40+
41+
if (!workspace)
42+
throw new InvalidWorkspaceError('์กด์žฌํ•˜์ง€ ์•Š๋Š” ์›Œํฌ์ŠคํŽ˜์ด์Šค์—์š” ^^');
43+
44+
const { name, users: userIds, moms: momsIds } = workspace;
45+
46+
const users: Pick<User, 'name' | 'avatarUrl'>[] =
47+
(await userModel.find(
48+
{
49+
id: { $in: userIds },
50+
},
51+
{ name: 1, avatarUrl: 1, _id: 0 },
52+
)) || [];
53+
54+
const moms: string[] =
55+
(await momModel.find({ id: { $in: momsIds } }, { name: 1 })) || [];
56+
57+
return { name, users, moms };
58+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import CustomError from '.';
2+
import { BAD_REQUEST } from '@constants/http-status';
3+
4+
class InvalidWorkspaceError extends CustomError {
5+
constructor(message = 'Unauthorized') {
6+
super(message, BAD_REQUEST);
7+
}
8+
}
9+
10+
export default InvalidWorkspaceError;

โ€Žtypes/params/workspace.tsโ€Ž

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ export interface PostParams {
55
export interface PostJoinParams {
66
code: string;
77
}
8+
9+
export interface GetInfoParams {
10+
id: string;
11+
}

0 commit comments

Comments
ย (0)