Skip to content
This repository has been archived by the owner on Apr 3, 2019. It is now read-only.

Commit

Permalink
chore(codes): update clients for token code experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
vbudhram committed Sep 13, 2018
1 parent 7c4a4b0 commit 7d23730
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 82 deletions.
39 changes: 28 additions & 11 deletions app/scripts/lib/experiments/grouping-rules/token-code.js
Expand Up @@ -6,17 +6,24 @@

const BaseGroupingRule = require('./base');
const Constants = require('../../../lib/constants');
const GROUPS = ['control', 'treatment-code', 'treatment-link'];
const GROUPS_DEFAULT = ['control', 'treatment-code', 'treatment-link'];

const ROLLOUT_CLIENTS = {
'3a1f53aabe17ba32': {
name: 'Firefox Add-ons',
rolloutRate: 0.0 // Rollout rate between 0..1
},
'dcdb5ae7add825d2': {
name: '123Done',
'37fdfa37698f251a': {
enableTestEmails: false,
groups: GROUPS_DEFAULT,
name: 'Lockbox Extension',
rolloutRate: 0.0
},
'98adfa37698f255b': {
enableTestEmails: true,
groups: ['treatment-code'],
name: 'Lockbox Extension iOS',
rolloutRate: 0.0,
},
'ecdb5ae7add825d4': {
enableTestEmails: false,
groups: GROUPS_DEFAULT,
name: 'TestClient',
rolloutRate: 0.0
}
Expand All @@ -31,14 +38,24 @@ module.exports = class TokenCodeGroupingRule extends BaseGroupingRule {
}

choose(subject) {
if (! subject || ! subject.uniqueUserId || ! subject.experimentGroupingRules || ! subject.isTokenCodeSupported) {
if (! subject || ! subject.uniqueUserId || ! subject.experimentGroupingRules || ! subject.isTokenCodeSupported || ! subject.account) {
return false;
}

if (subject.clientId) {
const client = this.ROLLOUT_CLIENTS[subject.clientId];
if (client && this.bernoulliTrial(client.rolloutRate, subject.uniqueUserId)) {
return this.uniformChoice(GROUPS, subject.uniqueUserId);

if (client) {
const groups = client.groups || GROUPS_DEFAULT;

// Check if this client supports test emails
if (client.enableTestEmails && this.isTestEmail(subject.account.get('email'))) {
return this.uniformChoice(groups, subject.uniqueUserId);
}

if (this.bernoulliTrial(client.rolloutRate, subject.uniqueUserId)) {
return this.uniformChoice(groups, subject.uniqueUserId);
}
}

// If a clientId was specified but not defined in the rollout configuration, the default
Expand All @@ -48,7 +65,7 @@ module.exports = class TokenCodeGroupingRule extends BaseGroupingRule {

if (subject.service && subject.service === Constants.SYNC_SERVICE) {
if (this.bernoulliTrial(this.SYNC_ROLLOUT_RATE, subject.uniqueUserId)) {
return this.uniformChoice(GROUPS, subject.uniqueUserId);
return this.uniformChoice(GROUPS_DEFAULT, subject.uniqueUserId);
}
}

Expand Down
1 change: 1 addition & 0 deletions app/scripts/views/mixins/token-code-experiment-mixin.js
Expand Up @@ -55,6 +55,7 @@ define(function (require, exports, module) {
*/
_getTokenCodeExperimentSubject () {
const subject = {
account: this.model.get('account'),
clientId: this.relier.get('clientId'),
isTokenCodeSupported: this.broker.getCapability('tokenCode'),
service: this.relier.get('service'),
Expand Down
152 changes: 81 additions & 71 deletions app/tests/spec/lib/experiments/grouping-rules/token-code.js
Expand Up @@ -2,92 +2,102 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

define(function (require, exports, module) {
'use strict';
import {assert} from 'chai';
import Account from 'models/account';
import Experiment from 'lib/experiments/grouping-rules/token-code';
import sinon from 'sinon';

const {assert} = require('chai');
const Experiment = require('lib/experiments/grouping-rules/token-code');
const sinon = require('sinon');
const ROLLOUT_CLIENTS = {
'3a1f53aabe17ba32': {
name: 'Firefox Add-ons',
rolloutRate: 0.0 // Rollout rate between 0..1
},
'dcdb5ae7add825d2': {
name: '123Done',
rolloutRate: 1.0
},
'ecdb5ae7add825d4': {
enableTestEmails: true,
name: 'TestClient',
rolloutRate: 0.0
},
};

const ROLLOUT_CLIENTS = {
'3a1f53aabe17ba32': {
name: 'Firefox Add-ons',
rolloutRate: 0.0 // Rollout rate between 0..1
},
'dcdb5ae7add825d2': {
name: '123Done',
rolloutRate: 1.0
},
'ecdb5ae7add825d4': {
name: 'TestClient',
rolloutRate: 0.0
}
};
describe('lib/experiments/grouping-rules/token-code', () => {
describe('choose', () => {
let account;
let experiment;
let subject;

describe('lib/experiments/grouping-rules/token-code', () => {
describe('choose', () => {
let experiment;
let subject;
beforeEach(() => {
account = new Account();
experiment = new Experiment();
experiment.ROLLOUT_CLIENTS = ROLLOUT_CLIENTS;
subject = {
account: account,
experimentGroupingRules: {},
isTokenCodeSupported: true,
service: null,
uniqueUserId: 'user-id'
};
});

beforeEach(() => {
experiment = new Experiment();
experiment.ROLLOUT_CLIENTS = ROLLOUT_CLIENTS;
subject = {
experimentGroupingRules: {},
isTokenCodeSupported: true,
service: null,
uniqueUserId: 'user-id'
};
});
it('returns false experiment not enabled', () => {
subject = {
isTokenCodeSupported: false
};
assert.equal(experiment.choose(subject), false);
});

it('returns false experiment not enabled', () => {
subject = {
isTokenCodeSupported: false
};
describe('with oauth client', () => {
it('returns false if client not defined in config', () => {
subject.clientId = 'invalidClientId';
assert.equal(experiment.choose(subject), false);
});

describe('with oauth client', () => {
it('returns false if client not defined in config', () => {
subject.clientId = 'invalidClientId';
assert.equal(experiment.choose(subject), false);
});
it('returns false if client rollout is 0', () => {
subject.clientId = '3a1f53aabe17ba32';
assert.equal(experiment.choose(subject), false);
});

it('returns false if client rollout is 0', () => {
subject.clientId = '3a1f53aabe17ba32';
assert.equal(experiment.choose(subject), false);
});
it('delegates to uniformChoice', () => {
subject.clientId = 'dcdb5ae7add825d2';
sinon.stub(experiment, 'uniformChoice').callsFake(() => 'control');
experiment.choose(subject);
assert.isTrue(experiment.uniformChoice.calledOnce);
assert.isTrue(experiment.uniformChoice.calledWith(['control', 'treatment-code', 'treatment-link'], 'user-id'));
});

it('delegates to uniformChoice', () => {
subject.clientId = 'dcdb5ae7add825d2';
sinon.stub(experiment, 'uniformChoice').callsFake(() => 'control');
experiment.choose(subject);
assert.isTrue(experiment.uniformChoice.calledOnce);
assert.isTrue(experiment.uniformChoice.calledWith(['control', 'treatment-code', 'treatment-link'], 'user-id'));
});
it('delegates to uniformChoice when `enableTestEmails` is true and using test email', () => {
subject.clientId = 'ecdb5ae7add825d4';
subject.account.set('email', 'a@mozilla.org');
sinon.stub(experiment, 'uniformChoice').callsFake(() => 'control');
experiment.choose(subject);
assert.isTrue(experiment.uniformChoice.calledOnce);
assert.isTrue(experiment.uniformChoice.calledWith(['control', 'treatment-code', 'treatment-link'], 'user-id'));
});
});

describe('with sync', () => {
beforeEach(() => {
subject.service = 'sync';
});
describe('with sync', () => {
beforeEach(() => {
subject.service = 'sync';
});

it('returns false if not Sync', () => {
subject.service = 'notSync';
assert.equal(experiment.choose(subject), false);
});
it('returns false if not Sync', () => {
subject.service = 'notSync';
assert.equal(experiment.choose(subject), false);
});

it('returns false if rollout is 0', () => {
assert.equal(experiment.choose(subject), false);
});
it('returns false if rollout is 0', () => {
assert.equal(experiment.choose(subject), false);
});

it('delegates to uniformChoice', () => {
experiment.SYNC_ROLLOUT_RATE = 1.0;
sinon.stub(experiment, 'uniformChoice').callsFake(() => 'control');
experiment.choose(subject);
assert.isTrue(experiment.uniformChoice.calledOnce, 'called once');
assert.isTrue(experiment.uniformChoice.calledWith(['control', 'treatment-code', 'treatment-link'], 'user-id'));
});
it('delegates to uniformChoice', () => {
experiment.SYNC_ROLLOUT_RATE = 1.0;
sinon.stub(experiment, 'uniformChoice').callsFake(() => 'control');
experiment.choose(subject);
assert.isTrue(experiment.uniformChoice.calledOnce, 'called once');
assert.isTrue(experiment.uniformChoice.calledWith(['control', 'treatment-code', 'treatment-link'], 'user-id'));
});
});
});
Expand Down

0 comments on commit 7d23730

Please sign in to comment.