From a7c8e912802dc4a21a09206652ebb7fc96c60711 Mon Sep 17 00:00:00 2001 From: Moon Date: Thu, 24 Feb 2022 12:21:40 -0800 Subject: [PATCH 1/3] Load backend experiments --- src/experiments/data/resolvers.js | 45 +++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/experiments/data/resolvers.js b/src/experiments/data/resolvers.js index 754e32b64bf..1b062ddbf7c 100644 --- a/src/experiments/data/resolvers.js +++ b/src/experiments/data/resolvers.js @@ -1,24 +1,59 @@ +/** + * External dependencies + */ +import { apiFetch } from '@wordpress/data-controls'; + /** * Internal dependencies */ 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( ( item ) => { return item[ 0 ].indexOf( EXPERIMENT_NAME_PREFIX ) === 0; } ); - const experiments = storageItems.map( ( storageItem ) => { + return storageItems.map( ( storageItem ) => { const [ key, value ] = storageItem; const objectValue = JSON.parse( value ); return { name: key.replace( EXPERIMENT_NAME_PREFIX, '' ), 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(); + } } From ed9a9fca55ad660ed94a33dfc1860e048ed15cad Mon Sep 17 00:00:00 2001 From: Moon Date: Thu, 24 Feb 2022 12:22:01 -0800 Subject: [PATCH 2/3] Add constants for the backend --- src/experiments/data/constants.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/experiments/data/constants.js b/src/experiments/data/constants.js index 9c918cb46e6..53877b8c47c 100644 --- a/src/experiments/data/constants.js +++ b/src/experiments/data/constants.js @@ -1,2 +1,4 @@ export const STORE_KEY = 'wc-admin-helper/experiments'; export const EXPERIMENT_NAME_PREFIX = 'explat-experiment--'; +export const TRANSIENT_NAME_PREFIX = '_transient_abtest_variation_'; +export const API_NAMESPACE = '/wc-admin-test-helper'; From 1071ef87ebf48bf71d0432fdec0da70335164ded Mon Sep 17 00:00:00 2001 From: Moon Date: Thu, 24 Feb 2022 12:35:22 -0800 Subject: [PATCH 3/3] Update toggleExperiment to support backend experiments --- src/experiments/data/actions.js | 38 ++++++++++++++++++++++++---- src/experiments/index.js | 44 +++++++++++++++++++-------------- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/experiments/data/actions.js b/src/experiments/data/actions.js index fdf0f0fdd1d..16716d534da 100644 --- a/src/experiments/data/actions.js +++ b/src/experiments/data/actions.js @@ -1,23 +1,51 @@ +/** + * External dependencies + */ +import { apiFetch } from '@wordpress/data-controls'; + /** * Internal dependencies */ 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( window.localStorage.getItem( EXPERIMENT_NAME_PREFIX + experimentName ) ); - const newVariation = - storageItem.variationName === 'control' ? 'treatment' : 'control'; - storageItem.variationName = newVariation; window.localStorage.setItem( EXPERIMENT_NAME_PREFIX + experimentName, 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 { type: TYPES.TOGGLE_EXPERIMENT, diff --git a/src/experiments/index.js b/src/experiments/index.js index 97e110fb908..15fcdad264a 100644 --- a/src/experiments/index.js +++ b/src/experiments/index.js @@ -24,24 +24,32 @@ function Experiments( { experiments, toggleExperiment } ) { - { experiments.map( ( { name, variation }, index ) => { - return ( - - { name } - { variation } - - - - - ); - } ) } + { experiments.map( + ( { name, variation, source }, index ) => { + return ( + + + { name } + + { variation } + + + + + ); + } + ) }