category.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. process.env.NODE_ENV = 'test'
  2. let chai = require('chai')
  3. let server = require('../server')
  4. let should = chai.should()
  5. let expect = chai.expect
  6. let { sequelize, Thread } = require('../models')
  7. const Errors = require('../lib/errors.js')
  8. chai.use(require('chai-http'))
  9. chai.use(require('chai-things'))
  10. describe('Category', () => {
  11. //Wait for app to start before commencing
  12. before((done) => {
  13. if(server.locals.appStarted) done()
  14. server.on('appStarted', () => {
  15. done()
  16. })
  17. })
  18. //Delete all rows in table after
  19. //tests completed
  20. after((done) => {
  21. sequelize.sync({ force: true })
  22. .then(() => {
  23. done(null);
  24. })
  25. .catch((err) => {
  26. done(err)
  27. })
  28. })
  29. describe('POST /category', () => {
  30. let agent = chai.request.agent(server)
  31. it('should add a new category if logged in', async () => {
  32. await agent
  33. .post('/api/v1/user')
  34. .set('content-type', 'application/json')
  35. .send({
  36. username: 'adminaccount',
  37. password: 'password',
  38. admin: true
  39. })
  40. let res = await agent
  41. .post('/api/v1/category')
  42. .set('content-type', 'application/json')
  43. .send({ name: 'category' })
  44. res.should.be.json
  45. res.should.have.status(200)
  46. res.body.should.have.property('name', 'category')
  47. res.body.should.have.property('color')
  48. })
  49. it('should have an "underscored" value field', async () => {
  50. let res = await agent
  51. .post('/api/v1/category')
  52. .set('content-type', 'application/json')
  53. .send({ name: ' another category here ' })
  54. res.should.be.json
  55. res.should.have.status(200)
  56. res.body.should.have.property('name', ' another category here ')
  57. res.body.should.have.property('value', 'ANOTHER_CATEGORY_HERE')
  58. })
  59. it('should return an error if category already exists', async () => {
  60. try {
  61. let res = await agent
  62. .post('/api/v1/category')
  63. .set('content-type', 'application/json')
  64. .send({ name: 'category' })
  65. res.should.be.json
  66. res.should.have.status(400)
  67. res.body.errors.should.contain.something.that.deep.equals(Errors.categoryAlreadyExists)
  68. } catch (res) {
  69. res.should.have.status(400)
  70. res.response.body.errors.should.contain.something.that.deep.equals(Errors.categoryAlreadyExists)
  71. }
  72. })
  73. it('should return an error if missing category parameter', done => {
  74. agent
  75. .post('/api/v1/category')
  76. .set('content-type', 'application/json')
  77. .send({})
  78. .end((err, res) => {
  79. res.should.be.json
  80. res.should.have.status(400)
  81. res.body.errors.should.contain.something.that.has.property('message', 'name cannot be null')
  82. done()
  83. })
  84. })
  85. it('should return an error if category parameter has no length', done => {
  86. agent
  87. .post('/api/v1/category')
  88. .set('content-type', 'application/json')
  89. .send({ name: '' })
  90. .end((err, res) => {
  91. res.should.be.json
  92. res.should.have.status(400)
  93. res.body.errors.should.contain.something.that.has.property('message', 'The category name can\'t be empty')
  94. done()
  95. })
  96. })
  97. it('should return an error if not an admin account', async () => {
  98. let agent = chai.request.agent(server)
  99. await agent
  100. .post('/api/v1/user')
  101. .set('content-type', 'application/json')
  102. .send({
  103. username: 'username',
  104. password: 'password',
  105. })
  106. try {
  107. let res = await agent
  108. .post('/api/v1/category')
  109. .set('content-type', 'application/json')
  110. .send({ name: 'category1' })
  111. res.should.be.json
  112. res.should.have.status(401)
  113. res.body.errors.should.contain.something.that.deep.equals(Errors.requestNotAuthorized)
  114. } catch (res) {
  115. res.should.have.status(401)
  116. JSON.parse(res.response.text).errors.should.contain.something.that.deep.equals(Errors.requestNotAuthorized)
  117. }
  118. })
  119. it('should return an error if not logged', async () => {
  120. try {
  121. await chai.request(server)
  122. .post('/api/v1/category')
  123. .set('content-type', 'application/json')
  124. .send({ name: 'category1' })
  125. res.should.be.json
  126. res.should.have.status(401)
  127. res.body.errors.should.contain.something.that.deep.equals(Errors.requestNotAuthorized)
  128. } catch (res) {
  129. res.should.have.status(401)
  130. JSON.parse(res.response.text).errors.should.contain.something.that.deep.equals(Errors.requestNotAuthorized)
  131. }
  132. })
  133. })
  134. describe('GET /category', () => {
  135. before(async () => {
  136. let agent = chai.request.agent(server)
  137. await agent
  138. .post('/api/v1/user/adminaccount/login')
  139. .set('content-type', 'application/json')
  140. .send({ password: 'password' })
  141. await agent
  142. .post('/api/v1/category')
  143. .set('content-type', 'application/json')
  144. .send({ name: 'another_category' })
  145. await agent
  146. .post('/api/v1/category')
  147. .set('content-type', 'application/json')
  148. .send({ name: 'category with spaces' })
  149. })
  150. it('should return all categories', async () => {
  151. let res = await chai.request(server)
  152. .get('/api/v1/category')
  153. res.should.be.json
  154. res.should.have.status(200)
  155. res.body.should.contain.an.item.with.property('name', 'category')
  156. res.body.should.contain.an.item.with.property('name', 'another_category')
  157. res.body.should.contain.an.item.with.property('name', 'category with spaces')
  158. })
  159. })
  160. describe('GET /category/:category', () => {
  161. it('should return allow pagination for category ALL', async () => {
  162. let agent = chai.request.agent(server)
  163. await agent
  164. .post('/api/v1/user/adminaccount/login')
  165. .set('content-type', 'application/json')
  166. .send({ password: 'password' })
  167. await agent
  168. .post('/api/v1/category')
  169. .set('content-type', 'application/json')
  170. .send({ name: 'pagination1' })
  171. await agent
  172. .post('/api/v1/category')
  173. .set('content-type', 'application/json')
  174. .send({ name: 'pagination2' })
  175. for(var i = 0; i < 30; i++) {
  176. let category = 'pagination1'
  177. if(i % 2) category = 'pagination2'
  178. let thread = await agent
  179. .post('/api/v1/thread')
  180. .set('content-type', 'application/json')
  181. .send({ name: `THREAD ${i}`, category })
  182. await agent
  183. .post('/api/v1/post')
  184. .set('content-type', 'application/json')
  185. .send({ content: `POST ${i}`, threadId: thread.body.id })
  186. }
  187. let pageOne = await agent.get('/api/v1/category/ALL')
  188. let pageTwo = await agent.get(pageOne.body.meta.nextURL)
  189. let pageThree = await agent.get(pageTwo.body.meta.nextURL)
  190. pageOne.body.Threads.should.have.length(10)
  191. pageOne.body.meta.should.have.property('nextThreadsCount', 10)
  192. pageOne.body.Threads[0].Posts[0].should.have.property('content', '<p>POST 29</p>\n')
  193. pageTwo.body.Threads.should.have.length(10)
  194. pageTwo.body.meta.should.have.property('nextThreadsCount', 10)
  195. pageTwo.body.Threads[0].Posts[0].should.have.property('content', '<p>POST 19</p>\n')
  196. pageThree.body.Threads.should.have.length(10)
  197. pageThree.body.meta.should.have.property('nextThreadsCount', 0)
  198. pageThree.body.Threads[0].Posts[0].should.have.property('content', '<p>POST 9</p>\n')
  199. pageThree.body.Threads[9].Posts[0].should.have.property('content', '<p>POST 0</p>\n')
  200. expect(pageThree.body.meta.nextURL).to.be.null
  201. })
  202. it('should return all threads in a category', async () => {
  203. let agent = chai.request.agent(server)
  204. await agent
  205. .post('/api/v1/user/adminaccount/login')
  206. .set('content-type', 'application/json')
  207. .send({ password: 'password' })
  208. for(var i = 0; i < 3; i++) {
  209. let thread = await agent
  210. .post('/api/v1/thread')
  211. .set('content-type', 'application/json')
  212. .send({ name: 'thread ' + i, category: 'category' })
  213. await agent
  214. .post('/api/v1/post')
  215. .set('content-type', 'application/json')
  216. .send({ content: 'content here ' + i, threadId: thread.body.id })
  217. }
  218. let res = await chai.request(server)
  219. .get('/api/v1/category/CATEGORY')
  220. res.should.be.json
  221. res.should.have.status(200)
  222. res.body.should.have.property('name', 'category')
  223. res.body.Threads.should.have.property('length', 3)
  224. res.body.Threads.should.contain.an.item.with.deep.property('User.username', 'adminaccount')
  225. res.body.Threads[0].Posts[0].should.have.property('content', '<p>content here 2</p>\n')
  226. res.body.Threads[1].Posts[0].should.have.property('content', '<p>content here 1</p>\n')
  227. res.body.Threads[2].Posts[0].should.have.property('content', '<p>content here 0</p>\n')
  228. res.body.Threads.should.contain.an.item.with.deep.property('Posts.0.User.username', 'adminaccount')
  229. })
  230. it('should return all threads in a category with spaces', async () => {
  231. let agent = chai.request.agent(server)
  232. await agent
  233. .post('/api/v1/user/adminaccount/login')
  234. .set('content-type', 'application/json')
  235. .send({ password: 'password' })
  236. let thread = await agent
  237. .post('/api/v1/thread')
  238. .set('content-type', 'application/json')
  239. .send({ name: 'thread', category: 'CATEGORY_WITH_SPACES' })
  240. await agent
  241. .post('/api/v1/post')
  242. .set('content-type', 'application/json')
  243. .send({ content: 'content here', threadId: thread.body.id })
  244. let res = await chai.request(server)
  245. .get('/api/v1/category/CATEGORY_WITH_SPACES')
  246. res.should.be.json
  247. res.should.have.status(200)
  248. res.body.should.have.property('name', 'category with spaces')
  249. res.body.Threads.should.have.property('length', 1)
  250. res.body.Threads.should.contain.an.item.with.deep.property('User.username', 'adminaccount')
  251. res.body.Threads[0].Posts[0].should.have.property('content', '<p>content here</p>\n')
  252. res.body.Threads.should.contain.an.item.with.deep.property('Posts.0.User.username', 'adminaccount')
  253. })
  254. it('should return an error if category does not exist', async () => {
  255. try {
  256. let res = await chai.request(server)
  257. .get('/api/v1/category/not_real')
  258. res.should.be.json
  259. res.should.have.status(400)
  260. res.body.errors.should.contain.something.that.deep.equals(Errors.invalidParameter('id', 'category does not exist'))
  261. } catch (res) {
  262. let body = JSON.parse(res.response.text)
  263. res.should.have.status(400)
  264. body.errors.should.contain.something.that.deep.equals(Errors.invalidParameter('id', 'category does not exist'))
  265. }
  266. })
  267. })
  268. })