From 3c1fd385faeea53be487e2e0156b90191b3702e6 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 16 Sep 2015 08:12:47 -0500 Subject: [PATCH 01/53] Rename existing api tests to api-legacy --- tasks/gulp-tests.js | 22 +++++++++---------- test/{api => api-legacy}/README.md | 0 test/{api => api-legacy}/anonymized.coffee | 0 test/{api => api-legacy}/api-helper.coffee | 0 test/{api => api-legacy}/challenges.coffee | 0 test/{api => api-legacy}/chat.coffee | 0 test/{api => api-legacy}/coupons.coffee | 0 test/{api => api-legacy}/get_user.coffee | 0 test/{api => api-legacy}/groups.coffee | 0 .../{api => api-legacy}/inAppPurchases.coffee | 0 test/{api => api-legacy}/party.coffee | 0 .../pushNotifications.coffee | 0 test/{api => api-legacy}/score.coffee | 0 test/{api => api-legacy}/status.coffee | 0 test/{api => api-legacy}/subscriptions.coffee | 0 test/{api => api-legacy}/todos.coffee | 0 test/{api => api-legacy}/users.coffee | 0 test/mocha.opts | 2 +- 18 files changed, 12 insertions(+), 12 deletions(-) rename test/{api => api-legacy}/README.md (100%) rename test/{api => api-legacy}/anonymized.coffee (100%) rename test/{api => api-legacy}/api-helper.coffee (100%) rename test/{api => api-legacy}/challenges.coffee (100%) rename test/{api => api-legacy}/chat.coffee (100%) rename test/{api => api-legacy}/coupons.coffee (100%) rename test/{api => api-legacy}/get_user.coffee (100%) rename test/{api => api-legacy}/groups.coffee (100%) rename test/{api => api-legacy}/inAppPurchases.coffee (100%) rename test/{api => api-legacy}/party.coffee (100%) rename test/{api => api-legacy}/pushNotifications.coffee (100%) rename test/{api => api-legacy}/score.coffee (100%) rename test/{api => api-legacy}/status.coffee (100%) rename test/{api => api-legacy}/subscriptions.coffee (100%) rename test/{api => api-legacy}/todos.coffee (100%) rename test/{api => api-legacy}/users.coffee (100%) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index e3b469a9a2..580372adc7 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -104,9 +104,9 @@ gulp.task('test:server_side:safe', ['test:prepare:build'], (cb) => { pipe(runner); }); -gulp.task('test:api', ['test:prepare:mongo'], (cb) => { +gulp.task('test:api-legacy', ['test:prepare:mongo'], (cb) => { let runner = exec( - testBin("istanbul cover -i 'website/src/**' --dir coverage/api ./node_modules/.bin/_mocha -- test/api"), + testBin("istanbul cover -i 'website/src/**' --dir coverage/api-legacy ./node_modules/.bin/_mocha -- test/api-legacy"), (err, stdout, stderr) => { cb(err); } @@ -114,12 +114,12 @@ gulp.task('test:api', ['test:prepare:mongo'], (cb) => { pipe(runner); }); -gulp.task('test:api:safe', ['test:prepare:mongo'], (cb) => { +gulp.task('test:api-legacy:safe', ['test:prepare:mongo'], (cb) => { let runner = exec( - testBin("istanbul cover -i 'website/src/**' --dir coverage/api ./node_modules/.bin/_mocha -- test/api"), + testBin("istanbul cover -i 'website/src/**' --dir coverage/api-legacy ./node_modules/.bin/_mocha -- test/api-legacy"), (err, stdout, stderr) => { testResults.push({ - suite: 'API Specs\t', + suite: 'API (legacy) Specs', pass: testCount(stdout, /(\d+) passing/), fail: testCount(stderr, /(\d+) failing/), pend: testCount(stdout, /(\d+) pending/) @@ -130,15 +130,15 @@ gulp.task('test:api:safe', ['test:prepare:mongo'], (cb) => { pipe(runner); }); -gulp.task('test:api:clean', (cb) => { - pipe(exec(testBin("mocha test/api"), () => cb())); +gulp.task('test:api-legacy:clean', (cb) => { + pipe(exec(testBin("mocha test/api-legacy"), () => cb())); }); -gulp.task('test:api:watch', [ +gulp.task('test:api-legacy:watch', [ 'test:prepare:mongo', - 'test:api:clean' + 'test:api-legacy:clean' ], () => { - gulp.watch(['website/src/**', 'test/api/**'], ['test:api:clean']); + gulp.watch(['website/src/**', 'test/api-legacy/**'], ['test:api-legacy:clean']); }); gulp.task('test:karma', ['test:prepare:build'], (cb) => { @@ -238,7 +238,7 @@ gulp.task('test', [ 'test:common:safe', 'test:server_side:safe', 'test:karma:safe', - 'test:api:safe', + 'test:api-legacy:safe', 'test:e2e:safe' ], () => { let totals = [0,0,0]; diff --git a/test/api/README.md b/test/api-legacy/README.md similarity index 100% rename from test/api/README.md rename to test/api-legacy/README.md diff --git a/test/api/anonymized.coffee b/test/api-legacy/anonymized.coffee similarity index 100% rename from test/api/anonymized.coffee rename to test/api-legacy/anonymized.coffee diff --git a/test/api/api-helper.coffee b/test/api-legacy/api-helper.coffee similarity index 100% rename from test/api/api-helper.coffee rename to test/api-legacy/api-helper.coffee diff --git a/test/api/challenges.coffee b/test/api-legacy/challenges.coffee similarity index 100% rename from test/api/challenges.coffee rename to test/api-legacy/challenges.coffee diff --git a/test/api/chat.coffee b/test/api-legacy/chat.coffee similarity index 100% rename from test/api/chat.coffee rename to test/api-legacy/chat.coffee diff --git a/test/api/coupons.coffee b/test/api-legacy/coupons.coffee similarity index 100% rename from test/api/coupons.coffee rename to test/api-legacy/coupons.coffee diff --git a/test/api/get_user.coffee b/test/api-legacy/get_user.coffee similarity index 100% rename from test/api/get_user.coffee rename to test/api-legacy/get_user.coffee diff --git a/test/api/groups.coffee b/test/api-legacy/groups.coffee similarity index 100% rename from test/api/groups.coffee rename to test/api-legacy/groups.coffee diff --git a/test/api/inAppPurchases.coffee b/test/api-legacy/inAppPurchases.coffee similarity index 100% rename from test/api/inAppPurchases.coffee rename to test/api-legacy/inAppPurchases.coffee diff --git a/test/api/party.coffee b/test/api-legacy/party.coffee similarity index 100% rename from test/api/party.coffee rename to test/api-legacy/party.coffee diff --git a/test/api/pushNotifications.coffee b/test/api-legacy/pushNotifications.coffee similarity index 100% rename from test/api/pushNotifications.coffee rename to test/api-legacy/pushNotifications.coffee diff --git a/test/api/score.coffee b/test/api-legacy/score.coffee similarity index 100% rename from test/api/score.coffee rename to test/api-legacy/score.coffee diff --git a/test/api/status.coffee b/test/api-legacy/status.coffee similarity index 100% rename from test/api/status.coffee rename to test/api-legacy/status.coffee diff --git a/test/api/subscriptions.coffee b/test/api-legacy/subscriptions.coffee similarity index 100% rename from test/api/subscriptions.coffee rename to test/api-legacy/subscriptions.coffee diff --git a/test/api/todos.coffee b/test/api-legacy/todos.coffee similarity index 100% rename from test/api/todos.coffee rename to test/api-legacy/todos.coffee diff --git a/test/api/users.coffee b/test/api-legacy/users.coffee similarity index 100% rename from test/api/users.coffee rename to test/api-legacy/users.coffee diff --git a/test/mocha.opts b/test/mocha.opts index 3f0bf9cd67..3ebc76edfc 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -6,4 +6,4 @@ --debug --compilers coffee:coffee-script --globals io ---require test/api/api-helper +--require test/api-legacy/api-helper From e5b19344f6868ed1623a6c51d7b9908bb7ebecb5 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 16 Sep 2015 08:18:50 -0500 Subject: [PATCH 02/53] Use $(npm bin) in gulp test --- tasks/gulp-tests.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index 580372adc7..e6c9e6e9bc 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -19,7 +19,7 @@ let testCount = (stdout, regexp) => { } let testBin = (string) => { - return `NODE_ENV=testing ./node_modules/.bin/${string}`; + return `NODE_ENV=testing $(npm bin)/${string}`; }; gulp.task('test:prepare:mongo', (cb) => { @@ -106,7 +106,7 @@ gulp.task('test:server_side:safe', ['test:prepare:build'], (cb) => { gulp.task('test:api-legacy', ['test:prepare:mongo'], (cb) => { let runner = exec( - testBin("istanbul cover -i 'website/src/**' --dir coverage/api-legacy ./node_modules/.bin/_mocha -- test/api-legacy"), + testBin("istanbul cover -i 'website/src/**' --dir coverage/api-legacy $(npm bin)/mocha -- test/api-legacy"), (err, stdout, stderr) => { cb(err); } @@ -116,7 +116,7 @@ gulp.task('test:api-legacy', ['test:prepare:mongo'], (cb) => { gulp.task('test:api-legacy:safe', ['test:prepare:mongo'], (cb) => { let runner = exec( - testBin("istanbul cover -i 'website/src/**' --dir coverage/api-legacy ./node_modules/.bin/_mocha -- test/api-legacy"), + testBin("istanbul cover -i 'website/src/**' --dir coverage/api-legacy $(npm bin)/mocha -- test/api-legacy"), (err, stdout, stderr) => { testResults.push({ suite: 'API (legacy) Specs', From 115af819a07de12e6ebd1cc86774b4a09caed770 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 16 Oct 2015 15:00:33 -0500 Subject: [PATCH 03/53] Create task to set up a test server --- tasks/gulp-tests.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index 6861b3a399..ef1bfcbd17 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -279,6 +279,15 @@ gulp.task('test:e2e:safe', ['test:prepare'], (cb) => { }); }); +gulp.task('test:startServer', (done) => { + process.env.NODE_DB_URI = TEST_DB_URI; + process.env.DISABLE_REQUEST_LOGGING = true; + process.env.PORT = TEST_SERVER_PORT; + + let server = require('../website/src/server.js'); + server.listen(TEST_SERVER_PORT, done); +}); + gulp.task('test', [ 'test:common:safe', 'test:content:safe', From b26c8c3e74d15cddee64b15a09f25df1241043fc Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 16 Oct 2015 21:43:43 -0500 Subject: [PATCH 04/53] Add api test task --- tasks/gulp-tests.js | 47 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index ef1bfcbd17..50e70a4ecd 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -4,21 +4,24 @@ import mongoose from 'mongoose'; import { exec } from 'child_process'; import psTree from 'ps-tree'; import gulp from 'gulp'; +import {sync as glob} from 'glob'; import Q from 'q'; +import Mocha from 'mocha'; const TEST_SERVER_PORT = 3001 const TEST_DB = 'habitrpg_test' const TEST_DB_URI = `mongodb://localhost/${TEST_DB}` -const API_TEST_COMMAND = 'mocha test/api-legacy'; +const API_TEST_COMMAND = 'mocha test/api'; +const LEGACY_API_TEST_COMMAND = 'mocha test/api-legacy'; const COMMON_TEST_COMMAND = 'mocha test/common'; const CONTENT_TEST_COMMAND = 'mocha test/content --opts test/content/mocha.content.opts'; const CONTENT_OPTIONS = {maxBuffer: 1024 * 500}; const KARMA_TEST_COMMAND = 'karma start'; const SERVER_SIDE_TEST_COMMAND = 'mocha test/server_side'; -const ISTANBUL_TEST_COMMAND = `istanbul cover -i "website/src/**" --dir coverage/api $(npm bin)/${API_TEST_COMMAND}`; +const ISTANBUL_TEST_COMMAND = `istanbul cover -i "website/src/**" --dir coverage/api $(npm bin)/${LEGACY_API_TEST_COMMAND}`; /* Helper methods for reporting test summary */ let testResults = []; @@ -176,7 +179,7 @@ gulp.task('test:api-legacy:safe', ['test:prepare:mongo'], (cb) => { }); gulp.task('test:api-legacy:clean', (cb) => { - pipe(exec(testBin(API_TEST_COMMAND), () => cb())); + pipe(exec(testBin(LEGACY_API_TEST_COMMAND), () => cb())); }); gulp.task('test:api-legacy:watch', [ @@ -279,10 +282,40 @@ gulp.task('test:e2e:safe', ['test:prepare'], (cb) => { }); }); +gulp.task('test:api', ['test:startServer', 'test:prepare:mongo'], (done) => { + let mocha = new Mocha(); + let tests = glob('./test/api/**/*.js'); + + tests.forEach((test) => { + delete require.cache[resolve(test)]; + mocha.addFile(test); + }); + + mocha.run((numberOfFailures) => { + done(); + }); +}); + +gulp.task('test:api:safe', ['test:startServer', 'test:prepare:mongo'], (done) => { + let runner = exec( + testBin(API_TEST_COMMAND), + (err, stdout, stderr) => { + testResults.push({ + suite: 'API Specs', + pass: testCount(stdout, /(\d+) passing/), + fail: testCount(stderr, /(\d+) failing/), + pend: testCount(stdout, /(\d+) pending/) + }); + done(); + } + ); + pipe(runner); +}); + gulp.task('test:startServer', (done) => { - process.env.NODE_DB_URI = TEST_DB_URI; + process.env.NODE_DB_URI = `mongodb://localhost/${TEST_DB}-api`; process.env.DISABLE_REQUEST_LOGGING = true; - process.env.PORT = TEST_SERVER_PORT; + process.env.PORT = 3002; let server = require('../website/src/server.js'); server.listen(TEST_SERVER_PORT, done); @@ -293,7 +326,8 @@ gulp.task('test', [ 'test:content:safe', 'test:server_side:safe', 'test:karma:safe', - 'test:api-legacy:safe', + // 'test:api-legacy:safe', + 'test:api:safe', 'test:e2e:safe' ], () => { let totals = [0,0,0]; @@ -321,5 +355,6 @@ gulp.task('test', [ if (totals[1] > 0) throw "ERROR: There are failing tests!" else { console.log('\n\x1b[36mThanks for helping keep Habitica clean!\x1b[0m'); + process.exit(); } }); From a61632fa92da7a7a611b0781ba4e685336e20886 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 16 Oct 2015 21:56:46 -0500 Subject: [PATCH 05/53] Set up api tests --- tasks/gulp-tests.js | 9 +++++---- test/api/mocha.api.opts | 7 +++++++ test/helpers/api.helper.js | 1 + test/mocha.opts | 2 -- 4 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 test/api/mocha.api.opts create mode 100644 test/helpers/api.helper.js diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index 50e70a4ecd..0ef0e2a9cf 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -4,18 +4,19 @@ import mongoose from 'mongoose'; import { exec } from 'child_process'; import psTree from 'ps-tree'; import gulp from 'gulp'; -import {sync as glob} from 'glob'; +import { sync as glob } from 'glob'; import Q from 'q'; import Mocha from 'mocha'; +import { resolve } from 'path'; const TEST_SERVER_PORT = 3001 const TEST_DB = 'habitrpg_test' const TEST_DB_URI = `mongodb://localhost/${TEST_DB}` -const API_TEST_COMMAND = 'mocha test/api'; +const API_TEST_COMMAND = 'mocha test/api --opts test/content/mocha.api.opts'; const LEGACY_API_TEST_COMMAND = 'mocha test/api-legacy'; -const COMMON_TEST_COMMAND = 'mocha test/common'; +const COMMON_TEST_COMMAND = 'mocha test/common --compilers coffee:coffee-script'; const CONTENT_TEST_COMMAND = 'mocha test/content --opts test/content/mocha.content.opts'; const CONTENT_OPTIONS = {maxBuffer: 1024 * 500}; const KARMA_TEST_COMMAND = 'karma start'; @@ -315,7 +316,7 @@ gulp.task('test:api:safe', ['test:startServer', 'test:prepare:mongo'], (done) => gulp.task('test:startServer', (done) => { process.env.NODE_DB_URI = `mongodb://localhost/${TEST_DB}-api`; process.env.DISABLE_REQUEST_LOGGING = true; - process.env.PORT = 3002; + process.env.PORT = 3003; let server = require('../website/src/server.js'); server.listen(TEST_SERVER_PORT, done); diff --git a/test/api/mocha.api.opts b/test/api/mocha.api.opts new file mode 100644 index 0000000000..57f495b3be --- /dev/null +++ b/test/api/mocha.api.opts @@ -0,0 +1,7 @@ +--colors +--reporter spec +--timeout 8000 +--check-leaks +--growl +--compilers js:babel/register +--require ./test/helpers/api.helper.js diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js new file mode 100644 index 0000000000..bf1e0b34ff --- /dev/null +++ b/test/helpers/api.helper.js @@ -0,0 +1 @@ +require('./globals.helper'); diff --git a/test/mocha.opts b/test/mocha.opts index 3ebc76edfc..9515b9d65a 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -4,6 +4,4 @@ --check-leaks --growl --debug ---compilers coffee:coffee-script --globals io ---require test/api-legacy/api-helper From aa9be8cb1a5cab33b0f8e63316e959829ab55eba Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 11:46:57 -0500 Subject: [PATCH 06/53] Update superagent --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5893a7d523..eeffbe408e 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "request": "~2.44.0", "s3-upload-stream": "^1.0.6", "stripe": "*", - "superagent": "~0.15.7", + "superagent": "~1.4.0", "swagger-node-express": "lefnire/swagger-node-express#habitrpg", "universal-analytics": "~0.3.2", "validator": "~3.19.0", From 56baf59195aa63e06738a8f1806208e571930a2f Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 11:55:05 -0500 Subject: [PATCH 07/53] Add global module to mocha requires --- test/mocha.opts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/mocha.opts b/test/mocha.opts index 9515b9d65a..f79948733b 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -5,3 +5,4 @@ --growl --debug --globals io +--require test/helpers/globals.helper From 9a14368170cce2e20db435c81393f7ce1dda4a0d Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 12:22:04 -0500 Subject: [PATCH 08/53] Correct test commands --- tasks/gulp-tests.js | 4 ++-- test/api/mocha.api.opts | 7 ------- test/content/mocha.content.opts | 7 ------- 3 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 test/api/mocha.api.opts delete mode 100644 test/content/mocha.content.opts diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index 0ef0e2a9cf..a929214718 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -14,10 +14,10 @@ const TEST_DB = 'habitrpg_test' const TEST_DB_URI = `mongodb://localhost/${TEST_DB}` -const API_TEST_COMMAND = 'mocha test/api --opts test/content/mocha.api.opts'; +const API_TEST_COMMAND = 'mocha test/api --compilers js:babel/register'; const LEGACY_API_TEST_COMMAND = 'mocha test/api-legacy'; const COMMON_TEST_COMMAND = 'mocha test/common --compilers coffee:coffee-script'; -const CONTENT_TEST_COMMAND = 'mocha test/content --opts test/content/mocha.content.opts'; +const CONTENT_TEST_COMMAND = 'mocha test/content --compilers js:babel/register'; const CONTENT_OPTIONS = {maxBuffer: 1024 * 500}; const KARMA_TEST_COMMAND = 'karma start'; const SERVER_SIDE_TEST_COMMAND = 'mocha test/server_side'; diff --git a/test/api/mocha.api.opts b/test/api/mocha.api.opts deleted file mode 100644 index 57f495b3be..0000000000 --- a/test/api/mocha.api.opts +++ /dev/null @@ -1,7 +0,0 @@ ---colors ---reporter spec ---timeout 8000 ---check-leaks ---growl ---compilers js:babel/register ---require ./test/helpers/api.helper.js diff --git a/test/content/mocha.content.opts b/test/content/mocha.content.opts deleted file mode 100644 index 610fc454d3..0000000000 --- a/test/content/mocha.content.opts +++ /dev/null @@ -1,7 +0,0 @@ ---colors ---reporter spec ---timeout 8000 ---check-leaks ---growl ---compilers js:babel/register ---require ./test/helpers/content.helper.js From 59e2b92daee56f5c7a0eddcbe59122683d8ed8e8 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 12:23:04 -0500 Subject: [PATCH 09/53] Kill mocha test if not set to watch --- tasks/gulp-tests.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index a929214718..b729afea6d 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -293,6 +293,9 @@ gulp.task('test:api', ['test:startServer', 'test:prepare:mongo'], (done) => { }); mocha.run((numberOfFailures) => { + if (!process.env.RUN_INTEGRATION_TEST_FOREVER) { + process.exit(numberOfFailures); + } done(); }); }); From 02e9775ba74537d940fea4c824096bb1798574bc Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 12:37:17 -0500 Subject: [PATCH 10/53] Set up new api test structure --- tasks/gulp-tests.js | 3 ++- test/api/get-status.js | 21 ++++++++++++++++++++ test/helpers/api.helper.js | 40 +++++++++++++++++++++++++++++++++++++- test/mocha.opts | 2 +- 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 test/api/get-status.js diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index b729afea6d..c8b9ed7912 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -284,7 +284,8 @@ gulp.task('test:e2e:safe', ['test:prepare'], (cb) => { }); gulp.task('test:api', ['test:startServer', 'test:prepare:mongo'], (done) => { - let mocha = new Mocha(); + require('../test/helpers/globals.helper'); + let mocha = new Mocha({reporter: 'spec'}); let tests = glob('./test/api/**/*.js'); tests.forEach((test) => { diff --git a/test/api/get-status.js b/test/api/get-status.js new file mode 100644 index 0000000000..f67399ece4 --- /dev/null +++ b/test/api/get-status.js @@ -0,0 +1,21 @@ +import {requester} from '../helpers/api.helper'; + +describe('Status', () => { + let api; + + beforeEach(() => { + api = requester(); + }); + + it('returns a status of up when server is up', (done) => { + api.get('/status') + .then((res) => { + expect(res.code).to.eql(200); + expect(res.body.status).to.eql('up'); + done(); + }) + .catch((err) => { + done(err); + }); + }); +}); diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index bf1e0b34ff..becc2f6274 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -1 +1,39 @@ -require('./globals.helper'); +import superagent from 'superagent'; + +export function requester(user={}) { + return { + get: _requestMaker(user, 'get'), + post: _requestMaker(user, 'post'), + put: _requestMaker(user, 'put'), + del: _requestMaker(user, 'del'), + } +} + +function _requestMaker(user, method) { + return (route, options={}) => { + return new Promise((resolve, reject) => { + let request = superagent[method](`http://localhost:3003/api/v2${route}`) + .accept('application/json'); + + if (user._id && user.apiToken) { + request + .set('x-api-user', user._id) + .set('x-api-key', user.apiToken); + } + + request + .query(options.query) + .send(options.send) + .end((err, response) => { + if (err) { return reject(err); } + + let res = { + code: response.statusCode, + body: response.body, + } + + resolve(res); + }); + }); + } +} diff --git a/test/mocha.opts b/test/mocha.opts index f79948733b..03db728cec 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -5,4 +5,4 @@ --growl --debug --globals io ---require test/helpers/globals.helper +--require ./test/helpers/globals.helper From 4a69dcbdf150b08bfac52a8df5c0abcd8bd8a8dd Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 12:40:00 -0500 Subject: [PATCH 11/53] Remove status test from legacy infrastructure --- test/api-legacy/status.coffee | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 test/api-legacy/status.coffee diff --git a/test/api-legacy/status.coffee b/test/api-legacy/status.coffee deleted file mode 100644 index b70dca0ea5..0000000000 --- a/test/api-legacy/status.coffee +++ /dev/null @@ -1,13 +0,0 @@ -'use strict' - -app = require("../../website/src/server") - -describe "Site Status", -> - - describe "GET /status", -> - - it "/api/v2/status", (done) -> - request.get(baseURL + "/status").set("Accept", "application/json").end (res) -> - expect(res.statusCode).to.equal 200 - expect(res.body.status).to.equal "up" - done() From ddf2ceeccda4786ed7806c8e7d724b08247f2093 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 15:05:32 -0500 Subject: [PATCH 12/53] Change name of test --- test/api/{get-status.js => status-get.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/api/{get-status.js => status-get.js} (100%) diff --git a/test/api/get-status.js b/test/api/status-get.js similarity index 100% rename from test/api/get-status.js rename to test/api/status-get.js From 0444a7d713c73c56bf9ebb9847ba00394335ed64 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 15:49:57 -0500 Subject: [PATCH 13/53] Move status test to own folder --- test/api/{ => status}/status-get.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test/api/{ => status}/status-get.js (87%) diff --git a/test/api/status-get.js b/test/api/status/status-get.js similarity index 87% rename from test/api/status-get.js rename to test/api/status/status-get.js index f67399ece4..9b9762c250 100644 --- a/test/api/status-get.js +++ b/test/api/status/status-get.js @@ -1,4 +1,4 @@ -import {requester} from '../helpers/api.helper'; +import {requester} from '../../helpers/api.helper'; describe('Status', () => { let api; From 5d268c58de6d207cf49095bd07911a7c08812e1f Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 18:04:32 -0500 Subject: [PATCH 14/53] Adjust api test commands --- tasks/gulp-tests.js | 76 +++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index c8b9ed7912..fded5009b1 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -9,12 +9,13 @@ import Q from 'q'; import Mocha from 'mocha'; import { resolve } from 'path'; -const TEST_SERVER_PORT = 3001 +const E2E_TEST_SERVER_PORT = 3001 +const API_TEST_SERVER_PORT = 3003 const TEST_DB = 'habitrpg_test' const TEST_DB_URI = `mongodb://localhost/${TEST_DB}` -const API_TEST_COMMAND = 'mocha test/api --compilers js:babel/register'; +const API_TEST_COMMAND = 'mocha test/api --recursive --compilers js:babel/register'; const LEGACY_API_TEST_COMMAND = 'mocha test/api-legacy'; const COMMON_TEST_COMMAND = 'mocha test/common --compilers coffee:coffee-script'; const CONTENT_TEST_COMMAND = 'mocha test/content --compilers js:babel/register'; @@ -229,7 +230,7 @@ gulp.task('test:karma:safe', ['test:prepare:build'], (cb) => { gulp.task('test:e2e', ['test:prepare'], (cb) => { let support = [ 'Xvfb :99 -screen 0 1024x768x24 -extension RANDR', - `NODE_DB_URI="${TEST_DB_URI}" PORT="${TEST_SERVER_PORT}" node ./website/src/server.js`, + `NODE_DB_URI="${TEST_DB_URI}" PORT="${E2E_TEST_SERVER_PORT}" node ./website/src/server.js`, './node_modules/protractor/bin/webdriver-manager start', ].map(exec); @@ -254,7 +255,7 @@ gulp.task('test:e2e', ['test:prepare'], (cb) => { gulp.task('test:e2e:safe', ['test:prepare'], (cb) => { let support = [ 'Xvfb :99 -screen 0 1024x768x24 -extension RANDR', - `NODE_DB_URI="${TEST_DB_URI}" PORT="${TEST_SERVER_PORT}" node ./website/src/server.js`, + `NODE_DB_URI="${TEST_DB_URI}" PORT="${E2E_TEST_SERVER_PORT}" node ./website/src/server.js`, './node_modules/protractor/bin/webdriver-manager start', ].map(exec); @@ -283,47 +284,48 @@ gulp.task('test:e2e:safe', ['test:prepare'], (cb) => { }); }); -gulp.task('test:api', ['test:startServer', 'test:prepare:mongo'], (done) => { +gulp.task('test:api', ['test:prepare:mongo'], (done) => { require('../test/helpers/globals.helper'); - let mocha = new Mocha({reporter: 'spec'}); - let tests = glob('./test/api/**/*.js'); - tests.forEach((test) => { - delete require.cache[resolve(test)]; - mocha.addFile(test); - }); + let server = exec(`NODE_DB_URI="${TEST_DB_URI}" PORT="${API_TEST_SERVER_PORT}" node ./website/src/server.js`); - mocha.run((numberOfFailures) => { - if (!process.env.RUN_INTEGRATION_TEST_FOREVER) { - process.exit(numberOfFailures); - } - done(); - }); -}); + awaitPort(API_TEST_SERVER_PORT).then(() => { + let mocha = new Mocha({reporter: 'spec'}); + let tests = glob('./test/api/**/*.js'); -gulp.task('test:api:safe', ['test:startServer', 'test:prepare:mongo'], (done) => { - let runner = exec( - testBin(API_TEST_COMMAND), - (err, stdout, stderr) => { - testResults.push({ - suite: 'API Specs', - pass: testCount(stdout, /(\d+) passing/), - fail: testCount(stderr, /(\d+) failing/), - pend: testCount(stdout, /(\d+) pending/) - }); + tests.forEach((test) => { + delete require.cache[resolve(test)]; + mocha.addFile(test); + }); + + mocha.run((numberOfFailures) => { + if (!process.env.RUN_INTEGRATION_TEST_FOREVER) { + kill(server); + } done(); - } - ); - pipe(runner); + }); + }); }); -gulp.task('test:startServer', (done) => { - process.env.NODE_DB_URI = `mongodb://localhost/${TEST_DB}-api`; - process.env.DISABLE_REQUEST_LOGGING = true; - process.env.PORT = 3003; +gulp.task('test:api:safe', ['test:prepare:mongo'], (done) => { + let server = exec(`NODE_DB_URI="${TEST_DB_URI}" PORT="${API_TEST_SERVER_PORT}" node ./website/src/server.js`); - let server = require('../website/src/server.js'); - server.listen(TEST_SERVER_PORT, done); + awaitPort(API_TEST_SERVER_PORT).then(() => { + let runner = exec( + testBin(API_TEST_COMMAND), + (err, stdout, stderr) => { + testResults.push({ + suite: 'API Specs\t', + pass: testCount(stdout, /(\d+) passing/), + fail: testCount(stderr, /(\d+) failing/), + pend: testCount(stdout, /(\d+) pending/) + }); + kill(server); + done(); + } + ); + pipe(runner); + }); }); gulp.task('test', [ From de6a853aaf9dda1b15a488ffdb3715be01f6d679 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 18:05:44 -0500 Subject: [PATCH 15/53] Adjust api helper --- test/api/status/status-get.js | 3 +-- test/helpers/api.helper.js | 17 +++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/test/api/status/status-get.js b/test/api/status/status-get.js index 9b9762c250..f4687b64be 100644 --- a/test/api/status/status-get.js +++ b/test/api/status/status-get.js @@ -10,8 +10,7 @@ describe('Status', () => { it('returns a status of up when server is up', (done) => { api.get('/status') .then((res) => { - expect(res.code).to.eql(200); - expect(res.body.status).to.eql('up'); + expect(res.status).to.eql('up'); done(); }) .catch((err) => { diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index becc2f6274..da1cf28075 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -1,5 +1,7 @@ import superagent from 'superagent'; +const API_TEST_SERVER_PORT = 3003; + export function requester(user={}) { return { get: _requestMaker(user, 'get'), @@ -10,9 +12,9 @@ export function requester(user={}) { } function _requestMaker(user, method) { - return (route, options={}) => { + return (route, send, query) => { return new Promise((resolve, reject) => { - let request = superagent[method](`http://localhost:3003/api/v2${route}`) + let request = superagent[method](`http://localhost:${API_TEST_SERVER_PORT}/api/v2${route}`) .accept('application/json'); if (user._id && user.apiToken) { @@ -22,17 +24,12 @@ function _requestMaker(user, method) { } request - .query(options.query) - .send(options.send) + .query(query) + .send(send) .end((err, response) => { if (err) { return reject(err); } - let res = { - code: response.statusCode, - body: response.body, - } - - resolve(res); + resolve(response.body); }); }); } From 5291d1a4e99ca3fbc8c8c8c4763814d5d0205c58 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 18:13:38 -0500 Subject: [PATCH 16/53] Add test for registering a user --- package.json | 1 + test/api/register/register-post.js | 31 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 test/api/register/register-post.js diff --git a/package.json b/package.json index eeffbe408e..3ffdc11869 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "sinon": "1.15.4", "sinon-chai": "^2.7.0", "superagent-defaults": "~0.1.5", + "uuid": "^2.0.1", "vinyl-source-stream": "^1.0.0", "vinyl-transform": "^1.0.0" } diff --git a/test/api/register/register-post.js b/test/api/register/register-post.js new file mode 100644 index 0000000000..e8e970cf44 --- /dev/null +++ b/test/api/register/register-post.js @@ -0,0 +1,31 @@ +import {requester} from '../../helpers/api.helper'; +import {v4 as generateRandomUserName} from 'uuid'; + +describe('POST /register', () => { + let api; + + beforeEach(() => { + api = requester(); + }); + + it('registers a new user', (done) => { + let username = generateRandomUserName(); + let email = `${username}@example.com`; + let password = 'password'; + + api.post('/register', { + username: username, + email: email, + password: password, + confirmPassword: password, + }).then((user) => { + expect(user._id).to.exist; + expect(user.auth.local.username).to.eql(username); + expect(user.auth.local.email).to.eql(`${username}@example.com`); + done(); + }) + .catch((err) => { + done(err); + }); + }); +}); From c51caa0664ba2ed39747724392b9a20d5a418469 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 18:27:19 -0500 Subject: [PATCH 17/53] Add generate new user helper --- test/api/user/user-get.js | 29 +++++++++++++++++++++++++++++ test/helpers/api.helper.js | 21 +++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 test/api/user/user-get.js diff --git a/test/api/user/user-get.js b/test/api/user/user-get.js new file mode 100644 index 0000000000..74516920e1 --- /dev/null +++ b/test/api/user/user-get.js @@ -0,0 +1,29 @@ +import { + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('GET /user', () => { + let api, user; + + beforeEach((done) => { + api = requester(); + generateUser().then((usr) => { + user = usr; + api = requester(usr); + done(); + }).catch(done); + }); + + it('gets the user object', (done) => { + api.get('/user') + .then((fetchedUser) => { + expect(fetchedUser._id).to.eql(user._id); + expect(fetchedUser.todos).to.eql(user.todos); + done(); + }) + .catch((err) => { + done(err); + }); + }); +}); diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index da1cf28075..31fdaf089e 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -1,3 +1,5 @@ +import {isEmpty} from 'lodash'; +import {v4 as generateRandomUserName} from 'uuid'; import superagent from 'superagent'; const API_TEST_SERVER_PORT = 3003; @@ -11,6 +13,25 @@ export function requester(user={}) { } } +export function generateUser(update={}) { + let username = generateRandomUserName(); + let password = 'password' + let email = username + '@example.com'; + + let request = _requestMaker({}, 'post'); + + return new Promise((resolve, reject) => { + request('/register', { + username: username, + email: email, + password: password, + confirmPassword: password, + }).then((user) => { + resolve(user); + }); + }); +}; + function _requestMaker(user, method) { return (route, send, query) => { return new Promise((resolve, reject) => { From 7f6b39251100e585668ae850c609b4d947262874 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 19:17:23 -0500 Subject: [PATCH 18/53] Add gulp watch task for api tests --- tasks/gulp-tests.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index fded5009b1..fc03660248 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -301,12 +301,18 @@ gulp.task('test:api', ['test:prepare:mongo'], (done) => { mocha.run((numberOfFailures) => { if (!process.env.RUN_INTEGRATION_TEST_FOREVER) { kill(server); + process.exit(numberOfFailures); } done(); }); }); }); +gulp.task('test:api:watch', () => { + process.env.RUN_INTEGRATION_TEST_FOREVER = true; + gulp.watch(['website/src/**', 'test/api/**'], ['test:api']); +}); + gulp.task('test:api:safe', ['test:prepare:mongo'], (done) => { let server = exec(`NODE_DB_URI="${TEST_DB_URI}" PORT="${API_TEST_SERVER_PORT}" node ./website/src/server.js`); From 75f63b1367c1f28be6f7a63fe4c58b7f4d1fefaa Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 19:19:40 -0500 Subject: [PATCH 19/53] Add functionality to generate user to update user --- package.json | 1 + test/helpers/api.helper.js | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ffdc11869..a14173614d 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,7 @@ "karma-script-launcher": "~0.1.0", "lcov-result-merger": "^1.0.2", "mocha": "~1.12.1", + "mongodb": "^2.0.46", "mongoskin": "~0.6.1", "protractor": "~2.0.0", "rewire": "^2.3.3", diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index 31fdaf089e..6da6728d78 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -1,4 +1,5 @@ import {isEmpty} from 'lodash'; +import {MongoClient as mongo} from 'mongodb'; import {v4 as generateRandomUserName} from 'uuid'; import superagent from 'superagent'; @@ -27,7 +28,9 @@ export function generateUser(update={}) { password: password, confirmPassword: password, }).then((user) => { - resolve(user); + _updateDocument('users', user._id, update, () => { + resolve(user); + }); }); }); }; @@ -55,3 +58,18 @@ function _requestMaker(user, method) { }); } } + +function _updateDocument(collectionName, uuid, update, cb) { + if (isEmpty(update)) { return cb(); } + + mongo.connect('mongodb://localhost/habitrpg_test', (err, db) => { + if (err) throw `Error connecting to database when updating ${collectionName} collection: ${err}`; + + let collection = db.collection(collectionName); + + collection.update({ _id: uuid }, { $set: update }, (err, result) => { + if (err) throw `Error updating ${collectionName}: ${err}`; + cb(); + }); + }); +} From 1d22382c16f743a8d92ea3794a7fb8cd0f43515a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 20:15:34 -0500 Subject: [PATCH 20/53] Remove get user test from legacy script --- test/api-legacy/users.coffee | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/test/api-legacy/users.coffee b/test/api-legacy/users.coffee index 87f7897dde..e465d1f3d5 100644 --- a/test/api-legacy/users.coffee +++ b/test/api-legacy/users.coffee @@ -5,30 +5,6 @@ app = require("../../website/src/server") describe "Users", -> - describe "GET /user without token or user id", -> - - it "/api/v2/user", (done) -> - request - .get(baseURL + "/user") - .set("Accept", "application/json") - .set("X-API-User", '') - .set("X-API-Key", '') - .end (res) -> - expect(res.statusCode).to.equal 401 - expect(res.body.err).to.equal "You must include a token and uid (user id) in your request" - done() - - describe "GET /user with token or user id", -> - - before (done) -> - registerNewUser(done, true) - - it "/api/v2/user", (done) -> - request.get(baseURL + "/user").set("Accept", "application/json").end (res) -> - expect(res.statusCode).to.equal 200 - expect(res.body._id).to.equal user._id - done() - describe "Deleting Users", -> before (done) -> From 416f82ade73cfe55d7ee59ef8870b94b54ac82a6 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 20:18:37 -0500 Subject: [PATCH 21/53] Clean up user test --- test/api/user/user-get.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/api/user/user-get.js b/test/api/user/user-get.js index 74516920e1..20cfce2308 100644 --- a/test/api/user/user-get.js +++ b/test/api/user/user-get.js @@ -7,7 +7,6 @@ describe('GET /user', () => { let api, user; beforeEach((done) => { - api = requester(); generateUser().then((usr) => { user = usr; api = requester(usr); From 680be3a641233e8b88f09a193612b3e8f6630f6a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 20:18:44 -0500 Subject: [PATCH 22/53] Add delete user test --- test/api/user/user-delete.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/api/user/user-delete.js diff --git a/test/api/user/user-delete.js b/test/api/user/user-delete.js new file mode 100644 index 0000000000..245088a83d --- /dev/null +++ b/test/api/user/user-delete.js @@ -0,0 +1,29 @@ +import { + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('DELETE /user', () => { + let api; + + beforeEach((done) => { + generateUser().then((usr) => { + api = requester(usr); + done(); + }).catch(done); + }); + + it('deletes the user', (done) => { + api.del('/user') + .then((fetchedUser) => { + return api.get('/user') + }) + .then((deletedUser) => { + done('Unexpected user'); + }) + .catch((err) => { + expect(err.response.status).to.eql(401); + done(); + }); + }); +}); From 7f5c556654d481a3e70cb6aaabba50d570eda31f Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 20:23:29 -0500 Subject: [PATCH 23/53] Add pending tests --- test/api/user/user-delete.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/api/user/user-delete.js b/test/api/user/user-delete.js index 245088a83d..44ba3d11e2 100644 --- a/test/api/user/user-delete.js +++ b/test/api/user/user-delete.js @@ -26,4 +26,20 @@ describe('DELETE /user', () => { done(); }); }); + + context('user in solo group', () => { + + it('deletes party when user is the only member'); + + it('deletes private guild when user is the only member'); + }); + + context('user in group with members', () => { + + it('removes user from all groups user was a part of'); + + it('chooses new group leader for any group user was the leader of'); + + it('removes invitations from groups'); + }); }); From 477fb8edcbba528145d9cdc7b02ae2e610ee259e Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 20:38:18 -0500 Subject: [PATCH 24/53] Add missing semicolon --- test/helpers/api.helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index 6da6728d78..9ef5a9a7c1 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -12,7 +12,7 @@ export function requester(user={}) { put: _requestMaker(user, 'put'), del: _requestMaker(user, 'del'), } -} +}; export function generateUser(update={}) { let username = generateRandomUserName(); From ab2b564a032b864731aebd3a444a330ee9f7d0ad Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 17 Oct 2015 21:24:46 -0500 Subject: [PATCH 25/53] Update error check --- test/api/user/user-delete.js | 2 +- test/helpers/api.helper.js | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/api/user/user-delete.js b/test/api/user/user-delete.js index 44ba3d11e2..ed97b2bdb7 100644 --- a/test/api/user/user-delete.js +++ b/test/api/user/user-delete.js @@ -22,7 +22,7 @@ describe('DELETE /user', () => { done('Unexpected user'); }) .catch((err) => { - expect(err.response.status).to.eql(401); + expect(err.code).to.eql(401); done(); }); }); diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index 9ef5a9a7c1..269bca88d4 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -51,7 +51,13 @@ function _requestMaker(user, method) { .query(query) .send(send) .end((err, response) => { - if (err) { return reject(err); } + if (err) { + let errorString = JSON.parse(err.response.text).err; + return reject({ + code: err.response.statusCode, + text: errorString, + }); + } resolve(response.body); }); From 8f7ecf7d7cb57b538795795746e129891cc5ae2c Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 06:03:22 -0500 Subject: [PATCH 26/53] Rename uuid function --- test/helpers/api.helper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index 269bca88d4..bce8ca71fc 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -1,6 +1,6 @@ import {isEmpty} from 'lodash'; import {MongoClient as mongo} from 'mongodb'; -import {v4 as generateRandomUserName} from 'uuid'; +import {v4 as generateUUID} from 'uuid'; import superagent from 'superagent'; const API_TEST_SERVER_PORT = 3003; @@ -15,7 +15,7 @@ export function requester(user={}) { }; export function generateUser(update={}) { - let username = generateRandomUserName(); + let username = generateUUID(); let password = 'password' let email = username + '@example.com'; From 24001c5c663f55286b2a37df15383ee399c3cf50 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 06:15:38 -0500 Subject: [PATCH 27/53] Create generate group function --- test/helpers/api.helper.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index bce8ca71fc..b1739b6259 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -35,6 +35,18 @@ export function generateUser(update={}) { }); }; +export function generateGroup(leader, update={}) { + let request = _requestMaker(leader, 'post'); + + return new Promise((resolve, reject) => { + request('/groups').then((group) => { + _updateDocument('groups', group._id, update, () => { + resolve(group); + }); + }); + }); +}; + function _requestMaker(user, method) { return (route, send, query) => { return new Promise((resolve, reject) => { From 82b133e8fca80875a6f4fde9bf3f1885de5cb2fd Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 06:38:22 -0500 Subject: [PATCH 28/53] Add tests for creating groups --- test/api-legacy/groups.coffee | 47 --------- test/api/groups/groups-post.js | 182 +++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 47 deletions(-) create mode 100644 test/api/groups/groups-post.js diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index b5a4fa2765..688a1bc956 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -6,53 +6,6 @@ Group = require("../../website/src/models/group").model app = require("../../website/src/server") describe "Guilds", -> - context "creating groups", -> - before (done) -> - registerNewUser -> - User.findByIdAndUpdate user._id, - $set: - "balance": 40 - , (err, _user) -> - done() - , true - - it "can create a public guild", (done) -> - request.post(baseURL + "/groups").send( - name: "TestGroup" - type: "guild", - privacy: "public" - ).end (res) -> - expectCode res, 200 - guild = res.body - expect(guild.members.length).to.equal 1 - expect(guild.leader).to.equal user._id - done() - - it "can create a private guild", (done) -> - request.post(baseURL + "/groups").send( - name: "TestGroup" - type: "guild", - privacy: "private" - ).end (res) -> - expectCode res, 200 - guild = res.body - expect(guild.members.length).to.equal 1 - expect(guild.leader).to.equal user._id - done() - - it "prevents user from creating a guild when the user has 0 gems", (done) -> - registerNewUser (err, user_with_0_gems) -> - request.post(baseURL + "/groups").send( - name: "TestGroup" - type: "guild", - ) - .set("X-API-User", user_with_0_gems._id) - .set("X-API-Key", user_with_0_gems.apiToken) - .end (res) -> - expectCode res, 401 - done() - , false - context "get guilds", -> guild = undefined diff --git a/test/api/groups/groups-post.js b/test/api/groups/groups-post.js new file mode 100644 index 0000000000..ea95205c09 --- /dev/null +++ b/test/api/groups/groups-post.js @@ -0,0 +1,182 @@ +import { + generateGroup, + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('POST /groups', () => { + + context('All groups', () => { + let api, leader; + + beforeEach((done) => { + generateUser().then((user) => { + leader = user; + api = requester(user); + done(); + }).catch(done); + }); + + it('returns a group object', (done) => { + let group = { + name: 'Test Group', + type: 'party', + leaderOnly: { challenges: true }, + description: 'Test Group Description', + leaderMessage: 'Test Group Message', + }; + + api.post('/groups', + group + ).then((createdGroup) => { + expect(createdGroup._id).to.exist; + expect(createdGroup.leader).to.eql(leader._id); + expect(createdGroup.name).to.eql(group.name); + expect(createdGroup.description).to.eql(group.description); + expect(createdGroup.leaderMessage).to.eql(group.leaderMessage); + expect(createdGroup.leaderOnly.challenges).to.eql(group.leaderOnly.challenges); + expect(createdGroup.memberCount).to.eql(1); + expect(createdGroup.members).to.have.a.lengthOf(1); + done(); + }) + .catch((err) => { + done(err); + }); + }); + + it('returns a populated members array', (done) => { + api.post('/groups', { + type: 'party', + }).then((createdGroup) => { + let member = createdGroup.members[0]; + + expect(member._id).to.eql(leader._id); + expect(member.profile.name).to.eql(leader.profile.name); + expect(member.items).to.exist; + expect(member.stats).to.exist; + expect(member.achievements).to.exist; + expect(member.contributor).to.exist; + done(); + }) + .catch((err) => { + done(err); + }); + }); + }); + + context('Parties', () => { + let api, leader; + + beforeEach((done) => { + generateUser().then((user) => { + leader = user; + api = requester(user); + done(); + }).catch(done); + }); + + it('allows party creation without gems', (done) => { + api.post('/groups', { + type: 'party', + }) + .then((group) => { + expect(group._id).to.exist; + done(); + }) + .catch((err) => { + done(err); + }); + }); + + it('prevents party creation if user is already in party', (done) => { + generateGroup(leader, { + type: 'party', + }).then((group) => { + return api.post('/groups', { + type: 'party', + }); + }).then((group) => { + done('Unexpected success'); + }) + .catch((err) => { + expect(err.code).to.eql(400); + expect(err.text).to.eql('Already in a party, try refreshing.'); + done(); + }); + }) + }); + + context('Guilds', () => { + let api, leader; + + beforeEach((done) => { + generateUser({ + balance: 2, + }).then((user) => { + leader = user; + api = requester(user); + done(); + }).catch(done); + }); + + it('prevents guild creation when user does not have enough gems', (done) => { + generateUser({ + balance: 0.75, + }).then((user) => { + api = requester(user); + return api.post('/groups', { + type: 'guild', + }); + }).then((group) => { + done('Unexpected success'); + }).catch((err) => { + expect(err.code).to.eql(401); + expect(err.text).to.eql('Not enough gems!'); + done(); + }); + }); + + + it('can create a public guild', (done) => { + api.post('/groups', { + type: 'guild', + privacy: 'public', + }).then((group) => { + expect(group.leader).to.eql(leader._id); + done(); + }) + .catch((err) => { + done(err); + }); + }); + + it('can create a private guild', (done) => { + api.post('/groups', { + type: 'guild', + privacy: 'private', + }).then((group) => { + expect(group.leader).to.eql(leader._id); + done(); + }) + .catch((err) => { + done(err); + }); + }); + + it('deducts gems from user and adds them to guild bank', (done) => { + api.post('/groups', { + type: 'guild', + privacy: 'private', + }).then((group) => { + expect(group.balance).to.eql(1); + return api.get('/user'); + }).then((user) => { + expect(user.balance).to.eql(1); + done(); + }) + .catch((err) => { + done(err); + }); + }); + }); +}); From 9b2da51991b00fe6805e17b578863a5bff3ec10d Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 06:48:43 -0500 Subject: [PATCH 29/53] Create pending tests for unhandled behavior --- test/api/groups/groups-post.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/api/groups/groups-post.js b/test/api/groups/groups-post.js index ea95205c09..e231e17812 100644 --- a/test/api/groups/groups-post.js +++ b/test/api/groups/groups-post.js @@ -17,6 +17,18 @@ describe('POST /groups', () => { }).catch(done); }); + xit('returns defaults? (TODO: it\'s possible to create a group without a type. Should the group default to party? Should we require type to be set?', (done) => { + api.post('/groups').then((group) => { + expect(group._id).to.exist; + expect(group.name).to.eql(`${leader.profile.name}'s group`); + expect(group.type).to.eql('party'); + expect(group.privacy).to.eql('private'); + done(); + }).catch((err) => { + done(err); + }); + }); + it('returns a group object', (done) => { let group = { name: 'Test Group', @@ -104,6 +116,21 @@ describe('POST /groups', () => { done(); }); }) + + xit('prevents creating a public party. TODO: it is possible to create a public party. Should we send back an error? Automatically switch the privacy to private?', (done) => { + api.post('/groups', { + type: 'party', + privacy: 'public', + }) + .then((group) => { + done('Unexpected success'); + }) + .catch((err) => { + expect(err.code).to.eql(400); + expect(err.text).to.eql('Parties must be private'); + done(); + }); + }); }); context('Guilds', () => { From 4fa82ba196487901e74e2b13825fae94467a9acd Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 07:00:48 -0500 Subject: [PATCH 30/53] Update generated document with update object --- test/helpers/api.helper.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index b1739b6259..d3fed6e2a7 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -1,4 +1,7 @@ -import {isEmpty} from 'lodash'; +import { + assign, + isEmpty, +} from 'lodash'; import {MongoClient as mongo} from 'mongodb'; import {v4 as generateUUID} from 'uuid'; import superagent from 'superagent'; @@ -28,7 +31,7 @@ export function generateUser(update={}) { password: password, confirmPassword: password, }).then((user) => { - _updateDocument('users', user._id, update, () => { + _updateDocument('users', user, update, () => { resolve(user); }); }); @@ -40,7 +43,7 @@ export function generateGroup(leader, update={}) { return new Promise((resolve, reject) => { request('/groups').then((group) => { - _updateDocument('groups', group._id, update, () => { + _updateDocument('groups', group, update, () => { resolve(group); }); }); @@ -77,7 +80,7 @@ function _requestMaker(user, method) { } } -function _updateDocument(collectionName, uuid, update, cb) { +function _updateDocument(collectionName, doc, update, cb) { if (isEmpty(update)) { return cb(); } mongo.connect('mongodb://localhost/habitrpg_test', (err, db) => { @@ -85,8 +88,9 @@ function _updateDocument(collectionName, uuid, update, cb) { let collection = db.collection(collectionName); - collection.update({ _id: uuid }, { $set: update }, (err, result) => { + collection.update({ _id: doc._id }, { $set: update }, (err, result) => { if (err) throw `Error updating ${collectionName}: ${err}`; + assign(doc, update); cb(); }); }); From bab093b7ab1395d9ad1766b8c4b0d4c1b72b1b08 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 07:15:35 -0500 Subject: [PATCH 31/53] Write get group tests --- test/api-legacy/groups.coffee | 27 ---- test/api/groups/groups_id-get.js | 206 +++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 27 deletions(-) create mode 100644 test/api/groups/groups_id-get.js diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index 688a1bc956..f3169bc443 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -17,33 +17,6 @@ describe "Guilds", -> guild = res.body done() - it "can find a guild", (done) -> - request.get(baseURL + "/groups/" + guild._id) - .end (res) -> - expectCode res, 200 - expect(res.body._id).to.equal res.body._id - done() - - it "transforms members array to an arrray of user objects", (done) -> - request.get(baseURL + "/groups/" + guild._id) - .end (res) -> - expectCode res, 200 - members = res.body.members - # @TODO: would be more instructive if it had more members in guild :( - _(members).each (member) -> - expect(member).to.be.an 'object' - expect(member.profile.name).to.exist - done() - - it "transforms leader id to a user object", (done) -> - request.get(baseURL + "/groups/" + guild._id) - .end (res) -> - expectCode res, 200 - leader = res.body.leader - expect(leader).to.be.an 'object' - expect(leader.profile.name).to.exist - done() - it "can list guilds", (done) -> request.get(baseURL + "/groups").send() .end (res) -> diff --git a/test/api/groups/groups_id-get.js b/test/api/groups/groups_id-get.js new file mode 100644 index 0000000000..6a6218e653 --- /dev/null +++ b/test/api/groups/groups_id-get.js @@ -0,0 +1,206 @@ +import { + generateGroup, + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('GET /groups/:id', () => { + + context('All Groups', () => { + let api, leader, createdGroup; + + beforeEach((done) => { + generateUser({ + balance: 1, + }).then((user) => { + leader = user; + api = requester(user); + return generateGroup(leader, { + name: 'group name', + type: 'guild', + privacy: 'public', + }); + }).then((group) => { + createdGroup = group; + done(); + }).catch(done); + }); + + it('transforms members array to an array of user objects', (done) => { + api.get(`/groups/${createdGroup._id}`).then((group) => { + let member = group.members[0]; + expect(member._id).to.eql(leader._id); + expect(member.profile.name).to.eql(leader.profile.name); + expect(member.items).to.exist; + expect(member.stats).to.exist; + expect(member.achievements).to.exist; + expect(member.contributor).to.exist; + done(); + }).catch(done); + }); + + it('transforms leader id to leader object', (done) => { + api.get(`/groups/${createdGroup._id}`).then((group) => { + expect(group.leader._id).to.eql(leader._id); + expect(group.leader.profile.name).to.eql(leader.profile.name); + expect(group.leader.items).to.exist; + expect(group.leader.stats).to.exist; + expect(group.leader.achievements).to.exist; + expect(group.leader.contributor).to.exist; + done(); + }).catch(done); + }); + + it('returns error if group does not exist', (done) => { + generateUser().then((user) => { + api = requester(user); + return api.get('/groups/group-that-does-not-exist'); + }).then((done)).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done() + }); + }); + }); + + context('Public Guilds', () => { + let api, leader, createdGroup; + + beforeEach((done) => { + generateUser({ + balance: 1, + }).then((user) => { + leader = user; + api = requester(user); + return generateGroup(leader, { + name: 'group name', + type: 'guild', + privacy: 'public', + }); + }).then((group) => { + createdGroup = group; + done(); + }).catch(done); + }); + + it('returns the group object', (done) => { + api.get(`/groups/${createdGroup._id}`) + .then((group) => { + expect(group._id).to.eql(createdGroup._id); + expect(group.name).to.eql(createdGroup.name); + expect(group.type).to.eql(createdGroup.type); + expect(group.privacy).to.eql(createdGroup.privacy); + done(); + }).catch(done); + }); + + it('returns the group object for a non-member', (done) => { + generateUser().then((user) => { + api = requester(user); + return api.get(`/groups/${createdGroup._id}`); + }).then((group) => { + expect(group._id).to.eql(createdGroup._id); + expect(group.name).to.eql(createdGroup.name); + expect(group.type).to.eql(createdGroup.type); + expect(group.privacy).to.eql(createdGroup.privacy); + done(); + }).catch(done); + }); + }); + + context('Private Guilds', () => { + let api, leader, createdGroup; + + beforeEach((done) => { + generateUser({ + balance: 1, + }).then((user) => { + leader = user; + api = requester(user); + return generateGroup(leader, { + name: 'group name', + type: 'guild', + privacy: 'private', + }); + }).then((group) => { + createdGroup = group; + done(); + }).catch(done); + }); + + it('returns the group object', (done) => { + api.get(`/groups/${createdGroup._id}`) + .then((group) => { + expect(group._id).to.eql(createdGroup._id); + expect(group.name).to.eql(createdGroup.name); + expect(group.type).to.eql(createdGroup.type); + expect(group.privacy).to.eql(createdGroup.privacy); + done(); + }).catch(done); + }); + + it('does not return the group object for a non-member', (done) => { + generateUser().then((user) => { + api = requester(user); + return api.get(`/groups/${createdGroup._id}`); + }).then((done)).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done() + }); + }); + }); + + context('Parties', () => { + let api, leader, createdGroup; + + beforeEach((done) => { + generateUser({ + balance: 1, + }).then((user) => { + leader = user; + api = requester(user); + return generateGroup(leader, { + name: 'group name', + type: 'party', + }); + }).then((group) => { + createdGroup = group; + done(); + }).catch(done); + }); + + it('returns the group object', (done) => { + api.get(`/groups/${createdGroup._id}`) + .then((group) => { + expect(group._id).to.eql(createdGroup._id); + expect(group.name).to.eql(createdGroup.name); + expect(group.type).to.eql(createdGroup.type); + expect(group.privacy).to.eql(createdGroup.privacy); + done(); + }).catch(done); + }); + + it('does not return the group object for a non-member', (done) => { + generateUser().then((user) => { + api = requester(user); + return api.get(`/groups/${createdGroup._id}`); + }).then((done)).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done() + }); + }); + + it('returns the user\'s party if an id of "party" is passed in', (done) => { + api.get('/groups/party') + .then((group) => { + expect(group._id).to.eql(createdGroup._id); + expect(group.name).to.eql(createdGroup.name); + expect(group.type).to.eql(createdGroup.type); + expect(group.privacy).to.eql(createdGroup.privacy); + done(); + }).catch(done); + }); + }); +}); From ece2985eb05f428acda8a4497742cc88905f8930 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 08:46:47 -0500 Subject: [PATCH 32/53] Return better error when connection can't be established --- test/helpers/api.helper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index d3fed6e2a7..c0bc64ddc3 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -67,6 +67,7 @@ function _requestMaker(user, method) { .send(send) .end((err, response) => { if (err) { + if (!err.response) return reject(err); let errorString = JSON.parse(err.response.text).err; return reject({ code: err.response.statusCode, From 63b17f01739410cd727e8fc10fdea1512c024672 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 08:47:14 -0500 Subject: [PATCH 33/53] Create method to reset habitica db --- test/helpers/api.helper.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index c0bc64ddc3..c5497213b6 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -50,6 +50,31 @@ export function generateGroup(leader, update={}) { }); }; +export function resetHabiticaDB() { + return new Promise((resolve, reject) => { + mongo.connect('mongodb://localhost/habitrpg_test', (err, db) => { + if (err) return reject(err); + + db.dropDatabase((err) => { + if (err) return reject(err); + // A fresh install of Habitica has a tavern group + let groups = db.collection('groups'); + groups.insertOne({ + _id: 'habitrpg', + chat: [], + leader: '9', + name: 'HabitRPG', + type: 'guild', + privacy: 'public', + }, (err) => { + if (err) return reject(err); + resolve(); + }); + }); + }); + }); +} + function _requestMaker(user, method) { return (route, send, query) => { return new Promise((resolve, reject) => { From cd224ac8d8db080e7cc482760f5dc245a2d6febf Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 09:59:39 -0500 Subject: [PATCH 34/53] Add members attribute to tavern --- test/helpers/api.helper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index c5497213b6..546e21a234 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -66,6 +66,7 @@ export function resetHabiticaDB() { name: 'HabitRPG', type: 'guild', privacy: 'public', + members: [], }, (err) => { if (err) return reject(err); resolve(); From b2350f10f1d7dbca1395e71a1852b836bf5e4e2b Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 10:01:55 -0500 Subject: [PATCH 35/53] Create get groups test --- test/api-legacy/groups.coffee | 19 ----- test/api/groups/groups-get.js | 143 ++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 19 deletions(-) create mode 100644 test/api/groups/groups-get.js diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index f3169bc443..4e6a92aa76 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -6,25 +6,6 @@ Group = require("../../website/src/models/group").model app = require("../../website/src/server") describe "Guilds", -> - context "get guilds", -> - guild = undefined - - beforeEach (done)-> - request.post(baseURL + "/groups").send( - name: "TestGroup2" - type: "guild" - ).end (res) -> - guild = res.body - done() - - it "can list guilds", (done) -> - request.get(baseURL + "/groups").send() - .end (res) -> - expectCode res, 200 - guild = res.body[0] - expect(guild).to.exist - done() - context "updating groups", -> groupToUpdate = undefined before (done) -> diff --git a/test/api/groups/groups-get.js b/test/api/groups/groups-get.js new file mode 100644 index 0000000000..102efc41f1 --- /dev/null +++ b/test/api/groups/groups-get.js @@ -0,0 +1,143 @@ +import { + generateGroup, + generateUser, + resetHabiticaDB, + requester, +} from '../../helpers/api.helper'; + +describe('GET /groups', () => { + let user, api; + + before((done) => { + let leader, createdGroup; + + // Set up a world with a mixture of public and private guilds + // Invite user to a few of them + resetHabiticaDB().then(() => { + return generateUser(); + }).then((_user) => { + user = _user; + + return generateUser({ + balance: 10, + }); + }).then((_user) => { + leader = _user; + api = requester(leader); + + let publicGuildWithUserAsMember = generateGroup(leader, { + name: 'public guild - is member', + type: 'guild', + privacy: 'public', + members: [leader._id, user._id], + }); + + let publicGuildWithoutUserAsMember = generateGroup(leader, { + name: 'public guild - is not member', + type: 'guild', + privacy: 'public', + }); + + let privateGuildWithUserAsMember = generateGroup(leader, { + name: 'private guild - is member', + type: 'guild', + privacy: 'private', + members: [leader._id, user._id], + }); + + let privateGuildWithoutUserAsMember = generateGroup(leader, { + name: 'private guild - is not member', + type: 'guild', + privacy: 'private', + }); + + let partyWithoutUserAsMember = generateGroup(leader, { + name: 'party name', + type: 'party', + privacy: 'private', + }); + + let promises = [ + publicGuildWithUserAsMember, + publicGuildWithoutUserAsMember, + privateGuildWithUserAsMember, + privateGuildWithoutUserAsMember, + partyWithoutUserAsMember, + ]; + + return Promise.all(promises); + }).then((groups) => { + api = requester(user); + return api.post('/groups', { + type: 'party', + name: 'user\'s party', + privacy: 'private', + }); + }) + .then((party) => { + done(); + }).catch(done); + }); + + context('no query passed in', () => { + + xit('lists all public guilds, the tavern, user\'s party, and any private guilds that user is a part of - TODO query includes duplicates - IE, tavern is included as tavern and part of public guilds. Refactor so this is not the case', (done) => { + api.get('/groups').then((groups) => { + expect(groups.length).to.eql(4); + done(); + }).catch(done); + }); + }); + + context('tavern passed in as query', () => { + + it('returns only the tavern', (done) => { + api.get('/groups', null, {type: 'tavern'}).then((groups) => { + expect(groups).to.have.a.lengthOf(1); + + let tavern = groups[0]; + expect(tavern._id).to.eql('habitrpg'); + done(); + }).catch((err) => { + console.log(err); + done(err); + }); + }); + }); + + context('party passed in as query', () => { + + it('returns only the user\'s party', (done) => { + api.get('/groups', null, {type: 'party'}).then((groups) => { + expect(groups).to.have.a.lengthOf(1); + + let party = groups[0]; + expect(party.leader).to.eql(user._id); + + done(); + }).catch(done); + }); + }); + + context('public passed in as query', () => { + + it('returns all public guilds', (done) => { + api.get('/groups', null, {type: 'public'}).then((groups) => { + expect(groups).to.have.a.lengthOf(3); + + done(); + }).catch(done); + }); + }); + + context('guilds passed in as query', () => { + + it('returns all guilds user is a part of ', (done) => { + api.get('/groups', null, {type: 'guilds'}).then((groups) => { + expect(groups).to.have.a.lengthOf(2); + + done(); + }).catch(done); + }); + }); +}); From 1417d643e48475297f95202e947bc7cda7b48993 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 18 Oct 2015 10:14:54 -0500 Subject: [PATCH 36/53] Comment out content test until we know for sure what we're doing with the content files --- tasks/gulp-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index fc03660248..3cada7842a 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -336,7 +336,7 @@ gulp.task('test:api:safe', ['test:prepare:mongo'], (done) => { gulp.task('test', [ 'test:common:safe', - 'test:content:safe', + // 'test:content:safe', 'test:server_side:safe', 'test:karma:safe', // 'test:api-legacy:safe', From a0e7eef956723f3b8a81a7ac776854bf23891bbb Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 20 Oct 2015 20:17:10 -0500 Subject: [PATCH 37/53] Fix legacy tests --- package.json | 2 +- tasks/gulp-tests.js | 2 +- test/api-legacy/anonymized.coffee | 2 +- test/api-legacy/api-helper.coffee | 4 +- test/api-legacy/challenges.coffee | 54 +++++++++---------- test/api-legacy/chat.coffee | 26 +++++----- test/api-legacy/coupons.coffee | 18 +++---- test/api-legacy/groups.coffee | 66 ++++++++++++------------ test/api-legacy/party.coffee | 56 ++++++++++---------- test/api-legacy/pushNotifications.coffee | 2 +- test/api-legacy/score.coffee | 36 ++++++------- test/api-legacy/todos.coffee | 24 ++++----- test/api-legacy/users.coffee | 42 +++++++-------- test/mocha.opts | 2 + 14 files changed, 169 insertions(+), 167 deletions(-) diff --git a/package.json b/package.json index a14173614d..56fa6cdd6c 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "shelljs": "^0.4.0", "sinon": "1.15.4", "sinon-chai": "^2.7.0", - "superagent-defaults": "~0.1.5", + "superagent-defaults": "^0.1.13", "uuid": "^2.0.1", "vinyl-source-stream": "^1.0.0", "vinyl-transform": "^1.0.0" diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index 3cada7842a..091c5fd5bd 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -339,7 +339,7 @@ gulp.task('test', [ // 'test:content:safe', 'test:server_side:safe', 'test:karma:safe', - // 'test:api-legacy:safe', + 'test:api-legacy:safe', 'test:api:safe', 'test:e2e:safe' ], () => { diff --git a/test/api-legacy/anonymized.coffee b/test/api-legacy/anonymized.coffee index 5532a8c472..c570229069 100644 --- a/test/api-legacy/anonymized.coffee +++ b/test/api-legacy/anonymized.coffee @@ -10,7 +10,7 @@ describe "GET /api/v2/user/anonymized", -> # TODO: Seed user with messages, rewards, dailys, checklists, webhooks, etc registerNewUser -> request.get(baseURL + "/user/anonymized") - .end (res) -> + .end (err, res) -> anon = res.body done() , true diff --git a/test/api-legacy/api-helper.coffee b/test/api-legacy/api-helper.coffee index 0c3ae7b580..3c4ed36df2 100644 --- a/test/api-legacy/api-helper.coffee +++ b/test/api-legacy/api-helper.coffee @@ -26,7 +26,7 @@ conf.set "PORT", "1337" ############################## # Node ENV and global variables ############################## -process.env.NODE_DB_URI = "mongodb://localhost/habitrpg_test" +process.env.NODE_DB_URI = "mongodb://localhost/habitrpg_test_api_legacy" global.baseURL = "http://localhost:" + conf.get("PORT") + "/api/v2" global.user = undefined @@ -51,7 +51,7 @@ global.registerNewUser = (cb, main) -> password: randomID confirmPassword: randomID email: randomID + "@gmail.com" - .end (res) -> + .end (err, res) -> return cb(null, res.body) unless main _id = res.body._id apiToken = res.body.apiToken diff --git a/test/api-legacy/challenges.coffee b/test/api-legacy/challenges.coffee index ad4172c30a..8fa3afe9ce 100644 --- a/test/api-legacy/challenges.coffee +++ b/test/api-legacy/challenges.coffee @@ -18,7 +18,7 @@ describe "Challenges", -> request.post(baseURL + "/groups").send( name: "TestGroup" type: "party" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 group = res.body expect(group.members.length).to.equal 1 @@ -38,7 +38,7 @@ describe "Challenges", -> }] rewards: [] habits: [] - ).end (res) -> + ).end (err, res) -> challenge = res.body done() ] @@ -64,7 +64,7 @@ describe "Challenges", -> rewards: [] habits: [] official: true - ).end (res) -> + ).end (err, res) -> expectCode res, 200 async.parallel [ (cb) -> @@ -84,7 +84,7 @@ describe "Challenges", -> updateTodo.notes = "User overriden notes" async.waterfall [ (cb) -> - request.put(baseURL + "/user/tasks/" + updateTodo.id).send(updateTodo).end (res) -> + request.put(baseURL + "/user/tasks/" + updateTodo.id).send(updateTodo).end (err, res) -> cb() , (cb) -> Challenge.findById challenge._id, cb @@ -93,7 +93,7 @@ describe "Challenges", -> cb() , (cb) -> request.get(baseURL + "/user/tasks/" + updateTodo.id) - .end (res) -> + .end (err, res) -> expect(res.body.notes).to.eql("User overriden notes") done() ] @@ -102,7 +102,7 @@ describe "Challenges", -> challenge.dailys[0].text = "Updated Daily" request.post(baseURL + "/challenges/" + challenge._id) .send(challenge) - .end (res) -> + .end (err, res) -> challenge = res.body expect(challenge.dailys[0].text).to.equal "Updated Daily" User.findById user._id, (err, _user) -> @@ -114,7 +114,7 @@ describe "Challenges", -> challenge.todos[0].notes = "Challenge Updated Todo Notes" request.post(baseURL + "/challenges/" + challenge._id) .send(challenge) - .end (res) -> + .end (err, res) -> challenge = res.body expect(challenge.todos[0].notes).to.equal "Challenge Updated Todo Notes" User.findById user._id, (err, _user) -> @@ -128,7 +128,7 @@ describe "Challenges", -> updateTodo.notes = "User overriden notes" async.waterfall [ (cb) -> - request.put(baseURL + "/user/tasks/" + updateTodo.id).send(updateTodo).end (res) -> + request.put(baseURL + "/user/tasks/" + updateTodo.id).send(updateTodo).end (err, res) -> cb() , (cb) -> Challenge.findById challenge._id, cb @@ -136,7 +136,7 @@ describe "Challenges", -> expect(chal.todos[0].notes).to.eql("Challenge Notes") cb() , (cb) -> - request.get(baseURL + "/challenges/" + challenge._id + "/member/" + user._id).end (res) -> + request.get(baseURL + "/challenges/" + challenge._id + "/member/" + user._id).end (err, res) -> expect(res.body.todos[res.body.todos.length - 1].notes).to.equal "User overriden notes" done() ] @@ -145,14 +145,14 @@ describe "Challenges", -> User.findById user._id, (err, _user) -> u = _user numTasks = (_.size(u.todos)) - request.post(baseURL + "/user/tasks/" + u.todos[0].id + "/up").end (res) -> - request.post(baseURL + "/user/tasks/clear-completed").end (res) -> + request.post(baseURL + "/user/tasks/" + u.todos[0].id + "/up").end (err, res) -> + request.post(baseURL + "/user/tasks/clear-completed").end (err, res) -> expect(_.size(res.body)).to.equal numTasks - 1 done() it "Challenge deleted, breaks task link", (done) -> itThis = this - request.del(baseURL + "/challenges/" + challenge._id).end (res) -> + request.del(baseURL + "/challenges/" + challenge._id).end (err, res) -> User.findById user._id, (err, user) -> len = user.dailys.length - 1 daily = user.dailys[user.dailys.length - 1] @@ -164,7 +164,7 @@ describe "Challenges", -> User.findByIdAndUpdate user._id, unset, (err, user) -> expect(err).to.not.exist expect(user.dailys[len].challenge.broken).to.not.exist - request.post(baseURL + "/user/tasks/" + daily.id + "/up").end (res) -> + request.post(baseURL + "/user/tasks/" + daily.id + "/up").end (err, res) -> setTimeout (-> User.findById user._id, (err, user) -> expect(user.dailys[len].challenge.broken).to.equal "CHALLENGE_DELETED" @@ -186,7 +186,7 @@ describe "Challenges", -> rewards: [] habits: [] official: false - ).end (res) -> + ).end (err, res) -> expect(res.body.official).to.equal false cb() (cb) -> @@ -197,7 +197,7 @@ describe "Challenges", -> rewards: [] habits: [] official: true - ).end (res) -> + ).end (err, res) -> expect(res.body.official).to.equal true cb() ], done @@ -215,7 +215,7 @@ describe "Challenges", -> rewards: [] habits: [] prize: 10 - ).end (res) -> + ).end (err, res) -> expect(res.body.prize).to.equal 10 async.parallel [ (cb) -> @@ -226,7 +226,7 @@ describe "Challenges", -> user = results[0] challenge = results[1] expect(user.balance).to.equal 5.5 - request.del(baseURL + "/challenges/" + challenge._id).end (res) -> + request.del(baseURL + "/challenges/" + challenge._id).end (err, res) -> User.findById user._id, (err, _user) -> expect(_user.balance).to.equal 8 done() @@ -244,7 +244,7 @@ describe "Challenges", -> rewards: [] habits: [] prize: 10 - ).end (res) -> + ).end (err, res) -> expect(res.body.prize).to.equal 10 async.parallel [ (cb) -> @@ -255,7 +255,7 @@ describe "Challenges", -> user = results[0] challenge = results[1] expect(user.balance).to.equal 5.5 - request.del(baseURL + "/challenges/" + challenge._id).end (res) -> + request.del(baseURL + "/challenges/" + challenge._id).end (err, res) -> User.findById user._id, (err, _user) -> expect(_user.balance).to.equal 5.5 done() @@ -273,7 +273,7 @@ describe "Challenges", -> type: "daily" text: "Challenge Daily" ] - ).end (res) -> + ).end (err, res) -> challenge = res.body cb() @@ -287,7 +287,7 @@ describe "Challenges", -> challenge.name = 'foobar' request.post(baseURL + "/challenges/" + challenge._id) .send(challenge) - .end (res) -> + .end (err, res) -> error = res.body.err expect(error).to.eql("You don't have permissions to edit this challenge") @@ -295,7 +295,7 @@ describe "Challenges", -> it 'can not close challenge', (done) -> request.post(baseURL + "/challenges/" + challenge._id + "/close?uid=" + user._id) - .end (res) -> + .end (err, res) -> error = res.body.err expect(error).to.eql("You don't have permissions to close this challenge") @@ -303,7 +303,7 @@ describe "Challenges", -> it 'can not delete challenge', (done) -> request.del(baseURL + "/challenges/" + challenge._id) - .end (res) -> + .end (err, res) -> error = res.body.err expect(error).to.eql("You don't have permissions to delete this challenge") @@ -318,7 +318,7 @@ describe "Challenges", -> challenge.name = 'foobar' request.post(baseURL + "/challenges/" + challenge._id) .send(challenge) - .end (res) -> + .end (err, res) -> expect(res.body.err).to.not.exist Challenge.findById challenge._id, (err, chal) -> expect(chal.name).to.eql('foobar') @@ -326,7 +326,7 @@ describe "Challenges", -> it 'can close challenge', (done) -> request.post(baseURL + "/challenges/" + challenge._id + "/close?uid=" + user._id) - .end (res) -> + .end (err, res) -> expect(res.body.err).to.not.exist User.findById user._id, (err, usr) -> expect(usr.achievements.challenges[0]).to.eql(challenge.name) @@ -334,10 +334,10 @@ describe "Challenges", -> it 'can delete challenge', (done) -> request.del(baseURL + "/challenges/" + challenge._id) - .end (res) -> + .end (err, res) -> expect(res.body.err).to.not.exist request.get(baseURL + "/challenges/" + challenge._id) - .end (res) -> + .end (err, res) -> error = res.body.err expect(error).to.eql("Challenge #{challenge._id} not found") done() diff --git a/test/api-legacy/chat.coffee b/test/api-legacy/chat.coffee index 38c1254a00..d480f75c6d 100644 --- a/test/api-legacy/chat.coffee +++ b/test/api-legacy/chat.coffee @@ -16,7 +16,7 @@ describe "Chat", -> request.post(baseURL + "/groups").send( name: "TestGroup" type: "party" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 group = res.body expect(group.members.length).to.equal 1 @@ -28,7 +28,7 @@ describe "Chat", -> chat = undefined it "posts a message to party chat", (done) -> msg = "TestMsg" - request.post(baseURL + "/groups/" + group._id + "/chat?message=" + msg).end (res) -> + request.post(baseURL + "/groups/" + group._id + "/chat?message=" + msg).end (err, res) -> expectCode res, 200 chat = res.body.message expect(chat.id).to.be.ok @@ -47,14 +47,14 @@ describe "Chat", -> it "does not post an empty message", (done) -> msg = "" request.post(baseURL + "/groups/" + group._id + "/chat?message=" + msg).send( - ).end (res) -> + ).end (err, res) -> expectCode res, 400 expect(res.body.err).to.equal 'You cannot send a blank message' done() it "can not like own chat message", (done) -> request.post(baseURL + "/groups/" + group._id + "/chat/" + chat.id + "/like").send( - ).end (res) -> + ).end (err, res) -> expectCode res, 401 body = res.body expect(body.err).to.equal "Can't like your own message. Don't be that person." @@ -62,7 +62,7 @@ describe "Chat", -> it "can not flag own message", (done) -> request.post(baseURL + "/groups/" + group._id + "/chat/" + chat.id + "/flag").send( - ).end (res) -> + ).end (err, res) -> expectCode res, 401 body = res.body expect(body.err).to.equal "Can't report your own message." @@ -70,7 +70,7 @@ describe "Chat", -> it "gets chat messages from party chat", (done) -> request.get(baseURL + "/groups/" + group._id + "/chat").send( - ).end (res) -> + ).end (err, res) -> expectCode res, 200 message = res.body[0] expect(message.id).to.equal chat.id @@ -86,14 +86,14 @@ describe "Chat", -> it "deletes a chat messages from party chat", (done) -> request.del(baseURL + "/groups/" + group._id + "/chat/" + chat.id).send( - ).end (res) -> + ).end (err, res) -> expectCode res, 204 expect(res.body).to.be.empty done() it "can not delete already deleted message", (done) -> request.del(baseURL + "/groups/" + group._id + "/chat/" + chat.id).send( - ).end (res) -> + ).end (err, res) -> expectCode res, 404 body = res.body expect(body.err).to.equal "Message not found!" @@ -116,30 +116,30 @@ describe "Chat", -> request.post(baseURL + "/groups/" + group._id + "/join") .set("X-API-User", userToRemove._id) .set("X-API-Key", userToRemove.apiToken) - .end (res) -> cb() + .end (err, res) -> cb() (cb) -> msg = "TestMsg" request.post(baseURL + "/groups/" + group._id + "/chat?message=" + msg) - .end (res) -> cb() + .end (err, res) -> cb() (cb) -> request.get(baseURL + "/user") .set("X-API-User", userToRemove._id) .set("X-API-Key", userToRemove.apiToken) - .end (res) -> + .end (err, res) -> expect(res.body.newMessages[group._id]).to.exist cb() (cb) -> request.post(baseURL + "/groups/" + group._id + "/removeMember?uuid=" + userToRemove._id) - .end (res) -> cb() + .end (err, res) -> cb() (cb) -> request.get(baseURL + "/user") .set("X-API-User", userToRemove._id) .set("X-API-Key", userToRemove.apiToken) - .end (res) -> + .end (err, res) -> expect(res.body.newMessages[group._id]).to.not.exist cb() ], done diff --git a/test/api-legacy/coupons.coffee b/test/api-legacy/coupons.coffee index 4a0635aa9c..c6fb4f36d7 100644 --- a/test/api-legacy/coupons.coffee +++ b/test/api-legacy/coupons.coffee @@ -34,7 +34,7 @@ describe "Coupons", -> queries = '?count=10' request .post(baseURL + '/coupons/generate/wondercon' + queries) - .end (res) -> + .end (err, res) -> expectCode res, 200 Coupon.find { event: 'wondercon' }, (err, _coupons) -> coupons = _coupons @@ -52,7 +52,7 @@ describe "Coupons", -> queries = '?count=10' request .post(baseURL + '/coupons/generate/wondercon' + queries) - .end (res) -> + .end (err, res) -> expectCode res, 401 expect(res.body.err).to.equal 'You don\'t have admin access' done() @@ -68,7 +68,7 @@ describe "Coupons", -> queries = '?_id=' + user._id + '&apiToken=' + user.apiToken request .get(baseURL + '/coupons' + queries) - .end (res) -> + .end (err, res) -> expectCode res, 200 codes = res.text expect(codes).to.contain('code') @@ -81,7 +81,7 @@ describe "Coupons", -> queries = '?_id=' + user._id + '&apiToken=' + user.apiToken + '&limit=5' request .get(baseURL + '/coupons' + queries) - .end (res) -> + .end (err, res) -> expectCode res, 200 codes = res.text sortedCoupons = _.sortBy(coupons, 'seq') @@ -98,7 +98,7 @@ describe "Coupons", -> queries = '?_id=' + user._id + '&apiToken=' + user.apiToken + '&skip=5' request .get(baseURL + '/coupons' + queries) - .end (res) -> + .end (err, res) -> expectCode res, 200 codes = res.text sortedCoupons = _.sortBy(coupons, 'seq') @@ -121,7 +121,7 @@ describe "Coupons", -> queries = '?_id=' + user._id + '&apiToken=' + user.apiToken request .get(baseURL + '/coupons' + queries) - .end (res) -> + .end (err, res) -> expectCode res, 401 expect(res.body.err).to.equal 'You don\'t have admin access' done() @@ -156,7 +156,7 @@ describe "Coupons", -> code = coupons[0]._id request .post(baseURL + '/user/coupon/' + code) - .end (res) -> + .end (err, res) -> expectCode res, 200 gear = res.body.items.gear.owned specialGear(gear, true) @@ -168,7 +168,7 @@ describe "Coupons", -> code = coupons[0]._id request .post(baseURL + '/user/coupon/' + code) - .end (res) -> + .end (err, res) -> expectCode res, 400 expect(res.body.err).to.equal "Coupon already used" User.findById user._id, (err, _user) -> @@ -182,7 +182,7 @@ describe "Coupons", -> code = "not-a-real-coupon" request .post(baseURL + '/user/coupon/' + code) - .end (res) -> + .end (err, res) -> expectCode res, 400 expect(res.body.err).to.equal "Invalid coupon code" User.findById user._id, (err, _user) -> diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index 4e6a92aa76..209b14e5cd 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -5,7 +5,7 @@ diff = require("deep-diff") Group = require("../../website/src/models/group").model app = require("../../website/src/server") -describe "Guilds", -> +describe.skip "Guilds", -> context "updating groups", -> groupToUpdate = undefined before (done) -> @@ -13,7 +13,7 @@ describe "Guilds", -> name: "TestGroup" type: "guild" description: "notUpdatedDesc" - ).end (res) -> + ).end (err, res) -> groupToUpdate = res.body done() @@ -25,7 +25,7 @@ describe "Guilds", -> ) .set("X-API-User", tmpUser._id) .set("X-API-Key", tmpUser.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 401 expect(res.body.err).to.equal "Only the group leader can update the group!" done() @@ -35,10 +35,10 @@ describe "Guilds", -> request.post(baseURL + "/groups/" + groupToUpdate._id).send( description: "updatedDesc" ) - .end (res) -> + .end (err, res) -> expectCode res, 204 request.get(baseURL + "/groups/" + groupToUpdate._id).send() - .end (res) -> + .end (err, res) -> updatedGroup = res.body expect(updatedGroup.description).to.equal "updatedDesc" done() @@ -49,11 +49,11 @@ describe "Guilds", -> request.post(baseURL + "/groups").send( name: "TestGroupToLeave" type: "guild" - ).end (res) -> + ).end (err, res) -> guildToLeave = res.body request.post(baseURL + "/groups/" + guildToLeave._id + "/leave") .send() - .end (res) -> + .end (err, res) -> expectCode res, 204 done() @@ -63,18 +63,18 @@ describe "Guilds", -> name: "TestGroupToDeleteAfteLeave" type: "guild" privacy: "private" - ).end (res) -> + ).end (err, res) -> groupToDeleteAfterLeave = res.body async.waterfall [ (cb) -> request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id + "/leave") - .end (res) -> + .end (err, res) -> expectCode res, 204 cb() (cb) -> request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id) - .end (res) -> + .end (err, res) -> expectCode res, 404 cb() ], done @@ -86,7 +86,7 @@ describe "Guilds", -> name: "TestGroupToDeleteAfterLeave" type: "guild" privacy: "private" - ).end (res) -> + ).end (err, res) -> groupToDeleteAfterLeave = res.body async.waterfall [ (cb) -> @@ -103,7 +103,7 @@ describe "Guilds", -> (cb) -> request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id + "/leave") - .end (res) -> + .end (err, res) -> expectCode res, 204 cb() @@ -119,7 +119,7 @@ describe "Guilds", -> (cb) -> request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id) - .end (res) -> + .end (err, res) -> expectCode res, 404 cb() ], done @@ -130,7 +130,7 @@ describe "Guilds", -> request.post(baseURL + "/groups").send( name: "TestPartyToDeleteAfterLeave" type: "party" - ).end (res) -> + ).end (err, res) -> partyToDeleteAfterLeave = res.body async.waterfall [ (cb) -> @@ -147,7 +147,7 @@ describe "Guilds", -> (cb) -> request.post(baseURL + "/groups/" + partyToDeleteAfterLeave._id + "/leave") - .end (res) -> + .end (err, res) -> expectCode res, 204 cb() @@ -166,7 +166,7 @@ describe "Guilds", -> (cb) -> request.post(baseURL + "/groups/" + partyToDeleteAfterLeave._id) - .end (res) -> + .end (err, res) -> expectCode res, 404 cb() ], done @@ -179,7 +179,7 @@ describe "Guilds", -> request.post(baseURL + "/groups").send( name: "TestGuildToRemoveMember" type: "guild" - ).end (res) -> + ).end (err, res) -> guildToRemoveMember = res.body #Add members to guild async.waterfall [ @@ -200,24 +200,24 @@ describe "Guilds", -> request.post(baseURL + "/groups/" + guildToRemoveMember._id + "/join") .set("X-API-User", userToRemove._id) .set("X-API-Key", userToRemove.apiToken) - .end (res) -> + .end (err, res) -> cb() (cb) -> request.post(baseURL + "/groups/" + guildToRemoveMember._id + "/removeMember?uuid=" + guildToRemoveMember.leader) - .send().end (res) -> + .send().end (err, res) -> expectCode res, 401 cb() (cb) -> request.post(baseURL + "/groups/" + guildToRemoveMember._id + "/removeMember?uuid=" + userToRemove._id) - .send().end (res) -> + .send().end (err, res) -> expectCode res, 204 cb() (cb) -> request.get(baseURL + "/groups/" + guildToRemoveMember._id) .send() - .end (res) -> + .end (err, res) -> g = res.body userInGroup = _.find g.members, (member) -> return member._id == userToRemove._id expect(userInGroup).to.not.exist @@ -232,7 +232,7 @@ describe "Guilds", -> name: "TestPrivateGroup" type: "guild" privacy: "private" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 guild = res.body expect(guild.members.length).to.equal 1 @@ -259,7 +259,7 @@ describe "Guilds", -> it "includes user in private group member list when user is a member", (done) -> request.get(baseURL + "/groups/" + guild._id) - .end (res) -> + .end (err, res) -> g = res.body userInGroup = _.find g.members, (member) -> return member._id == user._id expect(userInGroup).to.exist @@ -268,9 +268,9 @@ describe "Guilds", -> it "excludes user from viewing private group member list when user is not a member", (done) -> request.post(baseURL + "/groups/" + guild._id + "/leave") - .end (res) -> + .end (err, res) -> request.get(baseURL + "/groups/" + guild._id) - .end (res) -> + .end (err, res) -> expect res, 404 done() @@ -293,7 +293,7 @@ describe "Guilds", -> name: "TestGuildToEmptyAndAssignLeader" type: "guild", privacy: "public" - ).end (res) -> + ).end (err, res) -> guildToEmptyAndAssignLeader = res.body #Add members to guild async.waterfall [ @@ -313,7 +313,7 @@ describe "Guilds", -> (cb) -> request.post(baseURL + "/groups/" + guildToEmptyAndAssignLeader._id + "/leave") .send() - .end (res) -> + .end (err, res) -> expectCode res, 204 cb() @@ -321,7 +321,7 @@ describe "Guilds", -> request.post(baseURL + "/groups/" + guildToEmptyAndAssignLeader._id + "/join") .set("X-API-User", userToBecomeLeader._id) .set("X-API-Key", userToBecomeLeader.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -330,7 +330,7 @@ describe "Guilds", -> .set("X-API-User", userToBecomeLeader._id) .set("X-API-Key", userToBecomeLeader.apiToken) .send() - .end (res) -> + .end (err, res) -> expectCode res, 200 g = res.body expect(g.leader._id).to.equal(userToBecomeLeader._id) @@ -352,7 +352,7 @@ describe "Guilds", -> name: "TestPublicGroup" type: "guild" privacy: "public" - ).end (res) -> + ).end (err, res) -> guild = res.body expect(guild.members.length).to.equal 1 expect(guild.leader).to.equal user._id @@ -380,13 +380,13 @@ describe "Guilds", -> before (done) -> registerNewUser -> request.post(baseURL + "/groups/" + guild._id + "/join") - .end (res)-> + .end (err, res)-> done() , true it "includes user in public group member list", (done) -> request.get(baseURL + "/groups/" + guild._id) - .end (res) -> + .end (err, res) -> g = res.body expect(g.members.length).to.equal 15 userInGroup = _.find g.members, (member) -> return member._id == user._id @@ -399,7 +399,7 @@ describe "Guilds", -> it "excludes user in public group member list", (done) -> request.get(baseURL + "/groups/" + guild._id) - .end (res) -> + .end (err, res) -> g = res.body expect(g.members.length).to.equal 15 userInGroup = _.find g.members, (member) -> return member._id == user._id diff --git a/test/api-legacy/party.coffee b/test/api-legacy/party.coffee index 2a8b54801a..3e46328991 100644 --- a/test/api-legacy/party.coffee +++ b/test/api-legacy/party.coffee @@ -16,7 +16,7 @@ describe "Party", -> request.post(baseURL + "/groups").send( name: "TestGroup" type: "party" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 group = res.body expect(group.members.length).to.equal 1 @@ -28,7 +28,7 @@ describe "Party", -> request.post(baseURL + "/groups").send( name: "TestGroup" type: "party" - ).end (res) -> + ).end (err, res) -> expectCode res, 400 expect(res.body.err).to.equal "Already in a party, try refreshing." done() @@ -44,7 +44,7 @@ describe "Party", -> request.post(baseURL + "/groups").send( name: "TestGroup" type: "party" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 group = res.body expect(group.members.length).to.equal 1 @@ -55,7 +55,7 @@ describe "Party", -> it "can be found by querying for group type party", (done) -> request.get(baseURL + "/groups/").send( type: "party" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 party = _.find res.body, (g) -> return g._id == group._id expect(party._id).to.equal group._id @@ -76,7 +76,7 @@ describe "Party", -> request.post(baseURL + "/groups").send( name: "TestGroup" type: "party" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 group = res.body expect(group.members.length).to.equal 1 @@ -89,7 +89,7 @@ describe "Party", -> request.post(baseURL + "/groups/" + group._id + "/join").send() .set("X-API-User", user._id) .set("X-API-Key", user.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 401 expect(res.body.err).to.equal "Can't join a group you're not invited to." done() @@ -114,7 +114,7 @@ describe "Party", -> request.post(baseURL + "/groups/" + group._id + "/join") .set("X-API-User", tmpUser._id) .set("X-API-Key", tmpUser.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -153,7 +153,7 @@ describe "Party", -> request.post(baseURL + "/groups").send( name: "TestGroup" type: "party" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 group = res.body expect(group.members.length).to.equal 1 @@ -164,13 +164,13 @@ describe "Party", -> request.post(baseURL + '/user/tasks').send({ type: 'daily' text: 'daily one' - }).end (res) -> + }).end (err, res) -> cb() (cb) -> request.post(baseURL + '/user/tasks').send({ type: 'daily' text: 'daily two' - }).end (res) -> + }).end (err, res) -> cb() (cb) -> User.findByIdAndUpdate user._id, @@ -198,7 +198,7 @@ describe "Party", -> body: "stats.lvl": 50 } - ]).end (res) -> + ]).end (err, res) -> user = res.body expect(user.party.quest.progress.up).to.be.above 0 @@ -227,7 +227,7 @@ describe "Party", -> (cb2) -> request.post(inviteURL).send( uuids: [party[2]._id] - ).end (res)-> + ).end (err, res)-> cb2() ], cb @@ -255,7 +255,7 @@ describe "Party", -> # Start the quest async.waterfall [ (cb) -> - request.post(baseURL + "/groups/" + group._id + "/questAccept?key=vice3").end (res) -> + request.post(baseURL + "/groups/" + group._id + "/questAccept?key=vice3").end (err, res) -> expectCode res, 400 User.findByIdAndUpdate user._id, $set: @@ -263,7 +263,7 @@ describe "Party", -> , cb (_user, cb) -> - request.post(baseURL + "/groups/" + group._id + "/questAccept?key=vice3").end (res) -> + request.post(baseURL + "/groups/" + group._id + "/questAccept?key=vice3").end (err, res) -> expectCode res, 200 Group.findById group._id, cb @@ -271,8 +271,8 @@ describe "Party", -> expect(_group.quest.key).to.equal "vice3" expect(_group.quest.active).to.equal false request.post(baseURL + "/groups/" + group._id + "/questAccept").set("X-API-User", party[0]._id).set("X-API-Key", party[0].apiToken).end -> - request.post(baseURL + "/groups/" + group._id + "/questAccept").set("X-API-User", party[1]._id).set("X-API-Key", party[1].apiToken).end (res) -> - request.post(baseURL + "/groups/" + group._id + "/questReject").set("X-API-User", party[2]._id).set("X-API-Key", party[2].apiToken).end (res) -> + request.post(baseURL + "/groups/" + group._id + "/questAccept").set("X-API-User", party[1]._id).set("X-API-Key", party[1].apiToken).end (err, res) -> + request.post(baseURL + "/groups/" + group._id + "/questReject").set("X-API-User", party[2]._id).set("X-API-Key", party[2].apiToken).end (err, res) -> group = res.body expect(group.quest.active).to.equal true cb() @@ -282,12 +282,12 @@ describe "Party", -> it "Casts a spell", (done) -> mp = user.stats.mp - request.get(baseURL + "/members/" + party[0]._id).end (res) -> + request.get(baseURL + "/members/" + party[0]._id).end (err, res) -> party[0] = res.body - request.post(baseURL + "/user/class/cast/snowball?targetType=user&targetId=" + party[0]._id).end (res) -> + request.post(baseURL + "/user/class/cast/snowball?targetType=user&targetId=" + party[0]._id).end (err, res) -> #expect(res.body.stats.mp).to.be.below(mp); - request.get(baseURL + "/members/" + party[0]._id).end (res) -> + request.get(baseURL + "/members/" + party[0]._id).end (err, res) -> member = res.body expect(member.achievements.snowball).to.equal 1 expect(member.stats.buffs.snowball).to.exist @@ -295,18 +295,18 @@ describe "Party", -> expect(_.size(difference)).to.equal 2 # level up user so str is > 0 - request.put(baseURL + "/user").send("stats.lvl": 5).end (res) -> + request.put(baseURL + "/user").send("stats.lvl": 5).end (err, res) -> # Refill mana so user can cast - request.put(baseURL + "/user").send("stats.mp": 100).end (res) -> - request.post(baseURL + "/user/class/cast/valorousPresence?targetType=party").end (res) -> - request.get(baseURL + "/members/" + member._id).end (res) -> + request.put(baseURL + "/user").send("stats.mp": 100).end (err, res) -> + request.post(baseURL + "/user/class/cast/valorousPresence?targetType=party").end (err, res) -> + request.get(baseURL + "/members/" + member._id).end (err, res) -> expect(res.body.stats.buffs.str).to.be.above 0 expect(diff(res.body, member).length).to.equal 1 done() it "Doesn't include people who aren't participating", (done) -> - request.get(baseURL + "/groups/" + group._id).end (res) -> + request.get(baseURL + "/groups/" + group._id).end (err, res) -> expect(_.size(res.body.quest.members)).to.equal 3 done() @@ -325,7 +325,7 @@ describe "Party", -> done() xit "Hurts the boss", (done) -> - request.post(baseURL + "/user/batch-update").end (res) -> + request.post(baseURL + "/user/batch-update").end (err, res) -> user = res.body up = user.party.quest.progress.up expect(up).to.be.above 0 @@ -344,10 +344,10 @@ describe "Party", -> body: lastCron: moment().subtract(1, "days") } - ]).end (res) -> + ]).end (err, res) -> expect(res.body.party.quest.progress.up).to.be.above up request.post(baseURL + "/user/batch-update").end -> - request.get(baseURL + "/groups/party").end (res) -> + request.get(baseURL + "/groups/party").end (err, res) -> # Check boss damage async.waterfall [ @@ -419,7 +419,7 @@ describe "Party", -> cb() (cb) -> - request.post(baseURL + "/user/batch-update").end (res) -> + request.post(baseURL + "/user/batch-update").end (err, res) -> cb null, res.body (_user, cb) -> diff --git a/test/api-legacy/pushNotifications.coffee b/test/api-legacy/pushNotifications.coffee index d7c23ce47c..803e3fee0f 100644 --- a/test/api-legacy/pushNotifications.coffee +++ b/test/api-legacy/pushNotifications.coffee @@ -15,7 +15,7 @@ describe "Push-Notifications", -> it "Registers a DeviceID", (done) -> request.post(baseURL + "/user/pushDevice").send( { regId: "123123", type: "android"} - ).end (res) -> + ).end (err, res) -> expectCode res, 200 User.findOne diff --git a/test/api-legacy/score.coffee b/test/api-legacy/score.coffee index a3b1b41826..57e455f068 100644 --- a/test/api-legacy/score.coffee +++ b/test/api-legacy/score.coffee @@ -11,9 +11,9 @@ describe "Score", -> request.post(baseURL + "/user/tasks/withUp/up").send( type: "todo" text: "withUp" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 - request.get(baseURL + "/user/tasks/withUp").end (res) -> + request.get(baseURL + "/user/tasks/withUp").end (err, res) -> upTodo = res.body expect(upTodo.completed).to.equal true done() @@ -22,9 +22,9 @@ describe "Score", -> request.post(baseURL + "/user/tasks/withDown/down").send( type: "todo" text: "withDown" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 - request.get(baseURL + "/user/tasks/withDown").end (res) -> + request.get(baseURL + "/user/tasks/withDown").end (err, res) -> downTodo = res.body expect(downTodo.completed).to.equal false done() @@ -34,9 +34,9 @@ describe "Score", -> type: "todo" text: "withUpWithComplete" completed: false - ).end (res) -> + ).end (err, res) -> expectCode res, 200 - request.get(baseURL + "/user/tasks/withUpWithComplete").end (res) -> + request.get(baseURL + "/user/tasks/withUpWithComplete").end (err, res) -> upTodo = res.body expect(upTodo.completed).to.equal true done() @@ -46,9 +46,9 @@ describe "Score", -> type: "todo" text: "withDownWithUncomplete" completed: true - ).end (res) -> + ).end (err, res) -> expectCode res, 200 - request.get(baseURL + "/user/tasks/withDownWithUncomplete").end (res) -> + request.get(baseURL + "/user/tasks/withDownWithUncomplete").end (err, res) -> downTodo = res.body expect(downTodo.completed).to.equal false done() @@ -58,13 +58,13 @@ describe "Score", -> request.post(baseURL + "/user/tasks").send( type: "todo" text: "Sample Todo" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 unCompletedTodo = res.body expect(unCompletedTodo.completed).to.equal false - request.post(baseURL + "/user/tasks/"+unCompletedTodo._id+"/up").end (res) -> + request.post(baseURL + "/user/tasks/"+unCompletedTodo._id+"/up").end (err, res) -> expectCode res, 200 - request.get(baseURL + "/user/tasks/"+unCompletedTodo._id).end (res) -> + request.get(baseURL + "/user/tasks/"+unCompletedTodo._id).end (err, res) -> unCompletedTodo = res.body expect(unCompletedTodo.completed).to.equal true done() @@ -74,13 +74,13 @@ describe "Score", -> type: "todo" text: "Sample Todo" completed: true - ).end (res) -> + ).end (err, res) -> expectCode res, 200 completedTodo = res.body expect(completedTodo.completed).to.equal true - request.post(baseURL + "/user/tasks/"+completedTodo._id+"/down").end (res) -> + request.post(baseURL + "/user/tasks/"+completedTodo._id+"/down").end (err, res) -> expectCode res, 200 - request.get(baseURL + "/user/tasks/"+completedTodo._id).end (res) -> + request.get(baseURL + "/user/tasks/"+completedTodo._id).end (err, res) -> completedTodo = res.body expect(completedTodo.completed).to.equal false done() @@ -91,9 +91,9 @@ describe "Score", -> type: "habit" text: "testTitle" completed: true - ).end (res) -> + ).end (err, res) -> expectCode res, 200 - request.get(baseURL + "/user/tasks/habitWithUp").end (res) -> + request.get(baseURL + "/user/tasks/habitWithUp").end (err, res) -> upHabit = res.body expect(upHabit.value).to.be.at.least(1) expect(upHabit.type).to.equal("habit") @@ -105,9 +105,9 @@ describe "Score", -> type: "habit" text: "testTitle" completed: true - ).end (res) -> + ).end (err, res) -> expectCode res, 200 - request.get(baseURL + "/user/tasks/habitWithDown").end (res) -> + request.get(baseURL + "/user/tasks/habitWithDown").end (err, res) -> downHabit = res.body expect(downHabit.value).to.have.at.most(-1) expect(downHabit.type).to.equal("habit") diff --git a/test/api-legacy/todos.coffee b/test/api-legacy/todos.coffee index 7b57378bf4..0485266cea 100644 --- a/test/api-legacy/todos.coffee +++ b/test/api-legacy/todos.coffee @@ -31,7 +31,7 @@ describe "Todos", -> body: type: "todo" } - ]).end (res) -> + ]).end (err, res) -> expectCode res, 200 # Expect number of todos to be 3 greater than the number the user started with expect(_.size(res.body.todos)).to.equal numTasks + 3 @@ -56,7 +56,7 @@ describe "Todos", -> direction: "up" id: res.body.todos[2].id } - ]).end (res) -> + ]).end (err, res) -> expectCode res, 200 expect(_.size(res.body.todos)).to.equal numTasks request.post(baseURL + "/user/batch-update?_v=997").send([ @@ -76,7 +76,7 @@ describe "Todos", -> body: dateCompleted: moment().subtract(4, "days") } - ]).end (res) -> + ]).end (err, res) -> # Expect todos to be 2 less than the total count expect(_.size(res.body.todos)).to.equal numTasks - 2 done() @@ -89,7 +89,7 @@ describe "Todos", -> request.post(baseURL + "/user/tasks").send( type: "todo" text: "Sample Todo" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 todo = res.body expect(todo.text).to.equal "Sample Todo" @@ -110,10 +110,10 @@ describe "Todos", -> } request.post(baseURL + "/user/tasks").send( original_todo - ).end (res) -> + ).end (err, res) -> request.post(baseURL + "/user/tasks").send( duplicate_id_todo - ).end (res) -> + ).end (err, res) -> expectCode res, 409 expect(res.body.err).to.eql('A task with that ID already exists.') done() @@ -122,7 +122,7 @@ describe "Todos", -> it "Does not update id of todo", (done) -> request.put(baseURL + "/user/tasks/" + todo.id).send( id: "a-new-id" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 updateTodo = res.body expect(updateTodo.id).to.equal todo.id @@ -131,7 +131,7 @@ describe "Todos", -> it "Does not update type of todo", (done) -> request.put(baseURL + "/user/tasks/" + todo.id).send( type: "habit" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 updateTodo = res.body expect(updateTodo.type).to.equal todo.type @@ -144,7 +144,7 @@ describe "Todos", -> priority: 1.5 value: 5 notes: "Some notes" - ).end (res) -> + ).end (err, res) -> expectCode res, 200 todo = res.body expect(todo.text).to.equal "Changed Title" @@ -157,7 +157,7 @@ describe "Todos", -> describe "Deleting todos", -> it "Does delete todo", (done) -> request.del(baseURL + "/user/tasks/" + todo.id).send( - ).end (res) -> + ).end (err, res) -> expectCode res, 200 body = res.body expect(body).to.be.empty @@ -165,7 +165,7 @@ describe "Todos", -> it "Does not delete already deleted todo", (done) -> request.del(baseURL + "/user/tasks/" + todo.id).send( - ).end (res) -> + ).end (err, res) -> expectCode res, 404 body = res.body expect(body.err).to.equal "Task not found." @@ -178,7 +178,7 @@ describe "Todos", -> priority: 1 value: 4 notes: "Other notes" - ).end (res) -> + ).end (err, res) -> expectCode res, 404 body = res.body expect(body.err).to.equal "Task not found." diff --git a/test/api-legacy/users.coffee b/test/api-legacy/users.coffee index e465d1f3d5..966a6134a2 100644 --- a/test/api-legacy/users.coffee +++ b/test/api-legacy/users.coffee @@ -22,10 +22,10 @@ describe "Users", -> request.del(baseURL + "/user") .set("X-API-User", userToDelete._id) .set("X-API-Key", userToDelete.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 request.get(baseURL + "/user/" + userToDelete._id) - .end (res) -> + .end (err, res) -> expectCode res, 404 cb() @@ -56,7 +56,7 @@ describe "Users", -> ) .set("X-API-User", userToDelete._id) .set("X-API-Key", userToDelete.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 guildToHaveNewLeader = res.body expect(guildToHaveNewLeader.leader).to.eql(userToDelete._id) @@ -66,7 +66,7 @@ describe "Users", -> inviteURL = baseURL + "/groups/" + guildToHaveNewLeader._id + "/invite" request.post(inviteURL) .send( uuids: [userToBecomeLeader._id]) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -74,7 +74,7 @@ describe "Users", -> request.post(baseURL + "/groups/" + guildToHaveNewLeader._id + "/join") .set("X-API-User", userToBecomeLeader._id) .set("X-API-Key", userToBecomeLeader.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -82,7 +82,7 @@ describe "Users", -> request.del(baseURL + "/user") .set("X-API-User", userToDelete._id) .set("X-API-Key", userToDelete.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -90,7 +90,7 @@ describe "Users", -> request.get(baseURL + "/groups/" + guildToHaveNewLeader._id) .set("X-API-User", userToBecomeLeader._id) .set("X-API-Key", userToBecomeLeader.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 g = res.body userInGroup = _.find(g.members, (member) -> return member._id == userToDelete._id; ) @@ -114,7 +114,7 @@ describe "Users", -> name: "TestPrivateGroup" type: "party" ) - .end (res) -> + .end (err, res) -> expectCode res, 200 party = res.body cb() @@ -124,7 +124,7 @@ describe "Users", -> name: "TestPrivateGroup" type: "guild" ) - .end (res) -> + .end (err, res) -> expectCode res, 200 guild = res.body cb() @@ -143,7 +143,7 @@ describe "Users", -> inviteURL = baseURL + "/groups/" + party._id + "/invite" request.post(inviteURL) .send( uuids: [userToDelete._id]) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -151,7 +151,7 @@ describe "Users", -> inviteURL = baseURL + "/groups/" + guild._id + "/invite" request.post(inviteURL) .send( uuids: [userToDelete._id]) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -159,7 +159,7 @@ describe "Users", -> request.post(baseURL + "/groups/" + party._id + "/join") .set("X-API-User", userToDelete._id) .set("X-API-Key", userToDelete.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -167,7 +167,7 @@ describe "Users", -> request.post(baseURL + "/groups/" + guild._id + "/join") .set("X-API-User", userToDelete._id) .set("X-API-Key", userToDelete.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -175,13 +175,13 @@ describe "Users", -> request.del(baseURL + "/user") .set("X-API-User", userToDelete._id) .set("X-API-Key", userToDelete.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() (cb) -> request.get(baseURL + "/groups/" + party._id) - .end (res) -> + .end (err, res) -> expectCode res, 200 g = res.body userInGroup = _.find(g.members, (member) -> return member._id == userToDelete._id; ) @@ -190,7 +190,7 @@ describe "Users", -> (cb) -> request.get(baseURL + "/groups/" + guild._id) - .end (res) -> + .end (err, res) -> expectCode res, 200 g = res.body userInGroup = _.find(g.members, (member) -> return member._id == userToDelete._id; ); @@ -211,7 +211,7 @@ describe "Users", -> inviteURL = baseURL + "/groups/" + party._id + "/invite" request.post(inviteURL) .send( uuids: [userToDeleteInvites._id]) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -219,7 +219,7 @@ describe "Users", -> inviteURL = baseURL + "/groups/" + guild._id + "/invite" request.post(inviteURL) .send( uuids: [userToDeleteInvites._id]) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() @@ -227,13 +227,13 @@ describe "Users", -> request.del(baseURL + "/user") .set("X-API-User", userToDeleteInvites._id) .set("X-API-Key", userToDeleteInvites.apiToken) - .end (res) -> + .end (err, res) -> expectCode res, 200 cb() (cb) -> request.get(baseURL + "/groups/" + party._id) - .end (res) -> + .end (err, res) -> expectCode res, 200 g = res.body userInviteForGroup = _.find(g.invites, (invite) -> return invite._id == userToDeleteInvites._id; ) @@ -242,7 +242,7 @@ describe "Users", -> (cb) -> request.get(baseURL + "/groups/" + guild._id) - .end (res) -> + .end (err, res) -> expectCode res, 200 g = res.body userInviteForGroup = _.find(g.invites, (invite) -> return invite._id == userToDeleteInvites._id; ) diff --git a/test/mocha.opts b/test/mocha.opts index 03db728cec..01d9dcfcd7 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -4,5 +4,7 @@ --check-leaks --growl --debug +--compilers coffee:coffee-script --globals io +--require test/api-legacy/api-helper --require ./test/helpers/globals.helper From b52f901f41e4ea3158f884ca932c7c95a4f94fd9 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 20 Oct 2015 21:53:52 -0500 Subject: [PATCH 38/53] Convert legacy api helper to js --- test/api-legacy/api-helper.coffee | 76 -------------------------- test/api-legacy/api-helper.js | 90 +++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 76 deletions(-) delete mode 100644 test/api-legacy/api-helper.coffee create mode 100644 test/api-legacy/api-helper.js diff --git a/test/api-legacy/api-helper.coffee b/test/api-legacy/api-helper.coffee deleted file mode 100644 index 3c4ed36df2..0000000000 --- a/test/api-legacy/api-helper.coffee +++ /dev/null @@ -1,76 +0,0 @@ -############################## -# Global modules -############################## -superagentDefaults = require("superagent-defaults") -global.request = superagentDefaults() - -global.mongoose = require("mongoose") -global.moment = require("moment") -global.async = require("async") -global._ = require("lodash") -global.shared = require("../../common") -global.User = require("../../website/src/models/user").model - -global.chai = require("chai") -chai.use(require("sinon-chai")) -global.expect = chai.expect - -############################## -# Nconf config -############################## -path = require("path") -global.conf = require("nconf") -conf.argv().env().file(file: path.join(__dirname, "../config.json")).defaults() -conf.set "PORT", "1337" - -############################## -# Node ENV and global variables -############################## -process.env.NODE_DB_URI = "mongodb://localhost/habitrpg_test_api_legacy" -global.baseURL = "http://localhost:" + conf.get("PORT") + "/api/v2" -global.user = undefined - -############################## -# Helper Methods -############################## -global.expectCode = (res, code) -> - expect(res.body.err).to.not.exist if code is 200 - expect(res.statusCode).to.equal code - -global.registerNewUser = (cb, main) -> - main = true unless main? - randomID = shared.uuid() - username = password = randomID if main - request - .post(baseURL + "/register") - .set("Accept", "application/json") - .set("X-API-User", null) - .set("X-API-Key", null) - .send - username: randomID - password: randomID - confirmPassword: randomID - email: randomID + "@gmail.com" - .end (err, res) -> - return cb(null, res.body) unless main - _id = res.body._id - apiToken = res.body.apiToken - User.findOne - _id: _id - apiToken: apiToken - , (err, _user) -> - expect(err).to.not.be.ok - global.user = _user - request - .set("Accept", "application/json") - .set("X-API-User", _id) - .set("X-API-Key", apiToken) - cb null, res.body - -global.registerManyUsers = (number, callback) -> - async.times number, (n, next) -> - registerNewUser (err, user) -> - next(err, user) - , false - , (err, users) -> - callback(err, users) diff --git a/test/api-legacy/api-helper.js b/test/api-legacy/api-helper.js new file mode 100644 index 0000000000..3dcaf5241c --- /dev/null +++ b/test/api-legacy/api-helper.js @@ -0,0 +1,90 @@ +require('coffee-script'); +var path, superagentDefaults; + +superagentDefaults = require("superagent-defaults"); + +global.request = superagentDefaults(); + +global.mongoose = require("mongoose"); + +global.moment = require("moment"); + +global.async = require("async"); + +global._ = require("lodash"); + +global.shared = require("../../common"); + +global.User = require("../../website/src/models/user").model; + +global.chai = require("chai"); + +chai.use(require("sinon-chai")); + +global.expect = chai.expect; + +path = require("path"); + +global.conf = require("nconf"); + +conf.argv().env().file({ + file: path.join(__dirname, "../config.json") +}).defaults(); + +conf.set("PORT", "1337"); + +process.env.NODE_DB_URI = "mongodb://localhost/habitrpg_test_api_legacy"; + +global.baseURL = "http://localhost:" + conf.get("PORT") + "/api/v2"; + +global.user = void 0; + +global.expectCode = function(res, code) { + if (code === 200) { + expect(res.body.err).to.not.exist; + } + return expect(res.statusCode).to.equal(code); +}; + +global.registerNewUser = function(cb, main) { + var password, randomID, username; + if (main == null) { + main = true; + } + randomID = shared.uuid(); + if (main) { + username = password = randomID; + } + return request.post(baseURL + "/register").set("Accept", "application/json").set("X-API-User", null).set("X-API-Key", null).send({ + username: randomID, + password: randomID, + confirmPassword: randomID, + email: randomID + "@gmail.com" + }).end(function(err, res) { + var _id, apiToken; + if (!main) { + return cb(null, res.body); + } + _id = res.body._id; + apiToken = res.body.apiToken; + return User.findOne({ + _id: _id, + apiToken: apiToken + }, function(err, _user) { + expect(err).to.not.be.ok; + global.user = _user; + request.set("Accept", "application/json").set("X-API-User", _id).set("X-API-Key", apiToken); + return cb(null, res.body); + }); + }); +}; + +global.registerManyUsers = function(number, callback) { + return async.times(number, function(n, next) { + return registerNewUser(function(err, user) { + return next(err, user); + }, false); + }, function(err, users) { + return callback(err, users); + }); +}; From f4256f7bf6ac949ba5aa3dafd9c38abed0c6f866 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 21 Oct 2015 17:59:44 -0500 Subject: [PATCH 39/53] Adjust context description --- test/api/groups/groups_id-get.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/api/groups/groups_id-get.js b/test/api/groups/groups_id-get.js index 6a6218e653..40ab7d0e05 100644 --- a/test/api/groups/groups_id-get.js +++ b/test/api/groups/groups_id-get.js @@ -6,7 +6,7 @@ import { describe('GET /groups/:id', () => { - context('All Groups', () => { + context('All types of groups', () => { let api, leader, createdGroup; beforeEach((done) => { From c3aa70ecc3c5e4575223325e16382bcb2dc9ba05 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 21 Oct 2015 18:00:25 -0500 Subject: [PATCH 40/53] Moved guild update tests from legacy file to new file --- test/api-legacy/groups.coffee | 37 --------------- test/api/groups/groups_id-post.js | 78 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 37 deletions(-) create mode 100644 test/api/groups/groups_id-post.js diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index 209b14e5cd..4111bf82e8 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -6,43 +6,6 @@ Group = require("../../website/src/models/group").model app = require("../../website/src/server") describe.skip "Guilds", -> - context "updating groups", -> - groupToUpdate = undefined - before (done) -> - request.post(baseURL + "/groups").send( - name: "TestGroup" - type: "guild" - description: "notUpdatedDesc" - ).end (err, res) -> - groupToUpdate = res.body - done() - - it "prevents user from updating a party when they aren't the leader", (done) -> - registerNewUser (err, tmpUser) -> - request.post(baseURL + "/groups/" + groupToUpdate._id).send( - name: "TestGroupName" - description: "updatedDesc" - ) - .set("X-API-User", tmpUser._id) - .set("X-API-Key", tmpUser.apiToken) - .end (err, res) -> - expectCode res, 401 - expect(res.body.err).to.equal "Only the group leader can update the group!" - done() - , false - - it "allows user to update a group", (done) -> - request.post(baseURL + "/groups/" + groupToUpdate._id).send( - description: "updatedDesc" - ) - .end (err, res) -> - expectCode res, 204 - request.get(baseURL + "/groups/" + groupToUpdate._id).send() - .end (err, res) -> - updatedGroup = res.body - expect(updatedGroup.description).to.equal "updatedDesc" - done() - context "leaving groups", -> it "can leave a guild", (done) -> guildToLeave = undefined diff --git a/test/api/groups/groups_id-post.js b/test/api/groups/groups_id-post.js new file mode 100644 index 0000000000..43659bae91 --- /dev/null +++ b/test/api/groups/groups_id-post.js @@ -0,0 +1,78 @@ +import { + generateGroup, + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('POST /groups/:id', () => { + + context('user is not the leader of the group', () => { + let api, user, otherUser, groupUserDoesNotOwn; + + beforeEach((done) => { + Promise.all([ + generateUser({ balance: 10 }), + generateUser({ balance: 10 }), + ]).then((users) => { + user = users[0]; + otherUser = users[1]; + api = requester(user); + + return generateGroup(otherUser, { + name: 'Group not Owned By User', + type: 'guild', + privacy: 'public', + members: [user, otherUser], + }); + }).then((group) => { + groupUserDoesNotOwn = group; + done(); + }).catch(done); + }); + + it('does not allow user to update group', (done) => { + api.post(`/groups/${groupUserDoesNotOwn._id}`, { + name: 'Change' + }).then(done).catch((err) => { + expect(err.code).to.eql(401); + expect(err.text).to.eql('Only the group leader can update the group!'); + done(); + }); + }); + }); + + context('user is the leader of the group', () => { + let api, user, usersGroup; + + beforeEach((done) => { + generateUser({ + balance: 10, + }).then((_user) => { + user = _user; + api = requester(user); + + return generateGroup(user, { + name: 'Original Group Title', + type: 'guild', + privacy: 'public', + }); + }).then((group) => { + usersGroup = group; + done(); + }).catch(done); + }); + + it('allows user to update group', (done) => { + api.post(`/groups/${usersGroup._id}`, { + name: 'New Group Title', + description: 'New group description', + }).then((group) => { + return api.get(`/groups/${usersGroup._id}`); + }).then((group) => { + expect(group.name).to.eql('New Group Title'); + expect(group.description).to.eql('New group description'); + done(); + }).catch(done); + }); + }); +}); From d28450d52a81c823885aae576c1918fbb5169b65 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Thu, 22 Oct 2015 12:28:26 -0500 Subject: [PATCH 41/53] Port groups /leave tests to new integration tests. --- test/api-legacy/groups.coffee | 128 ------------------ test/api/groups/groups_id_leave-post.js | 169 ++++++++++++++++++++++++ test/helpers/api.helper.js | 65 +++++++++ 3 files changed, 234 insertions(+), 128 deletions(-) create mode 100644 test/api/groups/groups_id_leave-post.js diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index 4111bf82e8..0927433138 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -6,134 +6,6 @@ Group = require("../../website/src/models/group").model app = require("../../website/src/server") describe.skip "Guilds", -> - context "leaving groups", -> - it "can leave a guild", (done) -> - guildToLeave = undefined - request.post(baseURL + "/groups").send( - name: "TestGroupToLeave" - type: "guild" - ).end (err, res) -> - guildToLeave = res.body - request.post(baseURL + "/groups/" + guildToLeave._id + "/leave") - .send() - .end (err, res) -> - expectCode res, 204 - done() - - it "deletes a group when the last member leaves", (done) -> - groupToDeleteAfterLeave = undefined - request.post(baseURL + "/groups").send( - name: "TestGroupToDeleteAfteLeave" - type: "guild" - privacy: "private" - ).end (err, res) -> - groupToDeleteAfterLeave = res.body - async.waterfall [ - (cb) -> - request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id + "/leave") - .end (err, res) -> - expectCode res, 204 - cb() - - (cb) -> - request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id) - .end (err, res) -> - expectCode res, 404 - cb() - ], done - - it "deletes all invites to a group (guild) when the last member leaves", (done) -> - groupToDeleteAfterLeave = undefined - userToRemoveInvite = undefined - request.post(baseURL + "/groups").send( - name: "TestGroupToDeleteAfterLeave" - type: "guild" - privacy: "private" - ).end (err, res) -> - groupToDeleteAfterLeave = res.body - async.waterfall [ - (cb) -> - registerManyUsers 1, cb - - (_members, cb) -> - userToRemoveInvite = _members[0] - inviteURL = baseURL + "/groups/" + groupToDeleteAfterLeave._id + "/invite" - request.post(inviteURL).send( - uuids: [userToRemoveInvite._id] - ) - .end -> - cb() - - (cb) -> - request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id + "/leave") - .end (err, res) -> - expectCode res, 204 - cb() - - (cb) -> - request.get(baseURL + '/user') - .set("X-API-User", userToRemoveInvite._id) - .set("X-API-Key", userToRemoveInvite.apiToken) - .end (err, res) -> - expectCode res, 200 - groupInvitation = _.find(res.body.invitations.guilds, {id: groupToDeleteAfterLeave._id}) - expect(groupInvitation).to.not.exist - cb() - - (cb) -> - request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id) - .end (err, res) -> - expectCode res, 404 - cb() - ], done - - it "deletes all invites to a group (party) when the last member leaves", (done) -> - partyToDeleteAfterLeave = undefined - userToRemovePartyInvite = undefined - request.post(baseURL + "/groups").send( - name: "TestPartyToDeleteAfterLeave" - type: "party" - ).end (err, res) -> - partyToDeleteAfterLeave = res.body - async.waterfall [ - (cb) -> - registerManyUsers 1, cb - - (_members, cb) -> - userToRemovePartyInvite = _members[0] - inviteURL = baseURL + "/groups/" + partyToDeleteAfterLeave._id + "/invite" - request.post(inviteURL).send( - uuids: [userToRemovePartyInvite._id] - ) - .end -> - cb() - - (cb) -> - request.post(baseURL + "/groups/" + partyToDeleteAfterLeave._id + "/leave") - .end (err, res) -> - expectCode res, 204 - cb() - - (cb) -> - request.get(baseURL + '/user') - .set("X-API-User", userToRemovePartyInvite._id) - .set("X-API-Key", userToRemovePartyInvite.apiToken) - .end (err, res) -> - expectCode res, 200 - party = partyToDeleteAfterLeave - partyInvitation = _.find(res.body.invitations.party, (invite) -> - return invite == party._id - ) - expect(partyInvitation).to.not.exist - cb() - - (cb) -> - request.post(baseURL + "/groups/" + partyToDeleteAfterLeave._id) - .end (err, res) -> - expectCode res, 404 - cb() - ], done - context "removing users groups", -> it "allows guild leaders to remove a member (but not themselves)", (done) -> guildToRemoveMember = undefined diff --git a/test/api/groups/groups_id_leave-post.js b/test/api/groups/groups_id_leave-post.js new file mode 100644 index 0000000000..ba008490a9 --- /dev/null +++ b/test/api/groups/groups_id_leave-post.js @@ -0,0 +1,169 @@ +import { + createAndPopulateGroup, + generateGroup, + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('POST /groups/:id/leave', () => { + + context('user is not member of the group', () => { + it('returns an error'); + }); + + context('user is a non-leader member of a guild', () => { + let api, user, group; + + beforeEach((done) => { + createAndPopulateGroup({ + members: 3, + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'public', + }, + }).then((res) => { + user = res.members[0]; + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + it('leaves the group', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return api.get(`/groups/${group._id}`); + }).then((group) => { + expect(group.members).to.not.include(user._id); + done(); + }).catch(done); + }); + }); + + context('user is the last member of a public guild', () => { + let api, user, group; + + beforeEach((done) => { + createAndPopulateGroup({ + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'public', + }, + }).then((res) => { + user = res.leader; + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + it('leaves the group accessible', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return api.get(`/groups/${group._id}`); + }).then((group) => { + expect(group._id).to.eql(group._id); + done(); + }).catch(done); + }); + }); + + context('user is the last member of a private group', () => { + let api, user, group; + + beforeEach((done) => { + createAndPopulateGroup({ + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'private', + }, + }).then((res) => { + user = res.leader; + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + it('group is not accessible after leaving', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return api.get(`/groups/${group._id}`); + }).then(done).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done(); + }); + }); + }); + + context('user is the last member of a private group with pending invites', () => { + let api, user, inviteeRequest1, inviteeRequest2, group; + + beforeEach((done) => { + createAndPopulateGroup({ + invites: 2, + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'private', + }, + }).then((res) => { + user = res.leader; + inviteeRequest1 = requester(res.invitees[0]); + inviteeRequest2 = requester(res.invitees[1]); + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + xit('@TODO: private guilds are not being deleted. Figure out why. deletes the group invitations from users', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return Promise.all([ + inviteeRequest1.get(`/user`), + inviteeRequest2.get(`/user`), + ]); + }).then((users) => { + expect(users[0].invitations.guilds[0]).to.not.exist; + expect(users[1].invitations.guilds[0]).to.not.exist; + done(); + }).catch(done); + }); + }); + + context('user is the last member of a party with pending invites', () => { + let api, user, inviteeRequest1, inviteeRequest2, group; + + beforeEach((done) => { + createAndPopulateGroup({ + invites: 2, + groupDetails: { + name: 'test party', + type: 'party', + privacy: 'private', + }, + }).then((res) => { + user = res.leader; + inviteeRequest1 = requester(res.invitees[0]); + inviteeRequest2 = requester(res.invitees[1]); + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + xit('@TODO: private guilds are not being deleted. Figure out why. deletes the group invitations from users', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return Promise.all([ + inviteeRequest1.get(`/user`), + inviteeRequest2.get(`/user`), + ]); + }).then((users) => { + expect(users[0].invitations.party).to.be.empty; + expect(users[1].invitations.party).to.be.empty; + done(); + }).catch(done); + }); + }); +}); diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index 546e21a234..4c6d35b16a 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -1,6 +1,8 @@ import { assign, + each, isEmpty, + times, } from 'lodash'; import {MongoClient as mongo} from 'mongodb'; import {v4 as generateUUID} from 'uuid'; @@ -50,6 +52,69 @@ export function generateGroup(leader, update={}) { }); }; +export function createAndPopulateGroup(settings={}) { + let request, leader, members, invitees, group; + + let numberOfMembers = settings.members || 0; + let numberOfInvites = settings.invites || 0; + let groupDetails = settings.groupDetails; + let leaderDetails = settings.leaderDetails || { balance: 10 }; + + let leaderPromise = generateUser(leaderDetails); + + let memberPromises = Promise.all( + times(numberOfMembers, () => { + return generateUser(); + }) + ); + + let invitePromises = Promise.all( + times(numberOfInvites, () => { + return generateUser(); + }) + ); + + return new Promise((resolve, reject) => { + return leaderPromise.then((user) => { + leader = user; + request = _requestMaker(leader, 'post'); + return memberPromises; + }).then((users) => { + members = users; + groupDetails.members = groupDetails.members || []; + + each(members, (member) => { + groupDetails.members.push(member._id); + }); + + return generateGroup(leader, groupDetails); + }).then((createdGroup) => { + group = createdGroup; + return invitePromises; + }).then((users) => { + invitees = users; + + let invitePromises = []; + + each(invitees, (invitee) => { + let invitePromise = request(`/groups/${group._id}/invite`, { + uuids: [invitee._id] + }); + invitePromises.push(invitePromise); + }); + + return Promise.all(invitePromises); + }).then((inviteResults) => { + resolve({ + leader: leader, + group: group, + members: members, + invitees: invitees, + }); + }).catch(reject); + }); +}; + export function resetHabiticaDB() { return new Promise((resolve, reject) => { mongo.connect('mongodb://localhost/habitrpg_test', (err, db) => { From abf4b1c6431580094b2caf7448d49be4754f1a91 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Thu, 22 Oct 2015 12:46:54 -0500 Subject: [PATCH 42/53] Fix bug where tests were failing erroneously --- test/api/groups/groups_id_leave-post.js | 4 ++-- test/helpers/api.helper.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/api/groups/groups_id_leave-post.js b/test/api/groups/groups_id_leave-post.js index ba008490a9..6a741206c0 100644 --- a/test/api/groups/groups_id_leave-post.js +++ b/test/api/groups/groups_id_leave-post.js @@ -118,7 +118,7 @@ describe('POST /groups/:id/leave', () => { }).catch(done); }); - xit('@TODO: private guilds are not being deleted. Figure out why. deletes the group invitations from users', (done) => { + it('deletes the group invitations from users', (done) => { api.post(`/groups/${group._id}/leave`).then((result) => { return Promise.all([ inviteeRequest1.get(`/user`), @@ -153,7 +153,7 @@ describe('POST /groups/:id/leave', () => { }).catch(done); }); - xit('@TODO: private guilds are not being deleted. Figure out why. deletes the group invitations from users', (done) => { + it('deletes the group invitations from users', (done) => { api.post(`/groups/${group._id}/leave`).then((result) => { return Promise.all([ inviteeRequest1.get(`/user`), diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index 4c6d35b16a..2965ea19e7 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -81,7 +81,7 @@ export function createAndPopulateGroup(settings={}) { return memberPromises; }).then((users) => { members = users; - groupDetails.members = groupDetails.members || []; + groupDetails.members = groupDetails.members || [leader._id]; each(members, (member) => { groupDetails.members.push(member._id); From c4402b2634f59f21eb45ce747b43208c0695d208 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Thu, 22 Oct 2015 12:48:20 -0500 Subject: [PATCH 43/53] Port removeMember tests to new test format --- test/api-legacy/groups.coffee | 54 ---------------- .../api/groups/groups_id_removeMember-post.js | 61 +++++++++++++++++++ 2 files changed, 61 insertions(+), 54 deletions(-) create mode 100644 test/api/groups/groups_id_removeMember-post.js diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index 0927433138..379fd18a32 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -6,60 +6,6 @@ Group = require("../../website/src/models/group").model app = require("../../website/src/server") describe.skip "Guilds", -> - context "removing users groups", -> - it "allows guild leaders to remove a member (but not themselves)", (done) -> - guildToRemoveMember = undefined - members = undefined - userToRemove = undefined - request.post(baseURL + "/groups").send( - name: "TestGuildToRemoveMember" - type: "guild" - ).end (err, res) -> - guildToRemoveMember = res.body - #Add members to guild - async.waterfall [ - (cb) -> - registerManyUsers 1, cb - - (_members, cb) -> - userToRemove = _members[0] - members = _members - inviteURL = baseURL + "/groups/" + guildToRemoveMember._id + "/invite" - request.post(inviteURL).send( - uuids: [userToRemove._id] - ) - .end -> - cb() - - (cb) -> - request.post(baseURL + "/groups/" + guildToRemoveMember._id + "/join") - .set("X-API-User", userToRemove._id) - .set("X-API-Key", userToRemove.apiToken) - .end (err, res) -> - cb() - (cb) -> - request.post(baseURL + "/groups/" + guildToRemoveMember._id + "/removeMember?uuid=" + guildToRemoveMember.leader) - .send().end (err, res) -> - expectCode res, 401 - cb() - - (cb) -> - request.post(baseURL + "/groups/" + guildToRemoveMember._id + "/removeMember?uuid=" + userToRemove._id) - .send().end (err, res) -> - expectCode res, 204 - cb() - - (cb) -> - request.get(baseURL + "/groups/" + guildToRemoveMember._id) - .send() - .end (err, res) -> - g = res.body - userInGroup = _.find g.members, (member) -> return member._id == userToRemove._id - expect(userInGroup).to.not.exist - cb() - - ], done - describe "Private Guilds", -> guild = undefined before (done) -> diff --git a/test/api/groups/groups_id_removeMember-post.js b/test/api/groups/groups_id_removeMember-post.js new file mode 100644 index 0000000000..283fcff60e --- /dev/null +++ b/test/api/groups/groups_id_removeMember-post.js @@ -0,0 +1,61 @@ +import { + createAndPopulateGroup, + generateGroup, + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('POST /groups/:id/removeMember', () => { + + context('user is not member of the group', () => { + it('returns an error'); + }); + + context('user is a non-leader member of a guild', () => { + it('returns an error'); + }); + + context('user is the leader of a guild', () => { + let api, leader, member, group; + + beforeEach((done) => { + createAndPopulateGroup({ + members: 1, + groupDetails: { + name: 'test group', + type: 'guild', + privacy: 'public', + }, + }).then((res) => { + leader = res.leader; + member = res.members[0]; + group = res.group; + + api = requester(leader); + done(); + }).catch(done); + }); + + it('does not allow leader to remove themselves', (done) => { + api.post(`/groups/${group._id}/removeMember`, null, { + uuid: leader._id, + }).then(done).catch((err) => { + expect(err.code).to.eql(401); + expect(err.text).to.eql('You cannot remove yourself!'); + done(); + }); + }); + + it('can remove other members of guild', (done) => { + api.post(`/groups/${group._id}/removeMember`, null, { + uuid: member._id, + }).then((res) => { + return api.get(`/groups/${group._id}`); + }).then((guild) => { + expect(guild.members).to.have.a.lengthOf(1); + expect(guild.members[0]._id).to.not.eql(member._id); + done(); + }).catch(done); + }); + }); +}); From 9a79870b93b9acdc3cc6ea3daaec4af837cab524 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Thu, 22 Oct 2015 12:53:48 -0500 Subject: [PATCH 44/53] Change convention for naming tests --- test/api/groups/{groups-get.js => GET-groups.test.js} | 0 test/api/groups/{groups_id-get.js => GET-groups_id.test.js} | 0 test/api/groups/{groups-post.js => POST-groups.test.js} | 0 test/api/groups/{groups_id-post.js => POST-groups_id.test.js} | 0 .../{groups_id_leave-post.js => POST-groups_id_leave.test.js} | 0 ...d_removeMember-post.js => POST-groups_id_removeMember.test.js} | 0 test/api/register/{register-post.js => POST-register.test.js} | 0 test/api/status/{status-get.js => GET-status.test.js} | 0 test/api/user/{user-delete.js => DELETE-user.test.js} | 0 test/api/user/{user-get.js => GET-user.test.js} | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename test/api/groups/{groups-get.js => GET-groups.test.js} (100%) rename test/api/groups/{groups_id-get.js => GET-groups_id.test.js} (100%) rename test/api/groups/{groups-post.js => POST-groups.test.js} (100%) rename test/api/groups/{groups_id-post.js => POST-groups_id.test.js} (100%) rename test/api/groups/{groups_id_leave-post.js => POST-groups_id_leave.test.js} (100%) rename test/api/groups/{groups_id_removeMember-post.js => POST-groups_id_removeMember.test.js} (100%) rename test/api/register/{register-post.js => POST-register.test.js} (100%) rename test/api/status/{status-get.js => GET-status.test.js} (100%) rename test/api/user/{user-delete.js => DELETE-user.test.js} (100%) rename test/api/user/{user-get.js => GET-user.test.js} (100%) diff --git a/test/api/groups/groups-get.js b/test/api/groups/GET-groups.test.js similarity index 100% rename from test/api/groups/groups-get.js rename to test/api/groups/GET-groups.test.js diff --git a/test/api/groups/groups_id-get.js b/test/api/groups/GET-groups_id.test.js similarity index 100% rename from test/api/groups/groups_id-get.js rename to test/api/groups/GET-groups_id.test.js diff --git a/test/api/groups/groups-post.js b/test/api/groups/POST-groups.test.js similarity index 100% rename from test/api/groups/groups-post.js rename to test/api/groups/POST-groups.test.js diff --git a/test/api/groups/groups_id-post.js b/test/api/groups/POST-groups_id.test.js similarity index 100% rename from test/api/groups/groups_id-post.js rename to test/api/groups/POST-groups_id.test.js diff --git a/test/api/groups/groups_id_leave-post.js b/test/api/groups/POST-groups_id_leave.test.js similarity index 100% rename from test/api/groups/groups_id_leave-post.js rename to test/api/groups/POST-groups_id_leave.test.js diff --git a/test/api/groups/groups_id_removeMember-post.js b/test/api/groups/POST-groups_id_removeMember.test.js similarity index 100% rename from test/api/groups/groups_id_removeMember-post.js rename to test/api/groups/POST-groups_id_removeMember.test.js diff --git a/test/api/register/register-post.js b/test/api/register/POST-register.test.js similarity index 100% rename from test/api/register/register-post.js rename to test/api/register/POST-register.test.js diff --git a/test/api/status/status-get.js b/test/api/status/GET-status.test.js similarity index 100% rename from test/api/status/status-get.js rename to test/api/status/GET-status.test.js diff --git a/test/api/user/user-delete.js b/test/api/user/DELETE-user.test.js similarity index 100% rename from test/api/user/user-delete.js rename to test/api/user/DELETE-user.test.js diff --git a/test/api/user/user-get.js b/test/api/user/GET-user.test.js similarity index 100% rename from test/api/user/user-get.js rename to test/api/user/GET-user.test.js From e3234a54cebcede1ba1193fb554b23fe5d1e6ec5 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Thu, 22 Oct 2015 17:15:40 -0500 Subject: [PATCH 45/53] Refactor get groups test to test all kinds of groups --- test/api/groups/GET-groups_id.test.js | 107 ++++++++++++++------------ 1 file changed, 56 insertions(+), 51 deletions(-) diff --git a/test/api/groups/GET-groups_id.test.js b/test/api/groups/GET-groups_id.test.js index 40ab7d0e05..6e532f2919 100644 --- a/test/api/groups/GET-groups_id.test.js +++ b/test/api/groups/GET-groups_id.test.js @@ -3,62 +3,67 @@ import { generateUser, requester, } from '../../helpers/api.helper'; +import {each} from 'lodash'; describe('GET /groups/:id', () => { - context('All types of groups', () => { - let api, leader, createdGroup; + let typesOfGroups = { + publicGuilds: { type: 'guild', privacy: 'public' }, + privateGuilds: { type: 'guild', privacy: 'private' }, + party: { type: 'party', privacy: 'private' }, + } - beforeEach((done) => { - generateUser({ - balance: 1, - }).then((user) => { - leader = user; - api = requester(user); - return generateGroup(leader, { - name: 'group name', - type: 'guild', - privacy: 'public', + each(typesOfGroups, (groupData, groupType) => { + context(`Group Type: ${groupType}`, () => { + let api, leader, createdGroup; + + beforeEach((done) => { + generateUser({ + balance: 1, + }).then((user) => { + leader = user; + api = requester(user); + return generateGroup(leader, groupData); + }).then((group) => { + createdGroup = group; + done(); + }).catch(done); + }); + + it('transforms members array to an array of user objects', (done) => { + api.get(`/groups/${createdGroup._id}`).then((group) => { + let member = group.members[0]; + expect(member._id).to.eql(leader._id); + expect(member.profile.name).to.eql(leader.profile.name); + expect(member.items).to.exist; + expect(member.stats).to.exist; + expect(member.achievements).to.exist; + expect(member.contributor).to.exist; + done(); + }).catch(done); + }); + + it('transforms leader id to leader object', (done) => { + api.get(`/groups/${createdGroup._id}`).then((group) => { + expect(group.leader._id).to.eql(leader._id); + expect(group.leader.profile.name).to.eql(leader.profile.name); + expect(group.leader.items).to.exist; + expect(group.leader.stats).to.exist; + expect(group.leader.achievements).to.exist; + expect(group.leader.contributor).to.exist; + done(); + }).catch(done); + }); + + it('returns error if group does not exist', (done) => { + generateUser().then((user) => { + api = requester(user); + return api.get('/groups/group-that-does-not-exist'); + }).then((done)).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done() }); - }).then((group) => { - createdGroup = group; - done(); - }).catch(done); - }); - - it('transforms members array to an array of user objects', (done) => { - api.get(`/groups/${createdGroup._id}`).then((group) => { - let member = group.members[0]; - expect(member._id).to.eql(leader._id); - expect(member.profile.name).to.eql(leader.profile.name); - expect(member.items).to.exist; - expect(member.stats).to.exist; - expect(member.achievements).to.exist; - expect(member.contributor).to.exist; - done(); - }).catch(done); - }); - - it('transforms leader id to leader object', (done) => { - api.get(`/groups/${createdGroup._id}`).then((group) => { - expect(group.leader._id).to.eql(leader._id); - expect(group.leader.profile.name).to.eql(leader.profile.name); - expect(group.leader.items).to.exist; - expect(group.leader.stats).to.exist; - expect(group.leader.achievements).to.exist; - expect(group.leader.contributor).to.exist; - done(); - }).catch(done); - }); - - it('returns error if group does not exist', (done) => { - generateUser().then((user) => { - api = requester(user); - return api.get('/groups/group-that-does-not-exist'); - }).then((done)).catch((err) => { - expect(err.code).to.eql(404); - expect(err.text).to.eql('Group not found or you don\'t have access.'); - done() }); }); }); From 3c8c4343ee136a8b3ac48ef19969967d51a32319 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Thu, 22 Oct 2015 18:02:58 -0500 Subject: [PATCH 46/53] Move group tests to new test structure --- test/api-legacy/groups.coffee | 49 ----- test/api/groups/GET-groups_id.test.js | 284 +++++++++++++++----------- 2 files changed, 163 insertions(+), 170 deletions(-) diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index 379fd18a32..014cb65a84 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -6,55 +6,6 @@ Group = require("../../website/src/models/group").model app = require("../../website/src/server") describe.skip "Guilds", -> - describe "Private Guilds", -> - guild = undefined - before (done) -> - request.post(baseURL + "/groups").send( - name: "TestPrivateGroup" - type: "guild" - privacy: "private" - ).end (err, res) -> - expectCode res, 200 - guild = res.body - expect(guild.members.length).to.equal 1 - expect(guild.leader).to.equal user._id - #Add members to guild - async.waterfall [ - (cb) -> - registerManyUsers 15, cb - - (_members, cb) -> - members = _members - - joinGuild = (member, callback) -> - request.post(baseURL + "/groups/" + guild._id + "/join") - .set("X-API-User", member._id) - .set("X-API-Key", member.apiToken) - .end -> - callback(null, null) - - async.map members, joinGuild, (err, results) -> cb() - - ], done - - it "includes user in private group member list when user is a member", (done) -> - - request.get(baseURL + "/groups/" + guild._id) - .end (err, res) -> - g = res.body - userInGroup = _.find g.members, (member) -> return member._id == user._id - expect(userInGroup).to.exist - done() - - it "excludes user from viewing private group member list when user is not a member", (done) -> - - request.post(baseURL + "/groups/" + guild._id + "/leave") - .end (err, res) -> - request.get(baseURL + "/groups/" + guild._id) - .end (err, res) -> - expect res, 404 - done() - describe "Public Guilds", -> before (done) -> async.waterfall [ diff --git a/test/api/groups/GET-groups_id.test.js b/test/api/groups/GET-groups_id.test.js index 6e532f2919..c23f6de01b 100644 --- a/test/api/groups/GET-groups_id.test.js +++ b/test/api/groups/GET-groups_id.test.js @@ -1,49 +1,68 @@ import { - generateGroup, + createAndPopulateGroup, generateUser, requester, } from '../../helpers/api.helper'; -import {each} from 'lodash'; +import { + find, + each +} from 'lodash'; describe('GET /groups/:id', () => { - let typesOfGroups = { - publicGuilds: { type: 'guild', privacy: 'public' }, - privateGuilds: { type: 'guild', privacy: 'private' }, - party: { type: 'party', privacy: 'private' }, - } + let typesOfGroups = {}; + typesOfGroups['public guild'] = { type: 'guild', privacy: 'public' }; + typesOfGroups['private guild'] = { type: 'guild', privacy: 'private' }; + typesOfGroups['party'] = { type: 'party', privacy: 'private' }; each(typesOfGroups, (groupData, groupType) => { - context(`Group Type: ${groupType}`, () => { - let api, leader, createdGroup; + context(`Member of a ${groupType}`, () => { + let leader, member, createdGroup; - beforeEach((done) => { - generateUser({ - balance: 1, - }).then((user) => { - leader = user; - api = requester(user); - return generateGroup(leader, groupData); - }).then((group) => { - createdGroup = group; + before((done) => { + createAndPopulateGroup({ + members: 30, + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'public', + }, + }).then((res) => { + leader = res.leader; + member = res.members[0]; + createdGroup = res.group; done(); }).catch(done); }); + it('returns the group object', (done) => { + let api = requester(member); + api.get(`/groups/${createdGroup._id}`) + .then((group) => { + expect(group._id).to.eql(createdGroup._id); + expect(group.name).to.eql(createdGroup.name); + expect(group.type).to.eql(createdGroup.type); + expect(group.privacy).to.eql(createdGroup.privacy); + done(); + }).catch(done); + }); + it('transforms members array to an array of user objects', (done) => { + let api = requester(member); api.get(`/groups/${createdGroup._id}`).then((group) => { - let member = group.members[0]; - expect(member._id).to.eql(leader._id); - expect(member.profile.name).to.eql(leader.profile.name); - expect(member.items).to.exist; - expect(member.stats).to.exist; - expect(member.achievements).to.exist; - expect(member.contributor).to.exist; + let foundMember = group.members[0]; + expect(foundMember._id).to.exist; + expect(foundMember.profile.name).to.exist; + expect(foundMember.items).to.exist; + expect(foundMember.stats).to.exist; + expect(foundMember.achievements).to.exist; + expect(foundMember.contributor).to.exist; done(); }).catch(done); }); it('transforms leader id to leader object', (done) => { + let api = requester(member); api.get(`/groups/${createdGroup._id}`).then((group) => { expect(group.leader._id).to.eql(leader._id); expect(group.leader.profile.name).to.eql(leader.profile.name); @@ -55,40 +74,43 @@ describe('GET /groups/:id', () => { }).catch(done); }); - it('returns error if group does not exist', (done) => { - generateUser().then((user) => { - api = requester(user); - return api.get('/groups/group-that-does-not-exist'); - }).then((done)).catch((err) => { - expect(err.code).to.eql(404); - expect(err.text).to.eql('Group not found or you don\'t have access.'); - done() - }); + it('includes the user in the members list', (done) => { + let api = requester(member); + api.get(`/groups/${createdGroup._id}`).then((group) => { + let members = group.members; + let userInGroup = find(members, (user) => { + return member._id === user._id; + }); + expect(userInGroup).to.be.ok; + done(); + }).catch(done); }); }); }); - context('Public Guilds', () => { - let api, leader, createdGroup; + context('Non-member of a public guild', () => { + let leader, nonMember, createdGroup; - beforeEach((done) => { - generateUser({ - balance: 1, - }).then((user) => { - leader = user; - api = requester(user); - return generateGroup(leader, { - name: 'group name', + before((done) => { + createAndPopulateGroup({ + members: 1, + groupDetails: { + name: 'test guild', type: 'guild', privacy: 'public', - }); - }).then((group) => { - createdGroup = group; + }, + }).then((res) => { + leader = res.leader; + createdGroup = res.group; + return generateUser(); + }).then((user) => { + nonMember = user; done(); }).catch(done); }); - it('returns the group object', (done) => { + it('returns the group object for a non-member', (done) => { + let api = requester(nonMember); api.get(`/groups/${createdGroup._id}`) .then((group) => { expect(group._id).to.eql(createdGroup._id); @@ -99,105 +121,104 @@ describe('GET /groups/:id', () => { }).catch(done); }); - it('returns the group object for a non-member', (done) => { - generateUser().then((user) => { - api = requester(user); - return api.get(`/groups/${createdGroup._id}`); - }).then((group) => { - expect(group._id).to.eql(createdGroup._id); - expect(group.name).to.eql(createdGroup.name); - expect(group.type).to.eql(createdGroup.type); - expect(group.privacy).to.eql(createdGroup.privacy); - done(); - }).catch(done); + it('does not include user in members list', (done) => { + let api = requester(nonMember); + api.get(`/groups/${createdGroup._id}`) + .then((group) => { + let userInGroup = find(group.members, (user) => { + return nonMember._id === user._id; + }); + expect(userInGroup).to.not.be.ok; + done(); + }).catch(done); }); }); context('Private Guilds', () => { - let api, leader, createdGroup; + let leader, nonMember, createdGroup; - beforeEach((done) => { - generateUser({ - balance: 1, - }).then((user) => { - leader = user; - api = requester(user); - return generateGroup(leader, { - name: 'group name', + before((done) => { + createAndPopulateGroup({ + members: 1, + groupDetails: { + name: 'test guild', type: 'guild', privacy: 'private', - }); - }).then((group) => { - createdGroup = group; + }, + }).then((res) => { + leader = res.leader; + createdGroup = res.group; + return generateUser(); + }).then((user) => { + nonMember = user; done(); }).catch(done); }); - it('returns the group object', (done) => { - api.get(`/groups/${createdGroup._id}`) - .then((group) => { - expect(group._id).to.eql(createdGroup._id); - expect(group.name).to.eql(createdGroup.name); - expect(group.type).to.eql(createdGroup.type); - expect(group.privacy).to.eql(createdGroup.privacy); - done(); - }).catch(done); - }); - it('does not return the group object for a non-member', (done) => { - generateUser().then((user) => { - api = requester(user); - return api.get(`/groups/${createdGroup._id}`); - }).then((done)).catch((err) => { - expect(err.code).to.eql(404); - expect(err.text).to.eql('Group not found or you don\'t have access.'); - done() + let api = requester(nonMember); + api.get(`/groups/${createdGroup._id}`) + .then((done)).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done() }); }); }); - context('Parties', () => { - let api, leader, createdGroup; + context('Non-member of a party', () => { + let leader, nonMember, createdGroup; - beforeEach((done) => { - generateUser({ - balance: 1, - }).then((user) => { - leader = user; - api = requester(user); - return generateGroup(leader, { - name: 'group name', + before((done) => { + createAndPopulateGroup({ + members: 1, + groupDetails: { + name: 'test party', type: 'party', - }); - }).then((group) => { - createdGroup = group; + privacy: 'private', + }, + }).then((res) => { + leader = res.leader; + createdGroup = res.group; + return generateUser(); + }).then((user) => { + nonMember = user; done(); }).catch(done); }); - it('returns the group object', (done) => { - api.get(`/groups/${createdGroup._id}`) - .then((group) => { - expect(group._id).to.eql(createdGroup._id); - expect(group.name).to.eql(createdGroup.name); - expect(group.type).to.eql(createdGroup.type); - expect(group.privacy).to.eql(createdGroup.privacy); - done(); - }).catch(done); - }); - it('does not return the group object for a non-member', (done) => { - generateUser().then((user) => { - api = requester(user); - return api.get(`/groups/${createdGroup._id}`); - }).then((done)).catch((err) => { - expect(err.code).to.eql(404); - expect(err.text).to.eql('Group not found or you don\'t have access.'); - done() - }); + let api = requester(nonMember); + api.get(`/groups/${createdGroup._id}`) + .then((done)).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done() + }); + }); + }); + + context('Member of a party', () => { + let leader, member, createdGroup; + + before((done) => { + createAndPopulateGroup({ + members: 1, + groupDetails: { + name: 'test party', + type: 'party', + privacy: 'private', + }, + }).then((res) => { + leader = res.leader; + createdGroup = res.group; + member = res.members[0]; + done(); + }).catch(done); }); it('returns the user\'s party if an id of "party" is passed in', (done) => { + let api = requester(member); api.get('/groups/party') .then((group) => { expect(group._id).to.eql(createdGroup._id); @@ -208,4 +229,25 @@ describe('GET /groups/:id', () => { }).catch(done); }); }); + + context('Non-existent group', () => { + let user; + + beforeEach((done) => { + generateUser().then((_user) => { + user = _user; + done(); + }).catch(done); + }); + + it('returns error if group does not exist', (done) => { + let api = requester(user); + api.get('/groups/group-that-does-not-exist') + .then((done)).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done() + }); + }); + }); }); From 73b22081060a5626b6646b17ebe9c9ab10b55072 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Thu, 22 Oct 2015 20:02:08 -0500 Subject: [PATCH 47/53] Port final groups test to new structure --- test/api-legacy/groups.coffee | 139 -------------------- test/api/groups/POST-groups_id_join.test.js | 44 +++++++ 2 files changed, 44 insertions(+), 139 deletions(-) delete mode 100644 test/api-legacy/groups.coffee create mode 100644 test/api/groups/POST-groups_id_join.test.js diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee deleted file mode 100644 index 014cb65a84..0000000000 --- a/test/api-legacy/groups.coffee +++ /dev/null @@ -1,139 +0,0 @@ -'use strict' - -diff = require("deep-diff") - -Group = require("../../website/src/models/group").model -app = require("../../website/src/server") - -describe.skip "Guilds", -> - describe "Public Guilds", -> - before (done) -> - async.waterfall [ - (cb) -> - registerNewUser -> - User.findByIdAndUpdate user._id, {$set: { "balance": 10 } }, (err, _user) -> - cb() - , true - ], done - - context "joining groups", -> - it "makes user a group leader when group is empty", (done) -> - guildToEmptyAndAssignLeader = undefined - members = undefined - userToBecomeLeader = undefined - request.post(baseURL + "/groups").send( - name: "TestGuildToEmptyAndAssignLeader" - type: "guild", - privacy: "public" - ).end (err, res) -> - guildToEmptyAndAssignLeader = res.body - #Add members to guild - async.waterfall [ - (cb) -> - registerManyUsers 1, cb - - (_members, cb) -> - userToBecomeLeader = _members[0] - members = _members - inviteURL = baseURL + "/groups/" + guildToEmptyAndAssignLeader._id + "/invite" - request.post(inviteURL).send( - uuids: [userToBecomeLeader._id] - ) - .end -> - cb() - - (cb) -> - request.post(baseURL + "/groups/" + guildToEmptyAndAssignLeader._id + "/leave") - .send() - .end (err, res) -> - expectCode res, 204 - cb() - - (cb) -> - request.post(baseURL + "/groups/" + guildToEmptyAndAssignLeader._id + "/join") - .set("X-API-User", userToBecomeLeader._id) - .set("X-API-Key", userToBecomeLeader.apiToken) - .end (err, res) -> - expectCode res, 200 - cb() - - (cb) -> - request.get(baseURL + "/groups/" + guildToEmptyAndAssignLeader._id) - .set("X-API-User", userToBecomeLeader._id) - .set("X-API-Key", userToBecomeLeader.apiToken) - .send() - .end (err, res) -> - expectCode res, 200 - g = res.body - expect(g.leader._id).to.equal(userToBecomeLeader._id) - cb() - - ], done - - context "viewing", -> - guild = undefined - before (done) -> - async.waterfall [ - (cb) -> - registerNewUser -> - User.findByIdAndUpdate user._id, {$set: { "balance": 10 } }, (err, _user) -> - cb() - , true - (cb) -> - request.post(baseURL + "/groups").send( - name: "TestPublicGroup" - type: "guild" - privacy: "public" - ).end (err, res) -> - guild = res.body - expect(guild.members.length).to.equal 1 - expect(guild.leader).to.equal user._id - #Add members to guild - cb() - - (cb) -> - registerManyUsers 15, cb - - (_members, cb) -> - members = _members - - joinGuild = (member, callback) -> - request.post(baseURL + "/groups/" + guild._id + "/join") - .set("X-API-User", member._id) - .set("X-API-Key", member.apiToken) - .end -> - callback(null, null) - - async.map members, joinGuild, (err, results) -> cb() - - ], done - - context "is a member", -> - before (done) -> - registerNewUser -> - request.post(baseURL + "/groups/" + guild._id + "/join") - .end (err, res)-> - done() - , true - - it "includes user in public group member list", (done) -> - request.get(baseURL + "/groups/" + guild._id) - .end (err, res) -> - g = res.body - expect(g.members.length).to.equal 15 - userInGroup = _.find g.members, (member) -> return member._id == user._id - expect(userInGroup).to.exist - done() - - context "is not a member", -> - before (done) -> - registerNewUser done, true - - it "excludes user in public group member list", (done) -> - request.get(baseURL + "/groups/" + guild._id) - .end (err, res) -> - g = res.body - expect(g.members.length).to.equal 15 - userInGroup = _.find g.members, (member) -> return member._id == user._id - expect(userInGroup).to.not.exist - done() diff --git a/test/api/groups/POST-groups_id_join.test.js b/test/api/groups/POST-groups_id_join.test.js new file mode 100644 index 0000000000..921165aa72 --- /dev/null +++ b/test/api/groups/POST-groups_id_join.test.js @@ -0,0 +1,44 @@ +import { + createAndPopulateGroup, + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('POST /groups/:id/join', () => { + + context('user is already a member of the group', () => { + it('returns an error'); + }); + + context('public guild has no leader', () => { + let user, group; + + beforeEach((done) => { + createAndPopulateGroup({ + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'public', + }, + }).then((res) => { + group = res.group; + return requester(res.leader).post(`/groups/${group._id}/leave`); + }).then((res) => { + return generateUser(); + }).then((generatedUser) => { + user = generatedUser; + done(); + }).catch(done); + }); + + it('makes the joining user the leader', (done) => { + let api = requester(user); + api.post(`/groups/${group._id}/join`).then((result) => { + return api.get(`/groups/${group._id}`); + }).then((group) => { + expect(group.leader._id).to.eql(user._id); + done(); + }).catch(done); + }); + }); +}); From 27d9e60d0f796b2e7c7fdb02f6608b6a79971bc9 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Thu, 22 Oct 2015 20:05:31 -0500 Subject: [PATCH 48/53] Update api legacy test readme --- test/api-legacy/README.md | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/test/api-legacy/README.md b/test/api-legacy/README.md index 2f3dc40681..9157af554d 100644 --- a/test/api-legacy/README.md +++ b/test/api-legacy/README.md @@ -1,32 +1,5 @@ -# API Tests +# Legacy API Tests -Our API tests are written in [coffeescript](http://coffeescript.org/) using the [Mocha testing framework](http://mochajs.org/). +These tests have been deprecated. Any tests that you see in this folder should be converted to ES2015 and ported to the `/test/api` directory. -There's a variety of ways to run the tests: - -```bash -# Individually -mocha test/api/name_of_test.coffee -# The entire collection of api tests -mocha test/api -# As part of the whole test suite -npm test -``` - -### Modules - -Some modules are declared in the [api-helper.coffee](api-helper.coffee) file for use in any of the api tests: - -* `moment` - time manipulation -* `async` - run async processes, good for before blocks -* `lodash (_)` - many utilities -* `shared` - generate uuids -* `expect` - making assertions -* `User` - look up a User in the db - -### Helper Methods - -There are helper methods declared in the [api-helper.coffee](api-helper.coffee) file. Some useful methods contained there: - -* `registerNewUser(callback, main)` - Theres a global user variable that gets overwritten with the new user whenever you call `registerNewUser` unless you pass false in as the second argument. -* `registerManyUsers(number, callback)` - Good for testing things that require many users. The callback function returns new users as and array in the second argument. +Once all tests have been ported, this directory will be removed. From 6492554cf17c67c1b778504ca1e033820a5b66ff Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 23 Oct 2015 12:19:51 -0500 Subject: [PATCH 49/53] Add error handling for when mongo is not running. --- tasks/gulp-tests.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index 091c5fd5bd..64de69f135 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -37,7 +37,8 @@ let testBin = (string) => { }; gulp.task('test:prepare:mongo', (cb) => { - mongoose.connect(TEST_DB_URI, () => { + mongoose.connect(TEST_DB_URI, (err) => { + if (err) return cb(`Unable to connect to mongo database. Are you sure it's running? \n\n${err}`); mongoose.connection.db.dropDatabase(); mongoose.connection.close(); cb(); From 7ad2e6d1ff5cb181828c905fcccaa08156ba2ad7 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 23 Oct 2015 12:32:15 -0500 Subject: [PATCH 50/53] Add comments to helper methods --- test/helpers/api.helper.js | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index 2965ea19e7..01afef66f1 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -10,6 +10,9 @@ import superagent from 'superagent'; const API_TEST_SERVER_PORT = 3003; +// Sets up an abject that can make all REST requests +// If a user is passed in, the uuid and api token of +// the user are used to make the requests export function requester(user={}) { return { get: _requestMaker(user, 'get'), @@ -19,6 +22,13 @@ export function requester(user={}) { } }; +// Creates a new user and returns it +// If you need the user to have specific requirements, +// such as a balance > 0, just pass in the adjustment +// to the update object. If you want to adjust a nested +// paramter, such as the number of wolf eggs the user has, +// , you can do so by passing in the full path as a string: +// { 'items.eggs.Wolf': 10 } export function generateUser(update={}) { let username = generateUUID(); let password = 'password' @@ -40,6 +50,9 @@ export function generateUser(update={}) { }); }; +// Generates a new group. Requires a user object, which +// will will become the groups leader. Takes an update +// argument which will update group export function generateGroup(leader, update={}) { let request = _requestMaker(leader, 'post'); @@ -52,6 +65,20 @@ export function generateGroup(leader, update={}) { }); }; +// This is generate group + the ability to create +// real users to populate it. The settings object +// takes in: +// members: Number - the number of group members to create. Defaults to 0. +// inivtes: Number - the number of users to create and invite to the group. Defaults to 0. +// groupDetails: Object - how to initialize the group +// leaderDetails: Object - defaults for the leader, defaults with a gem balance so the user +// can create the group +// +// Returns an object with +// members: an array of user objects that correspond to the members of the group +// invitees: an array of user objects that correspond to the invitees of the group +// leader: the leader user object +// group: the group object export function createAndPopulateGroup(settings={}) { let request, leader, members, invitees, group; @@ -115,6 +142,8 @@ export function createAndPopulateGroup(settings={}) { }); }; +// Specifically helpful for the GET /groups tests, +// resets the db to an empty state and creates a tavern document export function resetHabiticaDB() { return new Promise((resolve, reject) => { mongo.connect('mongodb://localhost/habitrpg_test', (err, db) => { @@ -122,7 +151,6 @@ export function resetHabiticaDB() { db.dropDatabase((err) => { if (err) return reject(err); - // A fresh install of Habitica has a tavern group let groups = db.collection('groups'); groups.insertOne({ _id: 'habitrpg', From 5481178dbe3f40e9f98e79cb8c391329cd399053 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 23 Oct 2015 12:42:47 -0500 Subject: [PATCH 51/53] Move e2e tests higher up in test calls --- tasks/gulp-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index 64de69f135..e8252dbd5f 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -336,13 +336,13 @@ gulp.task('test:api:safe', ['test:prepare:mongo'], (done) => { }); gulp.task('test', [ + 'test:e2e:safe', 'test:common:safe', // 'test:content:safe', 'test:server_side:safe', 'test:karma:safe', 'test:api-legacy:safe', 'test:api:safe', - 'test:e2e:safe' ], () => { let totals = [0,0,0]; From 26ccde6e102d0ea4767697b859acc0e94bf69e12 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 23 Oct 2015 17:31:29 -0500 Subject: [PATCH 52/53] Create guidelines for writing api tests --- test/api/README.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 test/api/README.md diff --git a/test/api/README.md b/test/api/README.md new file mode 100644 index 0000000000..df495489ee --- /dev/null +++ b/test/api/README.md @@ -0,0 +1,83 @@ +# So you want to write API integration tests? + +That's great! This README will serve as a quick primer for style conventions and practices for these tests. + +## What is this? + +These are integration tests for the Habitica API. They are performed by making REST requests to the API's endpoints and asserting on the data that is returned. + +If the javascript looks weird to you, that's because it's written in [ES2015](http://www.ecma-international.org/ecma-262/6.0/) and transpiled by [Babel](https://babeljs.io/docs/learn-es2015/). + +## How to run the tests + +First, install gulp. + +```bash +$ npm install -g gulp +``` + +To run the api tests, make sure the mongo db is up and running and then type this on the command line: + +```bash +$ gulp test:api +``` + +It may take a little while to get going, since it requires the web server to start up before the tests can run. + +You can also run a watch command for the api tests. This will allow the tests to re-run automatically when you make changes in the `/test/api/` or `/website/src/` directories. + +```bash +$ gulp test:api:watch +``` + +One caveat. If you have a severe syntax error in your files the tests may fail to run, but they won't alert you that they are not running. If you ever find your test hanging for a while, run this to get the stackstrace. Once you've fixed the problem, you can resume running the watch comand. + +```bash +$ gulp test:api:safe +``` + +## Structure + +Each top level route has it's own directory. So, all the routes that begin with `/groups/` live in `/test/api/groups/`. + +Each test should: + + * encompase a single route + * begin with the REST parameter for the route + * display the full name of the route, swapping out `/` for `_` + * end with test.js + +So, for the `POST` route `/groups/:id/leave`, it would be + +```bash +POST-groups_id_leave.test.js +``` + +## Promises + +To mitigate [callback hell](http://callbackhell.com/) :imp:, we've written helper methods that [return promises](https://babeljs.io/docs/learn-es2015/#promises). This makes it very easy to chain together commands. All you need to do to make a subsequent request is return another promise and then call `.then((result) => {})` on the surrounding block, like so: + +```js +it('does something', (done) => { // Since it's an asynronous test, we need to pass the done callback + let request; + generateUser().then((user) => { + request = requester(user); + return request.post('/groups', { + type: 'party', + }); + }).then((party) => { // the result of the promise above is the argument of the function + return request.put(`/groups/${party._id}`, { + name: 'My party', + }); + }).then((result) => { + return request.get('/groups/party'); + }).then((party) => { + expect(party.name).to.eql('My party'); + done(); // Call this function to end the test + }).catch(done); // If there is an error, it'll call the function done with that error, which will fail the test +}); +``` + +## Questions? + +Ask in the [Aspiring Coder's Guild](https://habitica.com/#/options/groups/guilds/68d4a01e-db97-4786-8ee3-05d612c5af6f)! From e456bdb2ae4671efb83d2da7ec910a91db4735d1 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 23 Oct 2015 17:35:45 -0500 Subject: [PATCH 53/53] Revert npm bin command --- tasks/gulp-tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/gulp-tests.js b/tasks/gulp-tests.js index e8252dbd5f..8f8c3c82a8 100644 --- a/tasks/gulp-tests.js +++ b/tasks/gulp-tests.js @@ -23,7 +23,7 @@ const CONTENT_OPTIONS = {maxBuffer: 1024 * 500}; const KARMA_TEST_COMMAND = 'karma start'; const SERVER_SIDE_TEST_COMMAND = 'mocha test/server_side'; -const ISTANBUL_TEST_COMMAND = `istanbul cover -i "website/src/**" --dir coverage/api $(npm bin)/${LEGACY_API_TEST_COMMAND}`; +const ISTANBUL_TEST_COMMAND = `istanbul cover -i "website/src/**" --dir coverage/api ./node_modules/.bin/${LEGACY_API_TEST_COMMAND}`; /* Helper methods for reporting test summary */ let testResults = []; @@ -33,7 +33,7 @@ let testCount = (stdout, regexp) => { } let testBin = (string) => { - return `NODE_ENV=testing $(npm bin)/${string}`; + return `NODE_ENV=testing ./node_modules/.bin/${string}`; }; gulp.task('test:prepare:mongo', (cb) => {