crud.spec.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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('error', true);
  87. });
  88. });
  89. describe('DOC_READ', () => {
  90. it('should set the route to loading', () => {
  91. const state = {};
  92. const route = 'employees';
  93. const action = docRead(route);
  94. const result = crud(state, action);
  95. expect(result).to.have.property(route);
  96. expect(result[route]).to.be.an('object');
  97. expect(result[route]).to.have.property('loading', true);
  98. expect(result[route]).to.have.property('items');
  99. expect(result[route].items).to.be.an('array').of.length(0);
  100. });
  101. });
  102. describe('DOC_READ_RESPONDED', () => {
  103. const route = 'employees';
  104. const state = {
  105. [route]: {
  106. loading: true,
  107. items: []
  108. }
  109. };
  110. const actualId = 'a0b444511123';
  111. const response = {
  112. data: {
  113. [route]: [
  114. {
  115. id: actualId,
  116. name: 'John Doe',
  117. email: 'john.doe@mubaloo.com'
  118. }
  119. ]
  120. }
  121. };
  122. const actionSuccess = docReadResponded(route, null, response);
  123. const resultSuccess = crud(state, actionSuccess);
  124. it('should add the response to state', () => {
  125. expect(resultSuccess[route].items).to.have.length(1);
  126. expect(resultSuccess[route].items[0]).to.have.property('id', actualId);
  127. expect(resultSuccess[route].items[0]).to.have.property('name', 'John Doe');
  128. expect(resultSuccess[route].items[0]).to.have.property('email', 'john.doe@mubaloo.com');
  129. });
  130. it('should set loading to false', () => {
  131. expect(resultSuccess[route].loading).to.equal(false);
  132. });
  133. it('should set an error status if an error occurred', () => {
  134. const error = new Error('something bad happened');
  135. const action = docReadResponded(route, error, null);
  136. const resultError = crud(state, action);
  137. expect(resultError[route].items).to.have.length(0);
  138. expect(resultError[route].error).to.equal(true);
  139. expect(resultError[route].loading).to.equal(false);
  140. });
  141. });
  142. describe('DOC_UPDATED', () => {
  143. const route = 'employees';
  144. const actualId = 'a0b444511123';
  145. const action = docUpdated(route, actualId, {
  146. name: 'John Doe',
  147. email: 'john.doe@mubaloo.com'
  148. });
  149. it('should optimistically update the item (pending) in state', () => {
  150. const state = {
  151. [route]: {
  152. items: [
  153. {
  154. id: actualId,
  155. name: 'Jack',
  156. email: 'jack@mubaloo.com'
  157. }
  158. ]
  159. }
  160. };
  161. const result = crud(state, action);
  162. expect(result[route].items).to.have.length(1);
  163. expect(result[route].items[0]).to.have.property('pending', true);
  164. expect(result[route].items[0]).to.deep.equal({
  165. id: actualId,
  166. pending: true,
  167. name: 'John Doe',
  168. email: 'john.doe@mubaloo.com'
  169. });
  170. });
  171. it('should not do anything if the state is loading', () => {
  172. const state = {
  173. [route]: {
  174. loading: true,
  175. items: []
  176. }
  177. };
  178. const result = crud(state, action);
  179. expect(result[route].items).to.have.length(0);
  180. });
  181. });
  182. describe('DOC_UPDATE_RESPONDED', () => {
  183. const route = 'employees';
  184. const actualId = 'a0b444511123';
  185. const state = {
  186. [route]: {
  187. items: [
  188. {
  189. id: actualId,
  190. pending: true,
  191. name: 'John Doe',
  192. email: 'john.doe@mubaloo.com'
  193. }
  194. ]
  195. }
  196. };
  197. const response = {
  198. data: {
  199. ok: true
  200. }
  201. };
  202. const actionSuccess = docUpdateResponded(route, actualId, null, response);
  203. it('should mark an optimistically updated document as successful, if the response was success', () => {
  204. const result = crud(state, actionSuccess);
  205. expect(result[route].items).to.have.length(1);
  206. expect(result[route].items[0]).to.have.property('pending', false);
  207. });
  208. it('should set an error status if an error occurred', () => {
  209. const error = new Error('something bad happened');
  210. const action = docUpdateResponded(route, actualId, error, null);
  211. const result = crud(state, action);
  212. expect(result[route].items).to.have.length(1);
  213. expect(result[route]).to.have.property('error', true);
  214. expect(result[route].items[0]).to.have.property('pending', false);
  215. });
  216. });
  217. describe('DOC_DELETED', () => {
  218. const route = 'employees';
  219. const actualId = 'a0b444511123';
  220. it('should mark the document as pending', () => {
  221. const state = {
  222. [route]: {
  223. items: [
  224. {
  225. id: actualId,
  226. pending: false,
  227. name: 'John Doe',
  228. email: 'john.doe@mubaloo.com'
  229. }
  230. ]
  231. }
  232. };
  233. const action = docDeleted(route, actualId);
  234. const result = crud(state, action);
  235. expect(result[route].items).to.have.length(1);
  236. expect(result[route].items[0]).to.have.property('pending', true);
  237. });
  238. });
  239. describe('DOC_DELETE_RESPONDED', () => {
  240. const route = 'employees';
  241. const actualId = 'a0b444511123';
  242. const state = {
  243. [route]: {
  244. items: [
  245. {
  246. id: actualId,
  247. pending: true,
  248. name: 'John Doe',
  249. email: 'john.doe@mubaloo.com'
  250. }
  251. ]
  252. }
  253. };
  254. it('should remove the document if the response was success', () => {
  255. const response = {
  256. data: {
  257. ok: true
  258. }
  259. };
  260. const action = docDeleteResponded(route, actualId, null, response);
  261. const result = crud(state, action);
  262. expect(result[route].items).to.have.length(0);
  263. });
  264. it('should set an error status if an error occurred', () => {
  265. const error = new Error('something bad happened');
  266. const action = docDeleteResponded(route, actualId, error, null);
  267. const result = crud(state, action);
  268. expect(result[route]).to.have.property('error', true);
  269. expect(result[route].items).to.have.length(1);
  270. expect(result[route].items[0]).to.have.property('pending', false);
  271. });
  272. });
  273. });