|
|
@@ -0,0 +1,359 @@
|
|
|
+import { expect } from 'chai';
|
|
|
+
|
|
|
+import { initialState, crud } from 'reducers/crud';
|
|
|
+
|
|
|
+import {
|
|
|
+ docCreated,
|
|
|
+ docCreateResponded,
|
|
|
+ docRead,
|
|
|
+ docReadResponded,
|
|
|
+ docUpdated,
|
|
|
+ docUpdateResponded,
|
|
|
+ docDeleted,
|
|
|
+ docDeleteResponded
|
|
|
+} from 'actions/crud';
|
|
|
+
|
|
|
+describe('CRUD reducer', () => {
|
|
|
+ it('should return the initial state by default', () => {
|
|
|
+ // eslint-disable-next-line no-undefined
|
|
|
+ expect(crud(undefined, null)).to.equal(initialState);
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('DOC_CREATED', () => {
|
|
|
+ const route = 'employees';
|
|
|
+
|
|
|
+ const pendingId = 'foo19123afvj';
|
|
|
+
|
|
|
+ const action = docCreated(route, pendingId, {
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should create an optimistic update (pending) in state', () => {
|
|
|
+ const state = {};
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result).to.have.property(route);
|
|
|
+
|
|
|
+ expect(result[route]).to.be.an('object');
|
|
|
+
|
|
|
+ expect(result[route]).to.have.property('items');
|
|
|
+
|
|
|
+ expect(result[route].items).to.be.an('array').of.length(1);
|
|
|
+
|
|
|
+ expect(result[route].items[0]).to.be.an('object');
|
|
|
+ expect(result[route].items[0]).to.deep.equal({
|
|
|
+ id: pendingId,
|
|
|
+ pending: true,
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should not do anything if the state is loading', () => {
|
|
|
+ const state = {
|
|
|
+ [route]: {
|
|
|
+ loading: true,
|
|
|
+ items: []
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(0);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('DOC_CREATE_RESPONDED', () => {
|
|
|
+ const route = 'employees';
|
|
|
+
|
|
|
+ const pendingId = 'foo19123afvj';
|
|
|
+
|
|
|
+ const state = {
|
|
|
+ [route]: {
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ id: pendingId,
|
|
|
+ pending: true,
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const actualId = 'a0b444511123';
|
|
|
+
|
|
|
+ const response = {
|
|
|
+ data: {
|
|
|
+ id: actualId,
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const actionSuccess = docCreateResponded(route, pendingId, null, response);
|
|
|
+
|
|
|
+ it('should mark an optimistically created document as successful, if the response was success', () => {
|
|
|
+ const result = crud(state, actionSuccess);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(1);
|
|
|
+ expect(result[route].items[0]).to.have.property('id', actualId);
|
|
|
+ expect(result[route].items[0]).to.have.property('pending', false);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should remove the pending item and set an error status if an error occurred', () => {
|
|
|
+ const error = new Error('something bad happened');
|
|
|
+
|
|
|
+ const action = docCreateResponded(route, pendingId, error, null);
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(0);
|
|
|
+ expect(result[route]).to.have.property('error', true);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('DOC_READ', () => {
|
|
|
+ it('should set the route to loading', () => {
|
|
|
+ const state = {};
|
|
|
+
|
|
|
+ const route = 'employees';
|
|
|
+
|
|
|
+ const action = docRead(route);
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result).to.have.property(route);
|
|
|
+ expect(result[route]).to.be.an('object');
|
|
|
+
|
|
|
+ expect(result[route]).to.have.property('loading', true);
|
|
|
+ expect(result[route]).to.have.property('items');
|
|
|
+ expect(result[route].items).to.be.an('array').of.length(0);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('DOC_READ_RESPONDED', () => {
|
|
|
+ const route = 'employees';
|
|
|
+
|
|
|
+ const state = {
|
|
|
+ [route]: {
|
|
|
+ loading: true,
|
|
|
+ items: []
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const actualId = 'a0b444511123';
|
|
|
+
|
|
|
+ const response = {
|
|
|
+ data: {
|
|
|
+ [route]: [
|
|
|
+ {
|
|
|
+ id: actualId,
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const actionSuccess = docReadResponded(route, null, response);
|
|
|
+
|
|
|
+ const resultSuccess = crud(state, actionSuccess);
|
|
|
+
|
|
|
+ it('should add the response to state', () => {
|
|
|
+ expect(resultSuccess[route].items).to.have.length(1);
|
|
|
+ expect(resultSuccess[route].items[0]).to.have.property('id', actualId);
|
|
|
+ expect(resultSuccess[route].items[0]).to.have.property('name', 'John Doe');
|
|
|
+ expect(resultSuccess[route].items[0]).to.have.property('email', 'john.doe@mubaloo.com');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should set loading to false', () => {
|
|
|
+ expect(resultSuccess[route].loading).to.equal(false);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should set an error status if an error occurred', () => {
|
|
|
+ const error = new Error('something bad happened');
|
|
|
+
|
|
|
+ const action = docReadResponded(route, error, null);
|
|
|
+
|
|
|
+ const resultError = crud(state, action);
|
|
|
+
|
|
|
+ expect(resultError[route].items).to.have.length(0);
|
|
|
+ expect(resultError[route].error).to.equal(true);
|
|
|
+ expect(resultError[route].loading).to.equal(false);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('DOC_UPDATED', () => {
|
|
|
+ const route = 'employees';
|
|
|
+
|
|
|
+ const actualId = 'a0b444511123';
|
|
|
+
|
|
|
+ const action = docUpdated(route, actualId, {
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should optimistically update the item (pending) in state', () => {
|
|
|
+ const state = {
|
|
|
+ [route]: {
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ id: actualId,
|
|
|
+ name: 'Jack',
|
|
|
+ email: 'jack@mubaloo.com'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(1);
|
|
|
+
|
|
|
+ expect(result[route].items[0]).to.have.property('pending', true);
|
|
|
+ expect(result[route].items[0]).to.deep.equal({
|
|
|
+ id: actualId,
|
|
|
+ pending: true,
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should not do anything if the state is loading', () => {
|
|
|
+ const state = {
|
|
|
+ [route]: {
|
|
|
+ loading: true,
|
|
|
+ items: []
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(0);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('DOC_UPDATE_RESPONDED', () => {
|
|
|
+ const route = 'employees';
|
|
|
+
|
|
|
+ const actualId = 'a0b444511123';
|
|
|
+
|
|
|
+ const state = {
|
|
|
+ [route]: {
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ id: actualId,
|
|
|
+ pending: true,
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const response = {
|
|
|
+ data: {
|
|
|
+ ok: true
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const actionSuccess = docUpdateResponded(route, actualId, null, response);
|
|
|
+
|
|
|
+ it('should mark an optimistically updated document as successful, if the response was success', () => {
|
|
|
+ const result = crud(state, actionSuccess);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(1);
|
|
|
+ expect(result[route].items[0]).to.have.property('pending', false);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should set an error status if an error occurred', () => {
|
|
|
+ const error = new Error('something bad happened');
|
|
|
+
|
|
|
+ const action = docUpdateResponded(route, actualId, error, null);
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(1);
|
|
|
+ expect(result[route]).to.have.property('error', true);
|
|
|
+
|
|
|
+ expect(result[route].items[0]).to.have.property('pending', false);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('DOC_DELETED', () => {
|
|
|
+ const route = 'employees';
|
|
|
+
|
|
|
+ const actualId = 'a0b444511123';
|
|
|
+
|
|
|
+ it('should mark the document as pending', () => {
|
|
|
+ const state = {
|
|
|
+ [route]: {
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ id: actualId,
|
|
|
+ pending: false,
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const action = docDeleted(route, actualId);
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(1);
|
|
|
+ expect(result[route].items[0]).to.have.property('pending', true);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('DOC_DELETE_RESPONDED', () => {
|
|
|
+ const route = 'employees';
|
|
|
+
|
|
|
+ const actualId = 'a0b444511123';
|
|
|
+
|
|
|
+ const state = {
|
|
|
+ [route]: {
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ id: actualId,
|
|
|
+ pending: true,
|
|
|
+ name: 'John Doe',
|
|
|
+ email: 'john.doe@mubaloo.com'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ it('should remove the document if the response was success', () => {
|
|
|
+ const response = {
|
|
|
+ data: {
|
|
|
+ ok: true
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const action = docDeleteResponded(route, actualId, null, response);
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result[route].items).to.have.length(0);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should set an error status if an error occurred', () => {
|
|
|
+ const error = new Error('something bad happened');
|
|
|
+
|
|
|
+ const action = docDeleteResponded(route, actualId, error, null);
|
|
|
+
|
|
|
+ const result = crud(state, action);
|
|
|
+
|
|
|
+ expect(result[route]).to.have.property('error', true);
|
|
|
+ expect(result[route].items).to.have.length(1);
|
|
|
+ expect(result[route].items[0]).to.have.property('pending', false);
|
|
|
+ });
|
|
|
+ });
|
|
|
+});
|
|
|
+
|