Merge pull request #29 from woocommerce/update/support-backend-experiments

Experiments - Support backend experiments
This commit is contained in:
Moon 2022-02-25 13:48:23 -08:00 committed by GitHub
commit 0655a53c80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 101 additions and 28 deletions

View File

@ -1,23 +1,51 @@
/**
* External dependencies
*/
import { apiFetch } from '@wordpress/data-controls';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import TYPES from './action-types'; import TYPES from './action-types';
import { EXPERIMENT_NAME_PREFIX } from './constants'; import { EXPERIMENT_NAME_PREFIX, TRANSIENT_NAME_PREFIX } from './constants';
export function toggleExperiment( experimentName ) { function toggleFrontendExperiment( experimentName, newVariation ) {
const storageItem = JSON.parse( const storageItem = JSON.parse(
window.localStorage.getItem( EXPERIMENT_NAME_PREFIX + experimentName ) window.localStorage.getItem( EXPERIMENT_NAME_PREFIX + experimentName )
); );
const newVariation =
storageItem.variationName === 'control' ? 'treatment' : 'control';
storageItem.variationName = newVariation; storageItem.variationName = newVariation;
window.localStorage.setItem( window.localStorage.setItem(
EXPERIMENT_NAME_PREFIX + experimentName, EXPERIMENT_NAME_PREFIX + experimentName,
JSON.stringify( storageItem ) JSON.stringify( storageItem )
); );
}
function* toggleBackendExperiment( experimentName, newVariation ) {
try {
const payload = {};
payload[ TRANSIENT_NAME_PREFIX + experimentName ] = newVariation;
yield apiFetch( {
method: 'POST',
path: '/wc-admin/options',
headers: { 'content-type': 'application/json' },
body: JSON.stringify( payload ),
} );
} catch ( error ) {
throw new Error();
}
}
export function* toggleExperiment( experimentName, currentVariation, source ) {
const newVariation =
currentVariation === 'control' ? 'treatment' : 'control';
if ( source === 'frontend' ) {
toggleFrontendExperiment( experimentName, newVariation );
} else {
yield toggleBackendExperiment( experimentName, newVariation );
}
return { return {
type: TYPES.TOGGLE_EXPERIMENT, type: TYPES.TOGGLE_EXPERIMENT,

View File

@ -1,2 +1,4 @@
export const STORE_KEY = 'wc-admin-helper/experiments'; export const STORE_KEY = 'wc-admin-helper/experiments';
export const EXPERIMENT_NAME_PREFIX = 'explat-experiment--'; export const EXPERIMENT_NAME_PREFIX = 'explat-experiment--';
export const TRANSIENT_NAME_PREFIX = '_transient_abtest_variation_';
export const API_NAMESPACE = '/wc-admin-test-helper';

View File

@ -1,24 +1,59 @@
/**
* External dependencies
*/
import { apiFetch } from '@wordpress/data-controls';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { setExperiments } from './actions'; import { setExperiments } from './actions';
import { EXPERIMENT_NAME_PREFIX } from './constants'; import {
EXPERIMENT_NAME_PREFIX,
TRANSIENT_NAME_PREFIX,
API_NAMESPACE,
} from './constants';
export function* getExperiments() { function getExperimentsFromFrontend() {
const storageItems = Object.entries( { ...window.localStorage } ).filter( const storageItems = Object.entries( { ...window.localStorage } ).filter(
( item ) => { ( item ) => {
return item[ 0 ].indexOf( EXPERIMENT_NAME_PREFIX ) === 0; return item[ 0 ].indexOf( EXPERIMENT_NAME_PREFIX ) === 0;
} }
); );
const experiments = storageItems.map( ( storageItem ) => { return storageItems.map( ( storageItem ) => {
const [ key, value ] = storageItem; const [ key, value ] = storageItem;
const objectValue = JSON.parse( value ); const objectValue = JSON.parse( value );
return { return {
name: key.replace( EXPERIMENT_NAME_PREFIX, '' ), name: key.replace( EXPERIMENT_NAME_PREFIX, '' ),
variation: objectValue.variationName || 'control', variation: objectValue.variationName || 'control',
source: 'frontend',
}; };
} ); } );
}
yield setExperiments( experiments );
export function* getExperiments() {
try {
const response = yield apiFetch( {
path: `${ API_NAMESPACE }/options?search=_transient_abtest_variation_`,
} );
const experimentsFromBackend = response.map( ( experiment ) => {
return {
name: experiment.option_name.replace(
TRANSIENT_NAME_PREFIX,
''
),
variation:
experiment.option_value === 'control'
? 'control'
: 'treatment',
source: 'backend',
};
} );
yield setExperiments(
getExperimentsFromFrontend().concat( experimentsFromBackend )
);
} catch ( error ) {
throw new Error();
}
} }

View File

@ -24,24 +24,32 @@ function Experiments( { experiments, toggleExperiment } ) {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{ experiments.map( ( { name, variation }, index ) => { { experiments.map(
return ( ( { name, variation, source }, index ) => {
<tr key={ index }> return (
<td className="experiment-name">{ name }</td> <tr key={ index }>
<td align="center">{ variation }</td> <td className="experiment-name">
<td align="center"> { name }
<Button </td>
onClick={ () => { <td align="center">{ variation }</td>
toggleExperiment( name ); <td align="center">
} } <Button
isPrimary onClick={ () => {
> toggleExperiment(
Toggle name,
</Button> variation,
</td> source
</tr> );
); } }
} ) } isPrimary
>
Toggle
</Button>
</td>
</tr>
);
}
) }
</tbody> </tbody>
</table> </table>
</div> </div>