crud.spec.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. import { expect } from 'chai';
  2. import { initialState, crud } from 'reducers/crud';
  3. import {
  4. docCreated,
  5. docCreateResponded,
  6. docRead,
  7. docReadResponded,
  8. docUpdated,
  9. docUpdateResponded,
  10. docDeleted,
  11. docDeleteResponded
  12. } from 'actions/crud';
  13. describe('CRUD reducer', () => {
  14. it('should return the initial state by default', () => {
  15. // eslint-disable-next-line no-undefined
  16. expect(crud(undefined, null)).to.equal(initialState);
  17. });
  18. describe('DOC_CREATED', () => {
  19. const route = 'employees';
  20. const pendingId = 'foo19123afvj';
  21. const action = docCreated(route, pendingId, {
  22. name: 'John Doe',
  23. email: 'john.doe@mubaloo.com'
  24. });
  25. it('should create an optimistic update (pending) in state', () => {
  26. const state = {};
  27. const result = crud(state, action);
  28. expect(result).to.have.property(route);
  29. expect(result[route]).to.be.an('object');
  30. expect(result[route]).to.have.property('items');
  31. expect(result[route].items).to.be.an('array').of.length(1);
  32. expect(result[route].items[0]).to.be.an('object');
  33. expect(result[route].items[0]).to.deep.equal({
  34. id: pendingId,
  35. pending: true,
  36. name: 'John Doe',
  37. email: 'john.doe@mubaloo.com'
  38. });
  39. });
  40. it('should not do anything if the state is loading', () => {
  41. const state = {
  42. [route]: {
  43. loading: true,
  44. items: []
  45. }
  46. };
  47. const result = crud(state, action);
  48. expect(result[route].items).to.have.length(0);
  49. });
  50. });
  51. describe('DOC_CREATE_RESPONDED', () => {
  52. const route = 'employees';
  53. const pendingId = 'foo19123afvj';
  54. const state = {
  55. [route]: {
  56. items: [
  57. {
  58. id: pendingId,
  59. pending: true,
  60. name: 'John Doe',
  61. email: 'john.doe@mubaloo.com'
  62. }
  63. ]
  64. }
  65. };
  66. const actualId = 'a0b444511123';
  67. const response = {
  68. data: {
  69. id: actualId,
  70. name: 'John Doe',
  71. email: 'john.doe@mubaloo.com'
  72. }
  73. };
  74. const actionSuccess = docCreateResponded(route, pendingId, null, response);
  75. it('should mark an optimistically created document as successful, if the response was success', () => {
  76. const result = crud(state, actionSuccess);
  77. expect(result[route].items).to.have.length(1);
  78. expect(result[route].items[0]).to.have.property('id', actualId);
  79. expect(result[route].items[0]).to.have.property('pending', false);
  80. });
  81. it('should remove the pending item and set an error status if an error occurred', () => {
  82. const error = new Error('something bad happened');
  83. const action = docCreateResponded(route, pendingId, error, null);
  84. const result = crud(state, action);
  85. expect(result[route].items).to.have.length(0);
  86. expect(result[route]).to.have.property('loading', false);
  87. expect(result[route]).to.have.property('error', true);
  88. });
  89. });
  90. describe('DOC_READ', () => {
  91. it('should set the route to loading', () => {
  92. const state = {};
  93. const route = 'employees';
  94. const action = docRead(route);
  95. const result = crud(state, action);
  96. expect(result).to.have.property(route);
  97. expect(result[route]).to.be.an('object');
  98. expect(result[route]).to.have.property('loading', true);
  99. expect(result[route]).to.have.property('items');
  100. expect(result[route].items).to.be.an('array').of.length(0);
  101. });
  102. });
  103. describe('DOC_READ_RESPONDED', () => {
  104. const route = 'employees';
  105. const state = {
  106. [route]: {
  107. loading: true,
  108. items: []
  109. }
  110. };
  111. const actualId = 'a0b444511123';
  112. const response = {
  113. data: {
  114. [route]: [
  115. {
  116. id: actualId,
  117. name: 'John Doe',
  118. email: 'john.doe@mubaloo.com'
  119. }
  120. ]
  121. }
  122. };
  123. const actionSuccess = docReadResponded(route, null, response);
  124. const resultSuccess = crud(state, actionSuccess);
  125. it('should add the response to state', () => {
  126. expect(resultSuccess[route].items).to.have.length(1);
  127. expect(resultSuccess[route].items[0]).to.have.property('id', actualId);
  128. expect(resultSuccess[route].items[0]).to.have.property('name', 'John Doe');
  129. expect(resultSuccess[route].items[0]).to.have.property('email', 'john.doe@mubaloo.com');
  130. });
  131. it('should set loading to false', () => {
  132. expect(resultSuccess[route].loading).to.equal(false);
  133. });
  134. it('should set an error status if an error occurred', () => {
  135. const error = new Error('something bad happened');
  136. const action = docReadResponded(route, error, null);
  137. const resultError = crud(state, action);
  138. expect(resultError[route].items).to.have.length(0);
  139. expect(resultError[route].error).to.equal(true);
  140. expect(resultError[route].loading).to.equal(false);
  141. });
  142. });
  143. describe('DOC_UPDATED', () => {
  144. const route = 'employees';
  145. const actualId = 'a0b444511123';
  146. const action = docUpdated(route, actualId, {
  147. name: 'John Doe',
  148. email: 'john.doe@mubaloo.com'
  149. });
  150. it('should optimistically update the item (pending) in state', () => {
  151. const state = {
  152. [route]: {
  153. items: [
  154. {
  155. id: actualId,
  156. name: 'Jack',
  157. email: 'jack@mubaloo.com'
  158. }
  159. ]
  160. }
  161. };
  162. const result = crud(state, action);
  163. expect(result[route].items).to.have.length(1);
  164. expect(result[route].items[0]).to.have.property('pending', true);
  165. expect(result[route].items[0]).to.deep.equal({
  166. id: actualId,
  167. pending: true,
  168. name: 'John Doe',
  169. email: 'john.doe@mubaloo.com'
  170. });
  171. });
  172. it('should not do anything if the state is loading', () => {
  173. const state = {
  174. [route]: {
  175. loading: true,
  176. items: []
  177. }
  178. };
  179. const result = crud(state, action);
  180. expect(result[route].items).to.have.length(0);
  181. });
  182. });
  183. describe('DOC_UPDATE_RESPONDED', () => {
  184. const route = 'employees';
  185. const actualId = 'a0b444511123';
  186. const state = {
  187. [route]: {
  188. items: [
  189. {
  190. id: actualId,
  191. pending: true,
  192. name: 'John Doe',
  193. email: 'john.doe@mubaloo.com'
  194. }
  195. ]
  196. }
  197. };
  198. const response = {
  199. data: {
  200. ok: true
  201. }
  202. };
  203. const actionSuccess = docUpdateResponded(route, actualId, null, response);
  204. it('should mark an optimistically updated document as successful, if the response was success', () => {
  205. const result = crud(state, actionSuccess);
  206. expect(result[route].items).to.have.length(1);
  207. expect(result[route].items[0]).to.have.property('pending', false);
  208. });
  209. it('should set an error status if an error occurred', () => {
  210. const error = new Error('something bad happened');
  211. const action = docUpdateResponded(route, actualId, error, null);
  212. const result = crud(state, action);
  213. expect(result[route].items).to.have.length(1);
  214. expect(result[route]).to.have.property('error', true);
  215. expect(result[route].items[0]).to.have.property('pending', false);
  216. });
  217. });
  218. describe('DOC_DELETED', () => {
  219. const route = 'employees';
  220. const actualId = 'a0b444511123';
  221. it('should mark the document as pending', () => {
  222. const state = {
  223. [route]: {
  224. items: [
  225. {
  226. id: actualId,
  227. pending: false,
  228. name: 'John Doe',
  229. email: 'john.doe@mubaloo.com'
  230. }
  231. ]
  232. }
  233. };
  234. const action = docDeleted(route, actualId);
  235. const result = crud(state, action);
  236. expect(result[route].items).to.have.length(1);
  237. expect(result[route].items[0]).to.have.property('pending', true);
  238. });
  239. });
  240. describe('DOC_DELETE_RESPONDED', () => {
  241. const route = 'employees';
  242. const actualId = 'a0b444511123';
  243. const state = {
  244. [route]: {
  245. items: [
  246. {
  247. id: actualId,
  248. pending: true,
  249. name: 'John Doe',
  250. email: 'john.doe@mubaloo.com'
  251. }
  252. ]
  253. }
  254. };
  255. it('should remove the document if the response was success', () => {
  256. const response = {
  257. data: {
  258. ok: true
  259. }
  260. };
  261. const action = docDeleteResponded(route, actualId, null, response);
  262. const result = crud(state, action);
  263. expect(result[route].items).to.have.length(0);
  264. });
  265. it('should set an error status if an error occurred', () => {
  266. const error = new Error('something bad happened');
  267. const action = docDeleteResponded(route, actualId, error, null);
  268. const result = crud(state, action);
  269. expect(result[route]).to.have.property('error', true);
  270. expect(result[route].items).to.have.length(1);
  271. expect(result[route].items[0]).to.have.property('pending', false);
  272. });
  273. });
  274. });