Skip to content

Commit

Permalink
Add themeRequestError reducer, getThemeRequestError selector and test…
Browse files Browse the repository at this point in the history
…s. (#9791)
  • Loading branch information
budzanowski authored Dec 4, 2016
1 parent b35dd4b commit 7a361ad
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 1 deletion.
26 changes: 25 additions & 1 deletion client/state/themes/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* External dependencies
*/
import { combineReducers } from 'redux';
import { mapValues } from 'lodash';
import { mapValues, omit } from 'lodash';

/**
* Internal dependencies
Expand Down Expand Up @@ -162,6 +162,29 @@ export function themeRequests( state = {}, action ) {
return state;
}

/**
* Returns the updated site theme requests error state after an action has been
* dispatched. The state reflects a mapping of site ID, theme ID pairing to a
* object describing request error. If there is no error null is storred.
*
* @param {Object} state Current state
* @param {Object} action Action payload
* @return {Object} Updated state
*/
export const themeRequestErrors = createReducer( {}, {
[ THEME_REQUEST_FAILURE ]: ( state, { siteId, themeId, error } ) => ( {
...state,
[ siteId ]: {
...state[ siteId ],
[ themeId ]: error
}
} ),
[ THEME_REQUEST_SUCCESS ]: ( state, { siteId, themeId } ) => ( {
...state,
[ siteId ]: omit( state[ siteId ], themeId ),
} )
} );

/**
* Returns the updated theme query requesting state after an action has been
* dispatched. The state reflects a mapping of serialized query to whether a
Expand Down Expand Up @@ -270,6 +293,7 @@ export default combineReducers( {
// queryRequests,
// lastQuery
themeRequests,
// themeRequestErrors
activeThemes,
activeThemeRequests,
activationRequests,
Expand Down
12 changes: 12 additions & 0 deletions client/state/themes/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ export const getTheme = createSelector(
( state ) => state.themes.queries
);

/**
* Returns theme request error object
*
* @param {Object} state Global state tree
* @param {String} themeId Theme ID
* @param {Number} siteId Site ID
* @return {Object} error object if present or null otherwise
*/
export function getThemeRequestErrors( state, themeId, siteId ) {
return get( state.themes.themeRequestErrors, [ siteId, themeId ], null );
}

/**
* Returns an array of normalized themes for the themes query, or null if no
* themes have been received.
Expand Down
98 changes: 98 additions & 0 deletions client/state/themes/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import reducer, {
queries,
lastQuery,
themeRequests,
themeRequestErrors,
activeThemes,
activationRequests,
activeThemeRequests,
Expand Down Expand Up @@ -464,6 +465,103 @@ describe( 'reducer', () => {
} );
} );

describe( '#themeRequestErrors()', () => {
it( 'should default to an empty object', () => {
const state = themeRequestErrors( undefined, {} );

expect( state ).to.deep.equal( {} );
} );

it( 'should create empyt mapping on success if previous state was empty', () => {
const state = themeRequestErrors( deepFreeze( {} ), {
type: THEME_REQUEST_SUCCESS,
siteId: 2916284,
themeId: 'twentysixteen'
} );

expect( state ).to.deep.equal( {
2916284: {}
} );
} );

it( 'should map site ID, theme ID to error if request finishes with failure', () => {
const state = themeRequestErrors( deepFreeze( {} ), {
type: THEME_REQUEST_FAILURE,
siteId: 2916284,
themeId: 'vivaro',
error: 'Request error'
} );

expect( state ).to.deep.equal( {
2916284: {
vivaro: 'Request error'
}
} );
} );

it( 'should switch from error to no mapping after successful request after a failure', () => {
const state = themeRequestErrors( deepFreeze( {
2916284: {
pinboard: {
error: 'Request Error'
}
}
} ), {
type: THEME_REQUEST_SUCCESS,
siteId: 2916284,
themeId: 'pinboard'
} );

expect( state ).to.deep.equal( {
2916284: {}
} );
} );

it( 'should accumulate mappings', () => {
const state = themeRequestErrors( deepFreeze( {
2916284: {
twentysixteennnnn: 'No such theme!'
}
} ), {
type: THEME_REQUEST_FAILURE,
siteId: 2916284,
themeId: 'twentysixteen',
error: 'System error'
} );

expect( state ).to.deep.equal( {
2916284: {
twentysixteennnnn: 'No such theme!',
twentysixteen: 'System error'
}
} );
} );

it( 'never persists state', () => {
const state = themeRequestErrors( deepFreeze( {
2916284: {
twentysixteen: null
}
} ), {
type: SERIALIZE
} );

expect( state ).to.deep.equal( {} );
} );

it( 'never loads persisted state', () => {
const state = themeRequestErrors( deepFreeze( {
2916284: {
twentysixteen: null
}
} ), {
type: DESERIALIZE
} );

expect( state ).to.deep.equal( {} );
} );
} );

describe( '#activeThemes()', () => {
it( 'should default to an empty object', () => {
const state = activeThemes( undefined, {} );
Expand Down
27 changes: 27 additions & 0 deletions client/state/themes/test/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { values } from 'lodash';
import {
getThemes,
getTheme,
getThemeRequestErrors,
isRequestingTheme,
getThemesForQuery,
getLastThemeQuery,
Expand Down Expand Up @@ -130,6 +131,32 @@ describe( 'themes selectors', () => {
} );
} );

describe( '#getThemesRequestError()', () => {
it( 'should return null if thre is not request error storred for that theme on site', () => {
const error = getThemeRequestErrors( {
themes: {
themeRequestErrors: {}
}
}, 'twentysixteen', 413 );

expect( error ).to.be.null;
} );

it( 'should return the error object for the site ID, theme ID pair', () => {
const error = getThemeRequestErrors( {
themes: {
themeRequestErrors: {
2916284: {
twentysixteen: 'Request error'
}
}
}
}, 'twentysixteen', 2916284, );

expect( error ).to.equal( 'Request error' );
} );
} );

describe( '#isRequestingTheme()', () => {
it( 'should return false if there are no active requests for site', () => {
const isRequesting = isRequestingTheme( {
Expand Down

0 comments on commit 7a361ad

Please sign in to comment.