From 83d87c46758509320ab8e9e1ebfa6b879e3f2d8f Mon Sep 17 00:00:00 2001 From: Marin Atanasov Date: Wed, 28 Sep 2016 12:35:08 +0300 Subject: [PATCH 1/4] Plugins: Add QueryJetpackPlugins query component --- .../data/query-jetpack-plugins/README.md | 19 +++++++ .../data/query-jetpack-plugins/index.jsx | 53 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 client/components/data/query-jetpack-plugins/README.md create mode 100644 client/components/data/query-jetpack-plugins/index.jsx diff --git a/client/components/data/query-jetpack-plugins/README.md b/client/components/data/query-jetpack-plugins/README.md new file mode 100644 index 0000000000000..d069b704c209d --- /dev/null +++ b/client/components/data/query-jetpack-plugins/README.md @@ -0,0 +1,19 @@ +Query Jetpack Plugins +================= + +`` is a React component used in managing network requests for Jetpack plugins. + +## Usage + +Render the component, passing `sites`. It does not accept any children, nor does it render any elements to the page. You can use it adjacent to other sibling components which make use of the fetched data made available through the global application state. + +## Props + +### `sites` + + + + +
TypeArray
RequiredYes
+ +The array of sites for which Jetpack plugins should be requested. diff --git a/client/components/data/query-jetpack-plugins/index.jsx b/client/components/data/query-jetpack-plugins/index.jsx new file mode 100644 index 0000000000000..90009a3536525 --- /dev/null +++ b/client/components/data/query-jetpack-plugins/index.jsx @@ -0,0 +1,53 @@ +/** + * External dependencies + */ +import { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { isEqual } from 'lodash'; + +/** + * Internal dependencies + */ +import { fetchPlugins } from 'state/plugins/installed/actions'; +import { isRequestingForSites } from 'state/plugins/installed/selectors'; + +class QueryJetpackPlugins extends Component { + componentWillMount() { + if ( this.props.sites && ! this.props.isRequestingForSites ) { + this.props.fetchPlugins( this.props.sites ); + } + } + + componentWillReceiveProps( nextProps ) { + if ( isEqual( nextProps.sites, this.props.sites ) ) { + return; + } + this.refresh( nextProps.isRequestingForSites, nextProps.sites ); + } + + refresh( isRequesting, sites ) { + if ( ! isRequesting ) { + this.props.fetchPlugins( sites ); + } + } + + render() { + return null; + } +} + +QueryJetpackPlugins.propTypes = { + sites: PropTypes.array.isRequired, + isRequestingForSites: PropTypes.bool, + fetchPlugins: PropTypes.func +}; + +export default connect( + ( state, props ) => { + const sites = props.sites; + return { + isRequestingForSites: isRequestingForSites( state, sites.map( site => site.ID ) ), + }; + }, + { fetchPlugins } +)( QueryJetpackPlugins ); From b69c6b4d98b51d1328297d166828db56eaf925e3 Mon Sep 17 00:00:00 2001 From: Marin Atanasov Date: Mon, 17 Oct 2016 18:52:12 +0300 Subject: [PATCH 2/4] Jetpack Plugins: Use site IDs instead of site objects to fetch plugins --- .../data/query-jetpack-plugins/README.md | 6 +++--- .../data/query-jetpack-plugins/index.jsx | 17 ++++++++--------- client/state/plugins/installed/README.md | 2 +- client/state/plugins/installed/actions.js | 10 +++++----- client/state/plugins/installed/test/actions.js | 10 +++++----- 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/client/components/data/query-jetpack-plugins/README.md b/client/components/data/query-jetpack-plugins/README.md index d069b704c209d..0a65dc578a6d4 100644 --- a/client/components/data/query-jetpack-plugins/README.md +++ b/client/components/data/query-jetpack-plugins/README.md @@ -5,15 +5,15 @@ Query Jetpack Plugins ## Usage -Render the component, passing `sites`. It does not accept any children, nor does it render any elements to the page. You can use it adjacent to other sibling components which make use of the fetched data made available through the global application state. +Render the component, passing `siteIds`. It does not accept any children, nor does it render any elements to the page. You can use it adjacent to other sibling components which make use of the fetched data made available through the global application state. ## Props -### `sites` +### `siteIds`
TypeArray
RequiredYes
-The array of sites for which Jetpack plugins should be requested. +The array of site IDs for which Jetpack plugins should be requested. diff --git a/client/components/data/query-jetpack-plugins/index.jsx b/client/components/data/query-jetpack-plugins/index.jsx index 90009a3536525..f7821846ba9a6 100644 --- a/client/components/data/query-jetpack-plugins/index.jsx +++ b/client/components/data/query-jetpack-plugins/index.jsx @@ -13,21 +13,21 @@ import { isRequestingForSites } from 'state/plugins/installed/selectors'; class QueryJetpackPlugins extends Component { componentWillMount() { - if ( this.props.sites && ! this.props.isRequestingForSites ) { - this.props.fetchPlugins( this.props.sites ); + if ( this.props.siteIds && ! this.props.isRequestingForSites ) { + this.props.fetchPlugins( this.props.siteIds ); } } componentWillReceiveProps( nextProps ) { - if ( isEqual( nextProps.sites, this.props.sites ) ) { + if ( isEqual( nextProps.siteIds, this.props.siteIds ) ) { return; } - this.refresh( nextProps.isRequestingForSites, nextProps.sites ); + this.refresh( nextProps.isRequestingForSites, nextProps.siteIds ); } - refresh( isRequesting, sites ) { + refresh( isRequesting, siteIds ) { if ( ! isRequesting ) { - this.props.fetchPlugins( sites ); + this.props.fetchPlugins( siteIds ); } } @@ -37,16 +37,15 @@ class QueryJetpackPlugins extends Component { } QueryJetpackPlugins.propTypes = { - sites: PropTypes.array.isRequired, + siteIds: PropTypes.array.isRequired, isRequestingForSites: PropTypes.bool, fetchPlugins: PropTypes.func }; export default connect( ( state, props ) => { - const sites = props.sites; return { - isRequestingForSites: isRequestingForSites( state, sites.map( site => site.ID ) ), + isRequestingForSites: isRequestingForSites( state, props.siteIds ), }; }, { fetchPlugins } diff --git a/client/state/plugins/installed/README.md b/client/state/plugins/installed/README.md index dc84528a111a6..9449fdb0fd7f7 100644 --- a/client/state/plugins/installed/README.md +++ b/client/state/plugins/installed/README.md @@ -5,7 +5,7 @@ A module for managing installed plugins on connected sites. ## Actions -### `fetchPlugins( sites: Array )` +### `fetchPlugins( siteIds: Array )` ### `installPlugin( siteId: Number, plugin: Object )` diff --git a/client/state/plugins/installed/actions.js b/client/state/plugins/installed/actions.js index 74113302b08aa..7d217a67323eb 100644 --- a/client/state/plugins/installed/actions.js +++ b/client/state/plugins/installed/actions.js @@ -302,11 +302,11 @@ export function removePlugin( siteId, plugin ) { }; } -export function fetchPlugins( sites ) { +export function fetchPlugins( siteIds ) { return ( dispatch ) => { - return sites.map( ( site ) => { + return siteIds.map( ( siteId ) => { const defaultAction = { - siteId: site.ID, + siteId }; dispatch( { ...defaultAction, type: PLUGINS_REQUEST } ); @@ -316,7 +316,7 @@ export function fetchPlugins( sites ) { data.plugins.map( plugin => { if ( plugin.update && plugin.autoupdate ) { - updatePlugin( site.ID, plugin )( dispatch ); + updatePlugin( siteId, plugin )( dispatch ); } } ); }; @@ -326,7 +326,7 @@ export function fetchPlugins( sites ) { dispatch( { ...defaultAction, type: PLUGINS_REQUEST_FAILURE, error } ); }; - return wpcom.site( site.ID ).pluginsList().then( receivePluginsDispatchSuccess ).catch( receivePluginsDispatchFail ); + return wpcom.site( siteId ).pluginsList().then( receivePluginsDispatchSuccess ).catch( receivePluginsDispatchFail ); } ); }; } diff --git a/client/state/plugins/installed/test/actions.js b/client/state/plugins/installed/test/actions.js index 0d614bbe62c7f..3591746a3d1ff 100644 --- a/client/state/plugins/installed/test/actions.js +++ b/client/state/plugins/installed/test/actions.js @@ -81,7 +81,7 @@ describe( 'actions', () => { } ); it( 'should dispatch fetch action when triggered', () => { - fetchPlugins( [ { ID: 2916284, jetpack: true } ] )( spy ); + fetchPlugins( [ 2916284 ] )( spy ); expect( spy ).to.have.been.calledWith( { type: PLUGINS_REQUEST, @@ -90,7 +90,7 @@ describe( 'actions', () => { } ); it( 'should dispatch plugins receive action when request completes', () => { - const responses = fetchPlugins( [ { ID: 2916284, jetpack: true } ] )( spy ); + const responses = fetchPlugins( [ 2916284 ] )( spy ); return Promise.all( responses ).then( () => { expect( spy ).to.have.been.calledWith( { type: PLUGINS_RECEIVE, @@ -100,7 +100,7 @@ describe( 'actions', () => { } ); it( 'should dispatch plugin request success action when request completes', () => { - const responses = fetchPlugins( [ { ID: 2916284, jetpack: true } ] )( spy ); + const responses = fetchPlugins( [ 2916284 ] )( spy ); return Promise.all( responses ).then( () => { expect( spy ).to.have.been.calledWith( { type: PLUGINS_REQUEST_SUCCESS, @@ -111,7 +111,7 @@ describe( 'actions', () => { } ); it( 'should dispatch fail action when request fails', () => { - const responses = fetchPlugins( [ { ID: 77203074, jetpack: true } ] )( spy ); + const responses = fetchPlugins( [ 77203074 ] )( spy ); return Promise.all( responses ).then( () => { expect( spy ).to.have.been.calledWith( { type: PLUGINS_REQUEST_FAILURE, @@ -122,7 +122,7 @@ describe( 'actions', () => { } ); it( 'should dispatch plugin update request if any site plugins need updating', () => { - const responses = fetchPlugins( [ { ID: 2916284, jetpack: true } ] )( spy ); + const responses = fetchPlugins( [ 2916284 ] )( spy ); return Promise.all( responses ).then( () => { expect( spy ).to.have.been.calledWith( { type: PLUGIN_UPDATE_REQUEST, From 432063eaf8bd715a84db74565606e428a133fa39 Mon Sep 17 00:00:00 2001 From: Marin Atanasov Date: Mon, 17 Oct 2016 18:57:09 +0300 Subject: [PATCH 3/4] Jetpack Plugins: Rename installed plugins test describe calls --- client/state/plugins/installed/test/actions.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/state/plugins/installed/test/actions.js b/client/state/plugins/installed/test/actions.js index 3591746a3d1ff..002424b3ffc2d 100644 --- a/client/state/plugins/installed/test/actions.js +++ b/client/state/plugins/installed/test/actions.js @@ -63,7 +63,7 @@ describe( 'actions', () => { spy.reset(); } ); - describe( '#fetch()', () => { + describe( '#fetchPlugins()', () => { useNock( ( nock ) => { nock( 'https://public-api.wordpress.com:443' ) .persist() @@ -134,7 +134,7 @@ describe( 'actions', () => { } ); } ); - describe( '#activate()', () => { + describe( '#activatePlugin()', () => { useNock( ( nock ) => { nock( 'https://public-api.wordpress.com:443' ) .persist() @@ -185,7 +185,7 @@ describe( 'actions', () => { } ); } ); - describe( '#deactivate()', () => { + describe( '#deactivatePlugin()', () => { useNock( ( nock ) => { nock( 'https://public-api.wordpress.com:443' ) .persist() @@ -236,7 +236,7 @@ describe( 'actions', () => { } ); } ); - describe( '#update()', () => { + describe( '#updatePlugin()', () => { const site = { ID: 2916284, jetpack: true, @@ -303,7 +303,7 @@ describe( 'actions', () => { } ); } ); - describe( '#enableAutoupdate()', () => { + describe( '#enableAutoupdatePlugin()', () => { const site = { ID: 2916284, jetpack: true, @@ -380,7 +380,7 @@ describe( 'actions', () => { } ); } ); - describe( '#disableAutoupdate()', () => { + describe( '#disableAutoupdatePlugin()', () => { const site = { ID: 2916284, jetpack: true, @@ -441,7 +441,7 @@ describe( 'actions', () => { } ); } ); - describe( '#install()', () => { + describe( '#installPlugin()', () => { const site = { ID: 2916284, jetpack: true, @@ -510,7 +510,7 @@ describe( 'actions', () => { } ); } ); - describe( '#remove()', () => { + describe( '#removePlugin()', () => { const site = { ID: 2916284, jetpack: true, From 01568f7b5b5cf3df0b620d2c84cbe845176a5e5e Mon Sep 17 00:00:00 2001 From: Marin Atanasov Date: Mon, 17 Oct 2016 19:01:01 +0300 Subject: [PATCH 4/4] Jetpack Plugins: Hide promise errors from installed plugin tests --- client/state/plugins/installed/test/actions.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/state/plugins/installed/test/actions.js b/client/state/plugins/installed/test/actions.js index 002424b3ffc2d..2e2543b7070e5 100644 --- a/client/state/plugins/installed/test/actions.js +++ b/client/state/plugins/installed/test/actions.js @@ -55,12 +55,13 @@ import { } from '../actions'; import { akismet, helloDolly, jetpack, jetpackUpdated } from './fixtures/plugins'; import useNock from 'test/helpers/use-nock'; +import { useSandbox } from 'test/helpers/use-sinon'; describe( 'actions', () => { - const spy = sinon.spy(); - - beforeEach( () => { - spy.reset(); + let spy; + useSandbox( ( sandbox ) => { + spy = sandbox.spy(); + sandbox.stub( console, 'error' ); } ); describe( '#fetchPlugins()', () => {