Merge pull request #5769 from overleaf/ab-null-split-tests

Setup null split tests

GitOrigin-RevId: 4cba55e123d0a4add19cdace7434506e9d20c7a9
This commit is contained in:
Alexandre Bourdin 2021-11-22 11:35:10 +01:00 committed by Copybot
parent fa6bc3fc7b
commit f9873619ad
4 changed files with 68 additions and 11 deletions

View file

@ -611,6 +611,12 @@ const ProjectController = {
: undefined
}
// null test targeting logged in users
SplitTestV2Handler.promises.getAssignmentForSession(
req.session,
'null-test-dashboard'
)
res.render('project/list', viewModel)
timer.done()
})
@ -724,12 +730,27 @@ const ProjectController = {
TpdsProjectFlusher.flushProjectToTpdsIfNeeded(projectId, cb)
},
sharingModalSplitTest(cb) {
SplitTestV2Handler.assignInLocalsContext(
SplitTestV2Handler.assignInLocalsContextForSession(
res,
userId,
req.session,
'project-share-modal-paywall',
err => {
cb(err, null)
{},
() => {
// do not fail editor load if assignment fails
cb()
}
)
},
sharingModalNullTest(cb) {
// null test targeting logged in users, for front-end side
SplitTestV2Handler.assignInLocalsContextForSession(
res,
req.session,
'null-test-share-modal',
{},
() => {
// do not fail editor load if assignment fails
cb()
}
)
},
@ -737,8 +758,14 @@ const ProjectController = {
SplitTestV2Handler.getAssignmentForSession(
req.session,
'react-pdf-preview-rollout',
(err, assignment) => {
cb(err, assignment)
{},
(error, assignment) => {
if (error) {
// do not fail editor load if assignment fails
cb(null, { variant: 'default' })
} else {
cb(null, assignment)
}
}
)
},

View file

@ -78,6 +78,15 @@ async function getAssignmentForSession(session, splitTestName, options) {
return _getAssignment(analyticsId, userId, session, splitTestName, options)
}
/**
* Get the assignment of a user to a split test by their ID and stores it in the locals context.
*
* @param res the Express response object
* @param userId the user ID
* @param splitTestName the unique name of the split test
* @param options {Object<sync: boolean>} - for test purposes only, to force the synchronous update of the user's profile
* @returns {Promise<void>}
*/
async function assignInLocalsContext(res, userId, splitTestName, options) {
const assignment = await getAssignment(userId, splitTestName, options)
if (!res.locals.splitTestVariants) {
@ -86,6 +95,15 @@ async function assignInLocalsContext(res, userId, splitTestName, options) {
res.locals.splitTestVariants[splitTestName] = assignment.variant
}
/**
* Get the assignment of a user to a split test by their session and stores it in the locals context.
*
* @param res the Express response object
* @param session the request session
* @param splitTestName the unique name of the split test
* @param options {Object<sync: boolean>} - for test purposes only, to force the synchronous update of the user's profile
* @returns {Promise<void>}
*/
async function assignInLocalsContextForSession(
res,
session,

View file

@ -11,6 +11,7 @@ import { useSplitTestContext } from '../../../shared/context/split-test-context'
import { Row } from 'react-bootstrap'
import PropTypes from 'prop-types'
import RecaptchaConditions from '../../../shared/components/recaptcha-conditions'
import * as eventTracking from '../../../infrastructure/event-tracking'
export default function ShareModalBody() {
const { isAdmin } = useShareProjectContext()
@ -18,6 +19,10 @@ export default function ShareModalBody() {
splitTestVariants: PropTypes.object,
})
eventTracking.sendMB('share-modal-opened', {
splitTestVariant: splitTestVariants['null-test-share-modal'],
})
const project = useProjectContext()
switch (splitTestVariants['project-share-modal-paywall']) {

View file

@ -136,14 +136,21 @@ describe('ProjectController', function () {
}
this.SplitTestV2Handler = {
promises: {
getAssignment: sinon.stub().resolves({ active: false }),
assignInLocalsContext: sinon.stub().resolves(),
getAssignment: sinon.stub().resolves({ variant: 'default' }),
getAssignmentForSession: sinon.stub().resolves({ variant: 'default' }),
assignInLocalsContext: sinon.stub().resolves({ variant: 'default' }),
assignInLocalsContextForSession: sinon
.stub()
.resolves({ variant: 'default' }),
},
getAssignment: sinon.stub().yields(null, { variant: 'default' }),
getAssignmentForSession: sinon
.stub()
.yields(null, { variant: 'variant' }),
getAssignment: sinon.stub().yields(null, { active: false }),
assignInLocalsContext: sinon.stub().yields(null),
.yields(null, { variant: 'default' }),
assignInLocalsContext: sinon.stub().yields(null, { variant: 'default' }),
assignInLocalsContextForSession: sinon
.stub()
.yields(null, { variant: 'default' }),
}
this.ProjectController = SandboxedModule.require(MODULE_PATH, {