Handle entry persisting state in actions and reducer + added tests.

This commit is contained in:
Andrey Okonetchnikov 2016-10-12 19:19:05 +02:00
parent a80d1087b2
commit 077e83dfc9
3 changed files with 84 additions and 16 deletions

View File

@ -83,8 +83,8 @@ export function entryPersisting(collection, entry) {
return { return {
type: ENTRY_PERSIST_REQUEST, type: ENTRY_PERSIST_REQUEST,
payload: { payload: {
collection, collectionName: collection.get('name'),
entry, entrySlug: entry.get('slug'),
}, },
}; };
} }
@ -93,17 +93,21 @@ export function entryPersisted(collection, entry) {
return { return {
type: ENTRY_PERSIST_SUCCESS, type: ENTRY_PERSIST_SUCCESS,
payload: { payload: {
collection, collectionName: collection.get('name'),
entry, entrySlug: entry.get('slug'),
}, },
}; };
} }
export function entryPersistFail(collection, entry, error) { export function entryPersistFail(collection, entry, error) {
return { return {
type: ENTRIES_FAILURE, type: ENTRY_PERSIST_FAILURE,
error: 'Failed to persist entry', error: 'Failed to persist entry',
payload: error.toString(), payload: {
collectionName: collection.get('name'),
entrySlug: entry.get('slug'),
error: error.toString(),
},
}; };
} }
@ -211,12 +215,10 @@ export function persistEntry(collection, entry) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const backend = currentBackend(state.config); const backend = currentBackend(state.config);
const MediaProxies = entry.get('mediaFiles').map(path => getMedia(state, path)); const mediaProxies = entry.get('mediaFiles').map(path => getMedia(state, path));
dispatch(entryPersisting(collection, entry)); dispatch(entryPersisting(collection, entry));
backend.persistEntry(state.config, collection, entry, MediaProxies.toJS()).then( backend.persistEntry(state.config, collection, entry, mediaProxies.toJS()).then(
() => { () => dispatch(entryPersisted(collection, entry)),
dispatch(entryPersisted(collection, entry));
},
error => dispatch(entryPersistFail(collection, entry, error)) error => dispatch(entryPersistFail(collection, entry, error))
); );
}; };

View File

@ -1,15 +1,16 @@
import expect from 'expect'; import Immutable, { Map, OrderedMap, fromJS } from 'immutable';
import { Map, OrderedMap, fromJS } from 'immutable'; import * as actions from '../../actions/entries';
import { entriesLoading, entriesLoaded } from '../../actions/entries';
import reducer from '../entries'; import reducer from '../entries';
let initialState;
describe('entries', () => { describe('entries', () => {
it('should mark entries as fetching', () => { it('should mark entries as fetching', () => {
const state = OrderedMap({ const state = OrderedMap({
posts: Map({ name: 'posts' }), posts: Map({ name: 'posts' }),
}); });
expect( expect(
reducer(state, entriesLoading(Map({ name: 'posts' }))) reducer(state, actions.entriesLoading(Map({ name: 'posts' })))
).toEqual( ).toEqual(
OrderedMap(fromJS({ OrderedMap(fromJS({
posts: { name: 'posts' }, posts: { name: 'posts' },
@ -26,7 +27,7 @@ describe('entries', () => {
}); });
const entries = [{ slug: 'a', path: '' }, { slug: 'b', title: 'B' }]; const entries = [{ slug: 'a', path: '' }, { slug: 'b', title: 'B' }];
expect( expect(
reducer(state, entriesLoaded(Map({ name: 'posts' }), entries, 0)) reducer(state, actions.entriesLoaded(Map({ name: 'posts' }), entries, 0))
).toEqual( ).toEqual(
OrderedMap(fromJS( OrderedMap(fromJS(
{ {
@ -45,4 +46,51 @@ describe('entries', () => {
)) ))
); );
}); });
describe('entry persisting', () => {
beforeEach(() => {
initialState = Immutable.fromJS({
entities: {
'posts.slug': {
collection: 'posts',
slug: 'slug',
path: 'content/blog/art-and-wine-festival.md',
partial: false,
raw: '',
data: {},
metaData: null,
},
},
pages: {},
});
});
it('should handle persisting request', () => {
const newState = reducer(
initialState,
actions.entryPersisting(Map({ name: 'posts' }), Map({ slug: 'slug' }))
);
expect(newState.getIn(['entities', 'posts.slug', 'isPersisting'])).toBe(true);
});
it('should handle persisting success', () => {
let newState = reducer(initialState,
actions.entryPersisting(Map({ name: 'posts' }), Map({ slug: 'slug' }))
);
newState = reducer(newState,
actions.entryPersisted(Map({ name: 'posts' }), Map({ slug: 'slug' }))
);
expect(newState.getIn(['entities', 'posts.slug', 'isPersisting'])).toBeUndefined();
});
it('should handle persisting error', () => {
let newState = reducer(initialState,
actions.entryPersisting(Map({ name: 'posts' }), Map({ slug: 'slug' }))
);
newState = reducer(newState,
actions.entryPersistFail(Map({ name: 'posts' }), Map({ slug: 'slug' }), 'Error message')
);
expect(newState.getIn(['entities', 'posts.slug', 'isPersisting'])).toBeUndefined();
});
});
}); });

View File

@ -2,6 +2,9 @@ import { Map, List, fromJS } from 'immutable';
import { import {
ENTRY_REQUEST, ENTRY_REQUEST,
ENTRY_SUCCESS, ENTRY_SUCCESS,
ENTRY_PERSIST_REQUEST,
ENTRY_PERSIST_SUCCESS,
ENTRY_PERSIST_FAILURE,
ENTRIES_REQUEST, ENTRIES_REQUEST,
ENTRIES_SUCCESS, ENTRIES_SUCCESS,
SEARCH_ENTRIES_REQUEST, SEARCH_ENTRIES_REQUEST,
@ -13,6 +16,10 @@ let loadedEntries;
let page; let page;
let searchTerm; let searchTerm;
function getEntryPath(collectionName, entrySlug) {
return `${ collectionName }.${ entrySlug }`;
}
const entries = (state = Map({ entities: Map(), pages: Map() }), action) => { const entries = (state = Map({ entities: Map(), pages: Map() }), action) => {
switch (action.type) { switch (action.type) {
case ENTRY_REQUEST: case ENTRY_REQUEST:
@ -24,6 +31,17 @@ const entries = (state = Map({ entities: Map(), pages: Map() }), action) => {
fromJS(action.payload.entry) fromJS(action.payload.entry)
); );
case ENTRY_PERSIST_REQUEST: {
const { collectionName, entrySlug } = action.payload;
return state.setIn(['entities', getEntryPath(collectionName, entrySlug), 'isPersisting'], true);
}
case ENTRY_PERSIST_SUCCESS:
case ENTRY_PERSIST_FAILURE: {
const { collectionName, entrySlug } = action.payload;
return state.deleteIn(['entities', getEntryPath(collectionName, entrySlug), 'isPersisting']);
}
case ENTRIES_REQUEST: case ENTRIES_REQUEST:
return state.setIn(['pages', action.payload.collection, 'isFetching'], true); return state.setIn(['pages', action.payload.collection, 'isFetching'], true);