Skip to content

Commit

Permalink
[#9] Modify createPost API to receive a markdown file
Browse files Browse the repository at this point in the history
  • Loading branch information
3jins committed Feb 16, 2021
1 parent b61284b commit b5ee40b
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 33 deletions.
5 changes: 2 additions & 3 deletions backend/src/post/PostDto.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import Language from '@src/common/constant/Language';
import { File } from 'formidable';

export interface AddPostParamDto {
post: File;
categoryId?: string;
tagIdList?: Array<string>;
seriesId?: string;
title: string;
rawContent: string;
language: Language;
thumbnailContent: string;
thumbnailImageId?: string;
createdDate?: Date;
isPrivate?: boolean;
}

Expand Down
23 changes: 16 additions & 7 deletions backend/src/post/PostRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,29 @@ import Router from '@koa/router';
import koaBody from 'koa-body';
import { Context } from 'koa';
import Container from 'typedi';
import _ from 'lodash';
import { BlogErrorCode } from '@src/common/error/BlogErrorCode';
import * as URL from '../common/constant/URL';
import PostService from './PostService';
import { File } from 'formidable';
import Language from '@src/common/constant/Language';

const postRouter = new Router();
const koaBodyOptions = {
multipart: true,
};
const postService: PostService = Container.get(PostService);

postRouter.post(`${URL.PREFIX.API}${URL.ENDPOINT.POST}`, koaBody(), (ctx: Context) => {
try {
const requestBody = ctx.request.body;
postService.createPost(requestBody);
ctx.status = 200;
} catch (err) {
console.log(err);
postRouter.post(`${URL.PREFIX.API}${URL.ENDPOINT.POST}`, koaBody(koaBodyOptions), (ctx: Context) => {
if (_.isEmpty(ctx.request.files) || _.has(ctx.request.files!.post)) {
throw new Error(BlogErrorCode.FILE_NOT_UPLOADED.code);
}

postService.createPost({
post: ctx.request.files!.post,
...ctx.request.body,
});
ctx.status = 200;
});

export default postRouter;
14 changes: 12 additions & 2 deletions backend/src/post/PostService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Service } from 'typedi';
import fs from 'fs';
import { AddPostParamDto } from '@src/post/PostDto';
import PostRepository from '@src/post/PostRepository';

Expand All @@ -8,12 +9,21 @@ export default class PostService {
}

public createPost = (paramDto: AddPostParamDto): void => {
const { rawContent } = paramDto;
const { post } = paramDto;
const rawContent: string = this.readPostContent(post.path);
const renderedContent = this.renderContent(rawContent);
this.postRepository.createPost({ ...paramDto, renderedContent });
this.postRepository.createPost({
...paramDto,
title: post.name,
rawContent,
renderedContent,
});
};

private readPostContent = (path: string): string => fs.readFileSync(path).toString();

private renderContent = (rawContent: string): string => {
// TODO: 렌더링 로직 구현
return rawContent;
};
}
18 changes: 18 additions & 0 deletions backend/test/data/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
이것은 테스트를 위한 파일입니다.



## 코드

리코드는 코드다. 이는 마치 개구리가 구리인 것과 같다.

```java
import java.lang.*;

public class Main {
public static void main (String[] arguments) {
System.out.prinltln("곤니치와 세카이");
}
}
```

13 changes: 13 additions & 0 deletions backend/test/post/PostRepositoryTest.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _ from 'lodash';
import { ClientSession, Connection } from 'mongoose';
import { should } from 'chai';
import sinon from 'sinon';
Expand Down Expand Up @@ -54,5 +55,17 @@ describe('PostRepository test', () => {
const posts: PostDoc[] = await Post.find().session(session);
posts.should.have.lengthOf(1);
const post: PostDoc = posts[0];
post.should.not.be.empty;
post.should.contain(commonTestData.post1);
(post.lastVersionPost !== undefined).should.be.true;
(post.lastVersionPost === null).should.be.true;
(post.isLatestVersion !== undefined).should.be.true;
post.isLatestVersion!.should.be.true;
(post.isDeleted !== undefined).should.be.true;
post.isDeleted!.should.be.false;
(post.createdDate !== undefined).should.be.true;
post.createdDate!.getTime().should.closeTo(new Date().getTime(), 3000); // Expect difference to be less than 3 seconds
(post.commentCount !== undefined).should.be.true;
post.commentCount!.should.equal(0);
});
});
31 changes: 19 additions & 12 deletions backend/test/post/PostRouterTest.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import supertest from 'supertest';
import { should } from 'chai';
import { Server } from 'http';
import { mock } from 'ts-mockito';
import { anything, instance, mock, objectContaining, verify } from 'ts-mockito';
import PostService from '@src/post/PostService';
import { Container } from 'typedi';
import { endApp, startApp } from '../../src/app';
import { common as commonTestData } from '../data/testData';
import { appPath } from '../data/testData';
import * as URL from '../../src/common/constant/URL';
import Language from '@src/common/constant/Language';

Container.set(PostService, mock(PostService));
const postService: PostService = mock(PostService);
Container.set(PostService, instance(postService));
const PostRouter = require('@src/post/PostRouter');

describe('Image integration test', () => {
describe('Post router test', () => {
const FILE_NAME = 'test.md';

let server: Server;
let request: supertest.SuperTest<supertest.Test>;

Expand All @@ -22,18 +26,21 @@ describe('Image integration test', () => {
});

it(`${URL.PREFIX.API}${URL.ENDPOINT.POST}`, async () => {
const serviceParamDto = {
title: commonTestData.post1.title,
rawContent: commonTestData.post1.rawContent,
language: commonTestData.post1.language,
thumbnailContent: commonTestData.post1.thumbnailContent,
createdDate: new Date(),
const payload = {
seriesId: '1234',
language: Language.KO,
thumbnailContent: '뚜샤!',
};
await request
.post(`${URL.PREFIX.API}${URL.ENDPOINT.POST}`)
.send(serviceParamDto)
.set('Accept', 'application/json')
.field(payload)
.attach('post', `${appPath.testData}/${FILE_NAME}`, { contentType: 'application/octet-stream' })
.expect(200);

verify(postService.createPost(objectContaining({
post: anything(),
...payload,
}))).once();
});

after(() => endApp(server));
Expand Down
37 changes: 29 additions & 8 deletions backend/test/post/postServiceTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,41 @@ import { deepEqual, instance, mock, verify } from 'ts-mockito';
import PostService from '@src/post/PostService';
import PostRepository from '@src/post/PostRepository';
import { AddPostParamDto, CreatePostRepoParamDto } from '@src/post/PostDto';
import { common as commonTestData } from '@test/data/testData';
import { appPath, common as commonTestData } from '@test/data/testData';
import fs from 'fs';
import { File } from 'formidable';
import Language from '@src/common/constant/Language';

describe('PostService test', () => {
let postService: PostService;
let postRepository: PostRepository;
let serviceParamDto: AddPostParamDto;
let post: File;
let fileContent: string;

before(() => {
serviceParamDto = {
title: commonTestData.post1.title,
rawContent: commonTestData.post1.rawContent,
language: commonTestData.post1.language,
thumbnailContent: commonTestData.post1.thumbnailContent,
createdDate: new Date(),
const fileName = 'test.md';
const filePath = `${appPath.testData}/${fileName}`;
const fileStream: Buffer = fs.readFileSync(filePath);
fileContent = fileStream.toString();
const fileStat: fs.Stats = fs.statSync(filePath);
post = {
size: fileStream.byteLength,
path: filePath,
name: fileName,
type: 'application/octet-stream',
lastModifiedDate: fileStat.mtime,
toJSON(): Object {
return {};
},
};

serviceParamDto = {
post,
seriesId: '1234',
language: Language.KO,
thumbnailContent: '뚜샤!',
};
postRepository = mock(PostRepository);
postService = new PostService(instance(postRepository));
should();
Expand All @@ -28,7 +47,9 @@ describe('PostService test', () => {
postService.createPost(serviceParamDto);
const repoParamDto: CreatePostRepoParamDto = {
...serviceParamDto,
renderedContent: serviceParamDto.rawContent,
title: post.name,
rawContent: fileContent,
renderedContent: fileContent,
};
verify(postRepository.createPost(deepEqual(repoParamDto))).once();
});
Expand Down
2 changes: 1 addition & 1 deletion backend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"baseUrl": "./",
"paths": {
"@src/*": ["src/*"],
"@test/*": ["test/*"],
"@test/*": ["test/*"]
},
"esModuleInterop": true,
"emitDecoratorMetadata": true,
Expand Down

0 comments on commit b5ee40b

Please sign in to comment.