Skip to content

Commit

Permalink
Try and Customize WP.com theme on Jetpack. (#10126)
Browse files Browse the repository at this point in the history
  • Loading branch information
budzanowski authored Jan 6, 2017
1 parent eaa6ea0 commit cf66c9a
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 15 deletions.
3 changes: 2 additions & 1 deletion client/my-sites/themes/single-site-jetpack.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ export default connectOptions(
/>
<ConnectedThemesSelection
options={ [
'activateOnJetpack'
'activateOnJetpack',
'tryAndCustomizeOnJetpack'
] }
search={ search }
tier={ tier }
Expand Down
17 changes: 16 additions & 1 deletion client/my-sites/themes/theme-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import { has, identity, mapValues, pick, pickBy } from 'lodash';
* Internal dependencies
*/
import config from 'config';
import { activateTheme, installAndActivate } from 'state/themes/actions';
import {
activateTheme,
installAndActivate,
installAndTryAndCustomize
} from 'state/themes/actions';
import {
getThemeSignupUrl as getSignupUrl,
getThemePurchaseUrl as getPurchaseUrl,
Expand Down Expand Up @@ -89,6 +93,16 @@ const tryandcustomize = {
hideForTheme: ( state, theme, siteId ) => isActive( state, theme.id, siteId )
};

const tryAndCustomizeOnJetpack = {
label: i18n.translate( 'Try & Customize' ),
header: i18n.translate( 'Try & Customize on:', {
comment: 'label in the dialog for opening the Customizer with the theme in preview'
} ),
action: ( themeId, siteId ) => installAndTryAndCustomize( themeId + '-wpcom', siteId ),
hideForSite: ( state, siteId ) => ! canCurrentUser( state, siteId, 'edit_theme_options' ) || ! isJetpackSite( state, siteId ),
hideForTheme: ( state, theme, siteId ) => isActive( state, theme.id, siteId )
};

// This is a special option that gets its `action` added by `ThemeShowcase` or `ThemeSheet`,
// respectively. TODO: Replace with a real action once we're able to use `SitePreview`.
const preview = {
Expand Down Expand Up @@ -141,6 +155,7 @@ const ALL_THEME_OPTIONS = {
activate,
activateOnJetpack,
tryandcustomize,
tryAndCustomizeOnJetpack,
signup,
separator,
info,
Expand Down
1 change: 1 addition & 0 deletions client/state/action-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ export const THEME_TRANSFER_INITIATE_REQUEST = 'THEME_TRANSFER_INITIATE_REQUEST'
export const THEME_TRANSFER_INITIATE_SUCCESS = 'THEME_TRANSFER_INITIATE_SUCCESS';
export const THEME_TRANSFER_STATUS_FAILURE = 'THEME_TRANSFER_STATUS_FAILURE';
export const THEME_TRANSFER_STATUS_RECEIVE = 'THEME_TRANSFER_STATUS_RECEIVE';
export const THEME_TRY_AND_CUSTOMIZE_FAILURE = 'THEME_TRY_AND_CUSTOMIZE_FAILURE';
export const USER_RECEIVE = 'USER_RECEIVE';
export const WORDADS_STATUS_REQUEST = 'WORDADS_STATUS_REQUEST';
export const WORDADS_STATUS_REQUEST_FAILURE = 'WORDADS_STATUS_REQUEST_FAILURE';
Expand Down
2 changes: 2 additions & 0 deletions client/state/notices/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
PUBLICIZE_CONNECTION_UPDATE,
PUBLICIZE_CONNECTION_UPDATE_FAILURE,
SITE_FRONT_PAGE_SET_FAILURE,
THEME_TRY_AND_CUSTOMIZE_FAILURE,
} from 'state/action-types';

import { dispatchSuccess, dispatchError } from './utils';
Expand Down Expand Up @@ -181,6 +182,7 @@ export const handlers = {
[ PUBLICIZE_CONNECTION_UPDATE_FAILURE ]: onPublicizeConnectionUpdateFailure,
[ GUIDED_TRANSFER_HOST_DETAILS_SAVE_SUCCESS ]: dispatchSuccess( translate( 'Thanks for confirming those details!' ) ),
[ SITE_FRONT_PAGE_SET_FAILURE ]: dispatchError( translate( 'An error occurred while setting the homepage' ) ),
[ THEME_TRY_AND_CUSTOMIZE_FAILURE ]: dispatchError( translate( 'Customize error, please retry or contact support' ) ),
};

/**
Expand Down
50 changes: 48 additions & 2 deletions client/state/themes/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import { map, property, delay } from 'lodash';
import debugFactory from 'debug';
import page from 'page';

/**
* Internal dependencies
Expand Down Expand Up @@ -33,6 +34,7 @@ import {
THEME_TRANSFER_INITIATE_SUCCESS,
THEME_TRANSFER_STATUS_FAILURE,
THEME_TRANSFER_STATUS_RECEIVE,
THEME_TRY_AND_CUSTOMIZE_FAILURE,
THEME_UPLOAD_START,
THEME_UPLOAD_SUCCESS,
THEME_UPLOAD_FAILURE,
Expand All @@ -47,7 +49,7 @@ import {
recordTracksEvent,
withAnalytics
} from 'state/analytics/actions';
import { getActiveTheme, getLastThemeQuery } from './selectors';
import { getTheme, getActiveTheme, getLastThemeQuery, getThemeCustomizeUrl } from './selectors';
import {
getThemeIdFromStylesheet,
filterThemesForJetpack,
Expand Down Expand Up @@ -374,7 +376,7 @@ export function installTheme( themeId, siteId ) {

return wpcom.undocumented().installThemeOnJetpack( siteId, themeId )
.then( ( theme ) => {
dispatch( receiveTheme( theme ) );
dispatch( receiveTheme( theme, siteId ) );
dispatch( {
type: THEME_INSTALL_SUCCESS,
siteId,
Expand Down Expand Up @@ -406,6 +408,50 @@ export function clearActivated( siteId ) {
};
}

/**
* Triggers a network request to install theme on Jetpack site.
* After installataion it switches page to the customizer
* See installTheme doc for install options.
* Requires Jetpack 4.4
*
* @param {String} themeId WP.com Theme ID
* @param {String} siteId Jetpack Site ID
* @return {Function} Action thunk
*/
export function installAndTryAndCustomize( themeId, siteId ) {
return ( dispatch ) => {
return dispatch( installTheme( themeId, siteId ) )
.then( () => {
dispatch( tryAndCustomize( themeId, siteId ) );
} );
};
}

/**
* Triggers a switch to the try&customize page of theme.
* When theme is not available dispatches FAILURE action
* that trigers displaying error notice by notices middlewaere
*
* @param {String} themeId WP.com Theme ID
* @param {String} siteId Jetpack Site ID
* @return {Function} Action thunk
*/
export function tryAndCustomize( themeId, siteId ) {
return ( dispatch, getState ) => {
const theme = getTheme( getState(), siteId, themeId );
if ( ! theme ) {
dispatch( {
type: THEME_TRY_AND_CUSTOMIZE_FAILURE,
themeId,
siteId
} );
return;
}
const url = getThemeCustomizeUrl( getState(), theme, siteId );
page( url );
};
}

/**
* Triggers a network request to install and activate a specific theme on a given
* Jetpack site. If the themeId parameter is suffixed with '-wpcom', install the
Expand Down
81 changes: 70 additions & 11 deletions client/state/themes/test/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import sinon from 'sinon';
import { expect } from 'chai';
import useMockery from 'test/helpers/use-mockery';

/**
* Internal dependencies
Expand All @@ -28,6 +29,7 @@ import {
THEME_TRANSFER_INITIATE_SUCCESS,
THEME_TRANSFER_STATUS_FAILURE,
THEME_TRANSFER_STATUS_RECEIVE,
THEME_TRY_AND_CUSTOMIZE_FAILURE,
THEMES_RECEIVE,
THEMES_REQUEST,
THEMES_REQUEST_SUCCESS,
Expand All @@ -46,13 +48,26 @@ import {
pollThemeTransferStatus,
initiateThemeTransfer,
installTheme,
installAndTryAndCustomize,
tryAndCustomize,
deleteTheme,
} from '../actions';
import useNock from 'test/helpers/use-nock';

describe( 'actions', () => {
const spy = sinon.spy();

function isEqualFunction( f1, f2 ) {
// TODO: Also compare params!
return f1.toString() === f2.toString();
}

function matchFunction( fn ) {
return sinon.match( ( value ) => (
isEqualFunction( value, fn )
) );
}

beforeEach( () => {
spy.reset();
} );
Expand Down Expand Up @@ -522,17 +537,6 @@ describe( 'actions', () => {
} );

describe( '#installAndActivate', () => {
function isEqualFunction( f1, f2 ) {
// TODO: Also compare params!
return f1.toString() === f2.toString();
}

function matchFunction( fn ) {
return sinon.match( ( value ) => (
isEqualFunction( value, fn )
) );
}

const stub = sinon.stub();
stub.returns( new Promise( ( res ) => {
res();
Expand Down Expand Up @@ -871,4 +875,59 @@ describe( 'actions', () => {
} );
} );
} );

describe( '#tryAndCustomize', () => {
const pageSpy = sinon.spy();
const getThemeSpy = ( store, siteId, themeId ) => {
if ( themeId === 'karuna-wpcom' ) {
return { theme: themeId };
}
return null;
};

// we import it again with different name because we want to mock functions inside.
let _tryAndCustomize;

useMockery( ( mockery ) => {
mockery.registerMock( 'page', pageSpy );
mockery.registerMock( './selectors', {
getThemeCustomizeUrl: () => 'customizer/url',
getTheme: getThemeSpy,
} );
_tryAndCustomize = require( '../actions' ).tryAndCustomize;
} );

it( 'page should be called, when theme is available', () => {
_tryAndCustomize( 'karuna-wpcom', 2211667 )( spy, () => {} );
expect( pageSpy.calledWith( 'customizer/url' ) ).to.be.true;
} );

const tryAndActivateFalilureAction = {
type: THEME_TRY_AND_CUSTOMIZE_FAILURE,
themeId: 'typist-wpcom',
siteId: 2211667,
};

it( 'page should not be called, when theme is not available and FAILURE action shoudl be dispatched', () => {
pageSpy.reset();
_tryAndCustomize( 'typist-wpcom', 2211667 )( spy, () => {} );
expect( pageSpy.calledWith( 'customizer/url' ) ).to.be.false;
expect( spy ).to.have.been.calledWith( tryAndActivateFalilureAction );
} );
} );

describe( '#installAndTryAndCustomize', () => {
const stub = sinon.stub();
stub.returns( new Promise( ( res ) => {
res();
} ) );

it( 'should dispatch installTheme(), and tryAndCustomize()', ( done ) => {
installAndTryAndCustomize( 'karuna-wpcom', 2211667 )( stub ).then( () => {
expect( stub ).to.have.been.calledWith( matchFunction( installTheme( 'karuna-wpcom', 2211667 ) ) );
expect( stub ).to.have.been.calledWith( matchFunction( tryAndCustomize( 'karuna-wpcom', 2211667 ) ) );
done();
} );
} );
} );
} );

0 comments on commit cf66c9a

Please sign in to comment.