PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/test/api.mocha.coffee

https://github.com/CrazyBeggar/habitrpg
CoffeeScript | 393 lines | 337 code | 44 blank | 12 comment | 3 complexity | 6a04258925a1cc049d4fdb3b1f613df2 MD5 | raw file
Possible License(s): GPL-3.0
  1. _ = require 'underscore'
  2. request = require 'superagent'
  3. expect = require 'expect.js'
  4. require 'coffee-script'
  5. conf = require("nconf")
  6. conf.argv().env().file({file: __dirname + '../config.json'}).defaults
  7. # Override normal ENV values with nconf ENV values (ENV values are used the same way without nconf)
  8. #FIXME can't get nconf file above to load...
  9. process.env.BASE_URL = conf.get("BASE_URL")
  10. process.env.FACEBOOK_KEY = conf.get("FACEBOOK_KEY")
  11. process.env.FACEBOOK_SECRET = conf.get("FACEBOOK_SECRET")
  12. process.env.NODE_DB_URI = 'mongodb://localhost/habitrpg'
  13. ## monkey-patch expect.js for better diffs on mocha
  14. ## see: https://github.com/LearnBoost/expect.js/pull/34
  15. origBe = expect.Assertion::be
  16. expect.Assertion::be = expect.Assertion::equal = (obj) ->
  17. @_expected = obj
  18. origBe.call this, obj
  19. # Custom modules
  20. character = require '../src/app/character'
  21. ###### Helpers & Variables ######
  22. model = null
  23. uuid = null
  24. taskPath = null
  25. baseURL = 'http://localhost:1337/api/v1'
  26. ###### Specs ######
  27. describe 'API', ->
  28. server = null
  29. store = null
  30. model = null
  31. user = null
  32. uid = null
  33. before (done) ->
  34. server = require '../src/server'
  35. server.listen '1337', '0.0.0.0'
  36. server.on 'listening', (data) ->
  37. store = server.habitStore
  38. #store.flush()
  39. model = store.createModel()
  40. model.set '_userId', uid = model.id()
  41. user = character.newUserObject()
  42. user.apiToken = model.id()
  43. model.session = {userId:uid}
  44. model.set "users.#{uid}", user
  45. delete model.session
  46. # Crappy hack to let server start before tests run
  47. setTimeout done, 2000
  48. describe 'Without token or user id', ->
  49. it '/api/v1/status', (done) ->
  50. request.get("#{baseURL}/status")
  51. .set('Accept', 'application/json')
  52. .end (res) ->
  53. expect(res.statusCode).to.be 200
  54. expect(res.body.status).to.be 'up'
  55. done()
  56. it '/api/v1/user', (done) ->
  57. request.get("#{baseURL}/user")
  58. .set('Accept', 'application/json')
  59. .end (res) ->
  60. expect(res.statusCode).to.be 401
  61. expect(res.body.err).to.be 'You must include a token and uid (user id) in your request'
  62. done()
  63. describe 'With token and user id', ->
  64. params = null
  65. currentUser = null
  66. before ->
  67. user = model.at("users.#{uid}")
  68. currentUser = user.get()
  69. params =
  70. title: 'Title'
  71. text: 'Text'
  72. type: 'habit'
  73. beforeEach ->
  74. currentUser = user.get()
  75. it 'GET /api/v1/user', (done) ->
  76. request.get("#{baseURL}/user")
  77. .set('Accept', 'application/json')
  78. .set('X-API-User', currentUser.id)
  79. .set('X-API-Key', currentUser.apiToken)
  80. .end (res) ->
  81. expect(res.body.err).to.be undefined
  82. expect(res.statusCode).to.be 200
  83. expect(res.body.id).not.to.be.empty()
  84. self = _.clone(currentUser)
  85. delete self.apiToken
  86. self.stats.toNextLevel = 150
  87. self.stats.maxHealth = 50
  88. expect(res.body).to.eql self
  89. done()
  90. it 'GET /api/v1/user/task/:id', (done) ->
  91. tid = _.pluck(currentUser.tasks, 'id')[0]
  92. request.get("#{baseURL}/user/task/#{tid}")
  93. .set('Accept', 'application/json')
  94. .set('X-API-User', currentUser.id)
  95. .set('X-API-Key', currentUser.apiToken)
  96. .end (res) ->
  97. expect(res.body.err).to.be undefined
  98. expect(res.statusCode).to.be 200
  99. expect(res.body).to.eql currentUser.tasks[tid]
  100. done()
  101. it 'POST /api/v1/user/task', (done) ->
  102. request.post("#{baseURL}/user/task")
  103. .set('Accept', 'application/json')
  104. .set('X-API-User', currentUser.id)
  105. .set('X-API-Key', currentUser.apiToken)
  106. .send(params)
  107. .end (res) ->
  108. query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken)
  109. query.fetch (err, user) ->
  110. expect(res.body.err).to.be undefined
  111. expect(res.statusCode).to.be 201
  112. expect(res.body.id).not.to.be.empty()
  113. # Ensure that user owns the newly created object
  114. expect(user.get().tasks[res.body.id]).to.be.an('object')
  115. done()
  116. it 'POST /api/v1/user/task (without type)', (done) ->
  117. request.post("#{baseURL}/user/task")
  118. .set('Accept', 'application/json')
  119. .set('X-API-User', currentUser.id)
  120. .set('X-API-Key', currentUser.apiToken)
  121. .send({})
  122. .end (res) ->
  123. expect(res.body.err).to.be 'type must be habit, todo, daily, or reward'
  124. expect(res.statusCode).to.be 400
  125. done()
  126. it 'POST /api/v1/user/task (only type)', (done) ->
  127. request.post("#{baseURL}/user/task")
  128. .set('Accept', 'application/json')
  129. .set('X-API-User', currentUser.id)
  130. .set('X-API-Key', currentUser.apiToken)
  131. .send(type: 'habit')
  132. .end (res) ->
  133. query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken)
  134. query.fetch (err, user) ->
  135. expect(res.body.err).to.be undefined
  136. expect(res.statusCode).to.be 201
  137. expect(res.body.id).not.to.be.empty()
  138. # Ensure that user owns the newly created object
  139. expect(user.get().tasks[res.body.id]).to.be.an('object')
  140. # Ensure that value gets set to 0 since not otherwise specified
  141. expect(user.get().tasks[res.body.id].value).to.be.equal(0)
  142. done()
  143. it 'PUT /api/v1/user/task/:id', (done) ->
  144. tid = _.pluck(currentUser.tasks, 'id')[0]
  145. request.put("#{baseURL}/user/task/#{tid}")
  146. .set('Accept', 'application/json')
  147. .set('X-API-User', currentUser.id)
  148. .set('X-API-Key', currentUser.apiToken)
  149. .send(text: 'bye')
  150. .end (res) ->
  151. expect(res.body.err).to.be undefined
  152. expect(res.statusCode).to.be 200
  153. currentUser.tasks[tid].text = 'bye'
  154. expect(res.body).to.eql currentUser.tasks[tid]
  155. done()
  156. it 'PUT /api/v1/user/task/:id (shouldnt update type)', (done) ->
  157. tid = _.pluck(currentUser.tasks, 'id')[1]
  158. type = if currentUser.tasks[tid].type is 'habit' then 'daily' else 'habit'
  159. request.put("#{baseURL}/user/task/#{tid}")
  160. .set('Accept', 'application/json')
  161. .set('X-API-User', currentUser.id)
  162. .set('X-API-Key', currentUser.apiToken)
  163. .send(type: type, text: 'fishman')
  164. .end (res) ->
  165. expect(res.body.err).to.be undefined
  166. expect(res.statusCode).to.be 200
  167. currentUser.tasks[tid].text = 'fishman'
  168. expect(res.body).to.eql currentUser.tasks[tid]
  169. done()
  170. it 'PUT /api/v1/user/task/:id (update notes)', (done) ->
  171. tid = _.pluck(currentUser.tasks, 'id')[2]
  172. request.put("#{baseURL}/user/task/#{tid}")
  173. .set('Accept', 'application/json')
  174. .set('X-API-User', currentUser.id)
  175. .set('X-API-Key', currentUser.apiToken)
  176. .send(text: 'hi',notes:'foobar matey')
  177. .end (res) ->
  178. expect(res.body.err).to.be undefined
  179. expect(res.statusCode).to.be 200
  180. currentUser.tasks[tid].text = 'hi'
  181. currentUser.tasks[tid].notes = 'foobar matey'
  182. expect(res.body).to.eql currentUser.tasks[tid]
  183. done()
  184. it 'GET /api/v1/user/tasks', (done) ->
  185. request.get("#{baseURL}/user/tasks")
  186. .set('Accept', 'application/json')
  187. .set('X-API-User', currentUser.id)
  188. .set('X-API-Key', currentUser.apiToken)
  189. .end (res) ->
  190. query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken)
  191. query.fetch (err, user) ->
  192. expect(res.body.err).to.be undefined
  193. expect(res.statusCode).to.be 200
  194. model.ref '_user', user
  195. tasks = []
  196. for type in ['habit','todo','daily','reward']
  197. model.refList "_#{type}List", "_user.tasks", "_user.#{type}Ids"
  198. tasks = tasks.concat model.get("_#{type}List")
  199. # Ensure that user owns the tasks
  200. expect(res.body.length).to.equal tasks.length
  201. # Ensure that the two sets are equal
  202. expect(_.difference(_.pluck(res.body,'id'), _.pluck(tasks,'id')).length).to.equal 0
  203. done()
  204. it 'GET /api/v1/user/tasks (todos)', (done) ->
  205. request.get("#{baseURL}/user/tasks")
  206. .set('Accept', 'application/json')
  207. .set('X-API-User', currentUser.id)
  208. .set('X-API-Key', currentUser.apiToken)
  209. .query(type:'todo')
  210. .end (res) ->
  211. query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken)
  212. query.fetch (err, user) ->
  213. expect(res.body.err).to.be undefined
  214. expect(res.statusCode).to.be 200
  215. model.ref '_user', user
  216. model.refList "_todoList", "_user.tasks", "_user.todoIds"
  217. tasks = model.get("_todoList")
  218. # Ensure that user owns the tasks
  219. expect(res.body.length).to.equal tasks.length
  220. # Ensure that the two sets are equal
  221. expect(_.difference(_.pluck(res.body,'id'), _.pluck(tasks,'id')).length).to.equal 0
  222. done()
  223. it 'DELETE /api/v1/user/task/:id', (done) ->
  224. tid = currentUser.habitIds[2]
  225. request.del("#{baseURL}/user/task/#{tid}")
  226. .set('Accept', 'application/json')
  227. .set('X-API-User', currentUser.id)
  228. .set('X-API-Key', currentUser.apiToken)
  229. .end (res) ->
  230. expect(res.body.err).to.be undefined
  231. expect(res.statusCode).to.be 204
  232. query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken)
  233. query.fetch (err, user) ->
  234. expect(user.get('habitIds').indexOf(tid)).to.be -1
  235. expect(user.get("tasks.#{tid}")).to.be undefined
  236. done()
  237. it 'DELETE /api/v1/user/task/:id (no task found)', (done) ->
  238. tid = "adsfasdfjunkshouldntbeatask"
  239. request.del("#{baseURL}/user/task/#{tid}")
  240. .set('Accept', 'application/json')
  241. .set('X-API-User', currentUser.id)
  242. .set('X-API-Key', currentUser.apiToken)
  243. .end (res) ->
  244. expect(res.statusCode).to.be 400
  245. expect(res.body.err).to.be 'No task found.'
  246. done()
  247. it 'POST /api/v1/user/task/:id/up (habit)', (done) ->
  248. tid = currentUser.habitIds[0]
  249. request.post("#{baseURL}/user/task/#{tid}/up")
  250. .set('Accept', 'application/json')
  251. .set('X-API-User', currentUser.id)
  252. .set('X-API-Key', currentUser.apiToken)
  253. .send({})
  254. .end (res) ->
  255. expect(res.body.err).to.be undefined
  256. expect(res.statusCode).to.be 200
  257. expect(res.body).to.eql { gp: 1, exp: 7.5, lvl: 1, hp: 50, delta: 1 }
  258. done()
  259. it 'POST /api/v1/user/task/:id/up (daily)', (done) ->
  260. tid = currentUser.dailyIds[0]
  261. request.post("#{baseURL}/user/task/#{tid}/up")
  262. .set('Accept', 'application/json')
  263. .set('X-API-User', currentUser.id)
  264. .set('X-API-Key', currentUser.apiToken)
  265. .send({})
  266. .end (res) ->
  267. expect(res.body.err).to.be undefined
  268. expect(res.statusCode).to.be 200
  269. expect(res.body).to.eql { gp: 2, exp: 15, lvl: 1, hp: 50, delta: 1 }
  270. query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken)
  271. query.fetch (err, user) ->
  272. expect(user.get("tasks.#{tid}.completed")).to.be true
  273. done()
  274. it 'POST /api/v1/user/task (array)', (done) ->
  275. habitId = currentUser.habitIds[0]
  276. dailyId = currentUser.dailyIds[0]
  277. arr = [{
  278. id: habitId
  279. text: 'hello'
  280. notes: 'note'
  281. },{
  282. text: 'new task'
  283. notes: 'notes!'
  284. },{
  285. id: dailyId
  286. del: true
  287. }]
  288. request.post("#{baseURL}/user/tasks")
  289. .set('Accept', 'application/json')
  290. .set('X-API-User', currentUser.id)
  291. .set('X-API-Key', currentUser.apiToken)
  292. .send(arr)
  293. .end (res) ->
  294. expect(res.body.err).to.be undefined
  295. expect(res.statusCode).to.be 201
  296. expect(res.body[0]).to.eql {id: habitId,text: 'hello',notes: 'note'}
  297. expect(res.body[1].id).to.be.a 'string'
  298. expect(res.body[1].text).to.be 'new task'
  299. expect(res.body[1].notes).to.be 'notes!'
  300. expect(res.body[2]).to.eql deleted: true
  301. query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken)
  302. query.fetch (err, user) ->
  303. expect(user.get("tasks.#{habitId}")).to.eql {id: habitId,text: 'hello',notes: 'note'}
  304. expect(user.get("tasks.#{dailyId}")).to.be undefined
  305. expect(user.get("tasks.#{res.body[1].id}")).to.eql id: res.body[1].id, text: 'new task', notes: 'notes!'
  306. done()
  307. it 'PUT /api/v1/user', (done) ->
  308. userBefore = {}
  309. query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken)
  310. query.fetch (err, user) -> userBefore = user.get()
  311. habitId = currentUser.habitIds[0]
  312. dailyId = currentUser.dailyIds[0]
  313. userUpdates =
  314. stats:
  315. hp: 30
  316. flags:
  317. itemsEnabled: true
  318. tasks: [{
  319. id: habitId
  320. text: 'hello2'
  321. notes: 'note2'
  322. },{
  323. text: 'new task2'
  324. notes: 'notes2'
  325. },{
  326. id: dailyId
  327. del: true
  328. }]
  329. request.put("#{baseURL}/user")
  330. .set('Accept', 'application/json')
  331. .set('X-API-User', currentUser.id)
  332. .set('X-API-Key', currentUser.apiToken)
  333. .send(user: userUpdates)
  334. .end (res) ->
  335. expect(res.body.err).to.be undefined
  336. expect(res.statusCode).to.be 201
  337. tasks = res.body.tasks
  338. expect(_.findWhere(tasks,{id:habitId})).to.eql {id: habitId,text: 'hello2',notes: 'note2'}
  339. foundNewTask = _.findWhere(tasks,{text:'new task2'})
  340. expect(foundNewTask.text).to.be 'new task2'
  341. expect(foundNewTask.notes).to.be 'notes2'
  342. found = _.findWhere(res.body.tasks, {id:dailyId})
  343. expect(found).to.not.be.ok()
  344. query.fetch (err, user) ->
  345. expect(user.get("tasks.#{habitId}")).to.eql {id: habitId, text: 'hello2',notes: 'note2'}
  346. expect(user.get("tasks.#{dailyId}")).to.be undefined
  347. tasks = res.body.tasks
  348. expect(user.get("tasks.#{foundNewTask.id}")).to.eql id: foundNewTask.id, text: 'new task2', notes: 'notes2'
  349. done()