From 931f17c58932d4a9b11fdad5d338e3c91fa749a3 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 23 Jan 2019 12:15:27 +0900
Subject: [PATCH] Refactor: Separate some test files

---
 test/api.ts       | 120 +++-------------------------------------------
 test/streaming.ts |  77 +++++++++++++++++++++++++++++
 test/utils.ts     |  82 +++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+), 113 deletions(-)
 create mode 100644 test/streaming.ts
 create mode 100644 test/utils.ts

diff --git a/test/api.ts b/test/api.ts
index d87380a1d7..fe41c751d9 100644
--- a/test/api.ts
+++ b/test/api.ts
@@ -11,7 +11,7 @@
 import * as http from 'http';
 import * as fs from 'fs';
 import * as assert from 'chai';
-import * as WebSocket from 'ws';
+import { async, _signup, _request, _uploadFile, _post, _react, resetDb } from './utils';
 
 assert.use(require('chai-http'));
 const expect = assert.expect;
@@ -33,87 +33,16 @@ const db = require('../built/db/mongodb').default;
 const server = http.createServer(app.callback());
 
 //#region Utilities
-const async = (fn: Function) => (done: Function) => {
-	fn().then(() => {
-		done();
-	}, (err: Error) => {
-		done(err);
-	});
-};
-
-const request = async (endpoint: string, params: any, me?: any): Promise<ChaiHttp.Response> => {
-	const auth = me ? {
-		i: me.token
-	} : {};
-
-	const res = await assert.request(server)
-		.post(endpoint)
-		.send(Object.assign(auth, params));
-
-	return res;
-};
-
-const signup = async (params?: any): Promise<any> => {
-	const q = Object.assign({
-		username: 'test',
-		password: 'test'
-	}, params);
-
-	const res = await request('/signup', q);
-
-	return res.body;
-};
-
-const post = async (user: any, params?: any): Promise<any> => {
-	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<any> => {
-	await request('/notes/reactions/create', {
-		noteId: note.id,
-		reaction: reaction
-	}, user);
-};
-
-const uploadFile = async (user: any): Promise<any> => {
-	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;
-};
+const request = _request(server);
+const signup = _signup(request);
+const post = _post(request);
+const react = _react(request);
+const uploadFile = _uploadFile(server);
 //#endregion
 
 describe('API', () => {
 	// Reset database each test
-	beforeEach(() => new Promise((res) => {
-		// APIがなにかレスポンスを返した後に、後処理を行う場合があり、
-		// レスポンスを受け取ってすぐデータベースをリセットすると
-		// その後処理と競合し(テスト自体は合格するものの)エラーがコンソールに出力され
-		// 見た目的に気持ち悪くなるので、後処理が終るのを待つために500msくらい待ってから
-		// データベースをリセットするようにする
-		setTimeout(async () => {
-			await Promise.all([
-				db.get('users').drop(),
-				db.get('notes').drop(),
-				db.get('driveFiles.files').drop(),
-				db.get('driveFiles.chunks').drop(),
-				db.get('driveFolders').drop(),
-				db.get('apps').drop(),
-				db.get('accessTokens').drop(),
-				db.get('authSessions').drop()
-			]);
-
-			res();
-		}, 500);
-	}));
+	beforeEach(resetDb(db));
 
 	describe('signup', () => {
 		it('不正なユーザー名でアカウントが作成できない', async(async () => {
@@ -1239,39 +1168,4 @@ describe('API', () => {
 			expect(res).have.status(400);
 		}));
 	});
-
-	describe('streaming', () => {
-		it('投稿がタイムラインに流れる', done => {
-			const post = {
-				text: 'foo'
-			};
-
-			signup().then(me => {
-				const ws = new WebSocket(`ws://localhost/streaming?i=${me.token}`);
-
-				ws.on('open', () => {
-					ws.on('message', data => {
-						const msg = JSON.parse(data.toString());
-						if (msg.type == 'channel' && msg.body.id == 'a') {
-							if (msg.body.type == 'note') {
-								expect(msg.body.body.text).eql(post.text);
-								done();
-							}
-						} else if (msg.type == 'connected' && msg.body.id == 'a') {
-							request('/notes/create', post, me);
-						}
-					});
-
-					ws.send(JSON.stringify({
-						type: 'connect',
-						body: {
-							channel: 'homeTimeline',
-							id: 'a',
-							pong: true
-						}
-					}));
-				});
-			});
-		});
-	});
 });
diff --git a/test/streaming.ts b/test/streaming.ts
new file mode 100644
index 0000000000..a3022173b9
--- /dev/null
+++ b/test/streaming.ts
@@ -0,0 +1,77 @@
+/*
+ * Tests of streaming API
+ *
+ * How to run the tests:
+ * > mocha test/streaming.ts --require ts-node/register
+ *
+ * To specify test:
+ * > mocha test/streaming.ts --require ts-node/register -g 'test name'
+ */
+
+import * as http from 'http';
+import * as WebSocket from 'ws';
+import * as assert from 'chai';
+import { _signup, _request, _uploadFile, _post, _react, resetDb } from './utils';
+
+assert.use(require('chai-http'));
+const expect = assert.expect;
+
+//#region process
+Error.stackTraceLimit = Infinity;
+
+// During the test the env variable is set to test
+process.env.NODE_ENV = 'test';
+
+// Display detail of unhandled promise rejection
+process.on('unhandledRejection', console.dir);
+//#endregion
+
+const app = require('../built/server/api').default;
+require('../built/server').default();
+const db = require('../built/db/mongodb').default;
+
+const server = http.createServer(app.callback());
+
+//#region Utilities
+const request = _request(server);
+const signup = _signup(request);
+//#endregion
+
+describe('Streaming', () => {
+	// Reset database each test
+	beforeEach(resetDb(db));
+
+	it('投稿がタイムラインに流れる', done => {
+		const post = {
+			text: 'foo'
+		};
+
+		signup().then(me => {
+			const ws = new WebSocket(`ws://localhost/streaming?i=${me.token}`);
+
+			ws.on('open', () => {
+				ws.on('message', data => {
+					const msg = JSON.parse(data.toString());
+					if (msg.type == 'channel' && msg.body.id == 'a') {
+						if (msg.body.type == 'note') {
+							expect(msg.body.body.text).eql(post.text);
+							ws.close();
+							done();
+						}
+					} else if (msg.type == 'connected' && msg.body.id == 'a') {
+						request('/notes/create', post, me);
+					}
+				});
+
+				ws.send(JSON.stringify({
+					type: 'connect',
+					body: {
+						channel: 'homeTimeline',
+						id: 'a',
+						pong: true
+					}
+				}));
+			});
+		});
+	});
+});
diff --git a/test/utils.ts b/test/utils.ts
new file mode 100644
index 0000000000..06fc1e4051
--- /dev/null
+++ b/test/utils.ts
@@ -0,0 +1,82 @@
+import * as fs from 'fs';
+import * as http from 'http';
+import * as assert from 'chai';
+
+export const async = (fn: Function) => (done: Function) => {
+	fn().then(() => {
+		done();
+	}, (err: Error) => {
+		done(err);
+	});
+};
+
+export const _request = (server: http.Server) => async (endpoint: string, params: any, me?: any): Promise<ChaiHttp.Response> => {
+	const auth = me ? {
+		i: me.token
+	} : {};
+
+	const res = await assert.request(server)
+		.post(endpoint)
+		.send(Object.assign(auth, params));
+
+	return res;
+};
+
+export const _signup = (request: ReturnType<typeof _request>) => async (params?: any): Promise<any> => {
+	const q = Object.assign({
+		username: 'test',
+		password: 'test'
+	}, params);
+
+	const res = await request('/signup', q);
+
+	return res.body;
+};
+
+export const _post = (request: ReturnType<typeof _request>) => async (user: any, params?: any): Promise<any> => {
+	const q = Object.assign({
+		text: 'test'
+	}, params);
+
+	const res = await request('/notes/create', q, user);
+
+	return res.body.createdNote;
+};
+
+export const _react = (request: ReturnType<typeof _request>) => async (user: any, note: any, reaction: string): Promise<any> => {
+	await request('/notes/reactions/create', {
+		noteId: note.id,
+		reaction: reaction
+	}, user);
+};
+
+export const _uploadFile = (server: http.Server) => async (user: any): Promise<any> => {
+	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;
+};
+
+export const resetDb = (db: any) => () => new Promise(res => {
+	// APIがなにかレスポンスを返した後に、後処理を行う場合があり、
+	// レスポンスを受け取ってすぐデータベースをリセットすると
+	// その後処理と競合し(テスト自体は合格するものの)エラーがコンソールに出力され
+	// 見た目的に気持ち悪くなるので、後処理が終るのを待つために500msくらい待ってから
+	// データベースをリセットするようにする
+	setTimeout(async () => {
+		await Promise.all([
+			db.get('users').drop(),
+			db.get('notes').drop(),
+			db.get('driveFiles.files').drop(),
+			db.get('driveFiles.chunks').drop(),
+			db.get('driveFolders').drop(),
+			db.get('apps').drop(),
+			db.get('accessTokens').drop(),
+			db.get('authSessions').drop()
+		]);
+
+		res();
+	}, 500);
+});