diff --git a/src/services/note/reaction/create.ts b/src/services/note/reaction/create.ts index b54f8a60bb..8fa0b52e7d 100644 --- a/src/services/note/reaction/create.ts +++ b/src/services/note/reaction/create.ts @@ -26,7 +26,7 @@ export default async (user: IUser, note: INote, reaction: string) => new Promise } catch (e) { // duplicate key error if (e.code === 11000) { - return res(null); + return rej('already reacted'); } console.error(e); diff --git a/test/api.ts b/test/api.ts index a978394129..1e51e6dff4 100644 --- a/test/api.ts +++ b/test/api.ts @@ -3,6 +3,7 @@ */ import * as http from 'http'; +import * as fs from 'fs'; import * as assert from 'chai'; assert.use(require('chai-http')); @@ -44,7 +45,7 @@ const request = async (endpoint: string, params: any, me?: any): Promise { +const signup = async (params?: any): Promise => { const q = Object.assign({ username: 'test', password: 'test' @@ -54,6 +55,32 @@ const signup = async (params?: any) => { return res.body; }; + +const post = async (user: any, params?: any): Promise => { + const q = Object.assign({ + text: 'test' + }, params); + + const res = await request('/notes/create', q, user); + + return res.body.createdNote; +}; + +const react = async (user: any, note: any, reaction: string): Promise => { + await request('/notes/reactions/create', { + noteId: note.id, + reaction: reaction + }, user); +}; + +const uploadFile = async (user: any): Promise => { + const res = await assert.request(server) + .post('/drive/files/create') + .field('i', user.token) + .attach('file', fs.readFileSync(__dirname + '/resources/Lenna.png'), 'Lenna.png'); + + return res.body; +}; //#endregion describe('API', () => { @@ -226,4 +253,319 @@ describe('API', () => { expect(res).have.status(400); })); }); + + describe('notes/create', () => { + it('投稿できる', async(async () => { + const me = await signup(); + const post = { + text: 'test' + }; + const res = await request('/notes/create', post, me); + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('createdNote'); + expect(res.body.createdNote).have.property('text').eql(post.text); + })); + + it('ファイルを添付できる', async(async () => { + const me = await signup(); + const file = await uploadFile(me); + const res = await request('/notes/create', { + fileIds: [file.id] + }, me); + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('createdNote'); + expect(res.body.createdNote).have.property('fileIds').eql([file.id]); + })); + + it('他人のファイルは無視', async(async () => { + const me = await signup({ username: 'alice' }); + const bob = await signup({ username: 'bob' }); + const file = await uploadFile(bob); + const res = await request('/notes/create', { + fileIds: [file.id] + }, me); + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('createdNote'); + expect(res.body.createdNote).have.property('fileIds').eql([]); + })); + + it('存在しないファイルは無視', async(async () => { + const me = await signup(); + const res = await request('/notes/create', { + fileIds: ['000000000000000000000000'] + }, me); + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('createdNote'); + expect(res.body.createdNote).have.property('fileIds').eql([]); + })); + + it('不正なファイルIDで怒られる', async(async () => { + const me = await signup(); + const res = await request('/notes/create', { + fileIds: ['kyoppie'] + }, me); + expect(res).have.status(400); + })); + + it('返信できる', async(async () => { + const bob = await signup({ username: 'bob' }); + const bobPost = await post(bob); + + const alice = await signup({ username: 'alice' }); + const alicePost = { + text: 'test', + replyId: bobPost.id + }; + + const res = await request('/notes/create', alicePost, alice); + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('createdNote'); + expect(res.body.createdNote).have.property('text').eql(alicePost.text); + expect(res.body.createdNote).have.property('replyId').eql(alicePost.replyId); + expect(res.body.createdNote).have.property('reply'); + expect(res.body.createdNote.reply).have.property('text').eql(alicePost.text); + })); + + it('renoteできる', async(async () => { + const bob = await signup({ username: 'bob' }); + const bobPost = await post(bob, { + text: 'test' + }); + + const alice = await signup({ username: 'alice' }); + const alicePost = { + renoteId: bobPost.id + }; + + const res = await request('/notes/create', alicePost, alice); + + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('createdNote'); + expect(res.body.createdNote).have.property('renoteId').eql(alicePost.renoteId); + expect(res.body.createdNote).have.property('renote'); + expect(res.body.createdNote.renote).have.property('text').eql(bobPost.text); + })); + + it('引用renoteできる', async(async () => { + const bob = await signup({ username: 'bob' }); + const bobPost = await post(bob, { + text: 'test' + }); + + const alice = await signup({ username: 'alice' }); + const alicePost = { + text: 'test', + renoteId: bobPost.id + }; + + const res = await request('/notes/create', alicePost, alice); + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('createdNote'); + expect(res.body.createdNote).have.property('text').eql(alicePost.text); + expect(res.body.createdNote).have.property('renoteId').eql(alicePost.renoteId); + expect(res.body.createdNote).have.property('renote'); + expect(res.body.createdNote.renote).have.property('text').eql(bobPost.text); + })); + + it('文字数ぎりぎりで怒られない', async(async () => { + const me = await signup(); + const post = { + text: '!'.repeat(1000) + }; + const res = await request('/notes/create', post, me); + expect(res).have.status(200); + })); + + it('文字数オーバーで怒られる', async(async () => { + const me = await signup(); + const post = { + text: '!'.repeat(1001) + }; + const res = await request('/notes/create', post, me); + expect(res).have.status(400); + })); + + it('存在しないリプライ先で怒られる', async(async () => { + const me = await signup(); + const post = { + text: 'test', + replyId: '000000000000000000000000' + }; + const res = await request('/notes/create', post, me); + expect(res).have.status(400); + })); + + it('存在しないrenote対象で怒られる', async(async () => { + const me = await signup(); + const post = { + renoteId: '000000000000000000000000' + }; + const res = await request('/notes/create', post, me); + expect(res).have.status(400); + })); + + it('不正なリプライ先IDで怒られる', async(async () => { + const me = await signup(); + const post = { + text: 'test', + replyId: 'foo' + }; + const res = await request('/notes/create', post, me); + expect(res).have.status(400); + })); + + it('不正なrenote対象IDで怒られる', async(async () => { + const me = await signup(); + const post = { + renoteId: 'foo' + }; + const res = await request('/notes/create', post, me); + expect(res).have.status(400); + })); + + it('投票を添付できる', async(async () => { + const me = await signup(); + const res = await request('/notes/create', { + text: 'test', + poll: { + choices: ['foo', 'bar'] + } + }, me); + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('createdNote'); + expect(res.body.createdNote).have.property('poll'); + })); + + it('投票の選択肢が無くて怒られる', async(async () => { + const me = await signup(); + const res = await request('/notes/create', { + poll: {} + }, me); + expect(res).have.status(400); + })); + + it('投票の選択肢が無くて怒られる (空の配列)', async(async () => { + const me = await signup(); + const res = await request('/notes/create', { + poll: { + choices: [] + } + }, me); + expect(res).have.status(400); + })); + + it('投票の選択肢が1つで怒られる', async(async () => { + const me = await signup(); + const res = await request('/notes/create', { + poll: { + choices: ['Strawberry Pasta'] + } + }, me); + expect(res).have.status(400); + })); + }); + + describe('notes/show', () => { + it('投稿が取得できる', async(async () => { + const me = await signup(); + const myPost = await post(me, { + text: 'test' + }); + const res = await request('/notes/show', { + noteId: myPost.id + }, me); + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('id').eql(myPost.id); + expect(res.body).have.property('text').eql(myPost.text); + })); + + it('投稿が存在しなかったら怒る', async(async () => { + const res = await request('/notes/show', { + noteId: '000000000000000000000000' + }); + expect(res).have.status(400); + })); + + it('間違ったIDで怒られる', async(async () => { + const res = await request('/notes/show', { + noteId: 'kyoppie' + }); + expect(res).have.status(400); + })); + }); + + describe('notes/reactions/create', () => { + it('リアクションできる', async(async () => { + const bob = await signup({ username: 'bob' }); + const bobPost = await post(bob); + + const alice = await signup({ username: 'alice' }); + const res = await request('/notes/reactions/create', { + noteId: bobPost.id, + reaction: 'like' + }, alice); + + expect(res).have.status(204); + })); + + it('自分の投稿にはリアクションできない', async(async () => { + const me = await signup(); + const myPost = await post(me); + + const res = await request('/notes/reactions/create', { + noteId: myPost.id, + reaction: 'like' + }, me); + + expect(res).have.status(400); + })); + + it('二重にリアクションできない', async(async () => { + const bob = await signup({ username: 'bob' }); + const bobPost = await post(bob); + + const alice = await signup({ username: 'alice' }); + await react(alice, bobPost, 'like'); + + const res = await request('/notes/reactions/create', { + noteId: bobPost.id, + reaction: 'like' + }, alice); + + expect(res).have.status(400); + })); + + it('存在しない投稿にはリアクションできない', async(async () => { + const me = await signup(); + const res = await request('/notes/reactions/create', { + noteId: '000000000000000000000000', + reaction: 'like' + }, me); + expect(res).have.status(400); + })); + + it('空のパラメータで怒られる', async(async () => { + const me = await signup(); + const res = await request('/notes/reactions/create', {}, me); + expect(res).have.status(400); + })); + + it('間違ったIDで怒られる', async(async () => { + const me = await signup(); + const res = await request('/notes/reactions/create', { + noteId: 'kyoppie', + reaction: 'like' + }, me); + expect(res).have.status(400); + })); + }); });