mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #5769 from overleaf/ab-null-split-tests
Setup null split tests GitOrigin-RevId: 4cba55e123d0a4add19cdace7434506e9d20c7a9
This commit is contained in:
parent
fa6bc3fc7b
commit
f9873619ad
4 changed files with 68 additions and 11 deletions
|
@ -611,6 +611,12 @@ const ProjectController = {
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// null test targeting logged in users
|
||||||
|
SplitTestV2Handler.promises.getAssignmentForSession(
|
||||||
|
req.session,
|
||||||
|
'null-test-dashboard'
|
||||||
|
)
|
||||||
|
|
||||||
res.render('project/list', viewModel)
|
res.render('project/list', viewModel)
|
||||||
timer.done()
|
timer.done()
|
||||||
})
|
})
|
||||||
|
@ -724,12 +730,27 @@ const ProjectController = {
|
||||||
TpdsProjectFlusher.flushProjectToTpdsIfNeeded(projectId, cb)
|
TpdsProjectFlusher.flushProjectToTpdsIfNeeded(projectId, cb)
|
||||||
},
|
},
|
||||||
sharingModalSplitTest(cb) {
|
sharingModalSplitTest(cb) {
|
||||||
SplitTestV2Handler.assignInLocalsContext(
|
SplitTestV2Handler.assignInLocalsContextForSession(
|
||||||
res,
|
res,
|
||||||
userId,
|
req.session,
|
||||||
'project-share-modal-paywall',
|
'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(
|
SplitTestV2Handler.getAssignmentForSession(
|
||||||
req.session,
|
req.session,
|
||||||
'react-pdf-preview-rollout',
|
'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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -78,6 +78,15 @@ async function getAssignmentForSession(session, splitTestName, options) {
|
||||||
return _getAssignment(analyticsId, userId, 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) {
|
async function assignInLocalsContext(res, userId, splitTestName, options) {
|
||||||
const assignment = await getAssignment(userId, splitTestName, options)
|
const assignment = await getAssignment(userId, splitTestName, options)
|
||||||
if (!res.locals.splitTestVariants) {
|
if (!res.locals.splitTestVariants) {
|
||||||
|
@ -86,6 +95,15 @@ async function assignInLocalsContext(res, userId, splitTestName, options) {
|
||||||
res.locals.splitTestVariants[splitTestName] = assignment.variant
|
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(
|
async function assignInLocalsContextForSession(
|
||||||
res,
|
res,
|
||||||
session,
|
session,
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { useSplitTestContext } from '../../../shared/context/split-test-context'
|
||||||
import { Row } from 'react-bootstrap'
|
import { Row } from 'react-bootstrap'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import RecaptchaConditions from '../../../shared/components/recaptcha-conditions'
|
import RecaptchaConditions from '../../../shared/components/recaptcha-conditions'
|
||||||
|
import * as eventTracking from '../../../infrastructure/event-tracking'
|
||||||
|
|
||||||
export default function ShareModalBody() {
|
export default function ShareModalBody() {
|
||||||
const { isAdmin } = useShareProjectContext()
|
const { isAdmin } = useShareProjectContext()
|
||||||
|
@ -18,6 +19,10 @@ export default function ShareModalBody() {
|
||||||
splitTestVariants: PropTypes.object,
|
splitTestVariants: PropTypes.object,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
eventTracking.sendMB('share-modal-opened', {
|
||||||
|
splitTestVariant: splitTestVariants['null-test-share-modal'],
|
||||||
|
})
|
||||||
|
|
||||||
const project = useProjectContext()
|
const project = useProjectContext()
|
||||||
|
|
||||||
switch (splitTestVariants['project-share-modal-paywall']) {
|
switch (splitTestVariants['project-share-modal-paywall']) {
|
||||||
|
|
|
@ -136,14 +136,21 @@ describe('ProjectController', function () {
|
||||||
}
|
}
|
||||||
this.SplitTestV2Handler = {
|
this.SplitTestV2Handler = {
|
||||||
promises: {
|
promises: {
|
||||||
getAssignment: sinon.stub().resolves({ active: false }),
|
getAssignment: sinon.stub().resolves({ variant: 'default' }),
|
||||||
assignInLocalsContext: sinon.stub().resolves(),
|
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
|
getAssignmentForSession: sinon
|
||||||
.stub()
|
.stub()
|
||||||
.yields(null, { variant: 'variant' }),
|
.yields(null, { variant: 'default' }),
|
||||||
getAssignment: sinon.stub().yields(null, { active: false }),
|
assignInLocalsContext: sinon.stub().yields(null, { variant: 'default' }),
|
||||||
assignInLocalsContext: sinon.stub().yields(null),
|
assignInLocalsContextForSession: sinon
|
||||||
|
.stub()
|
||||||
|
.yields(null, { variant: 'default' }),
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ProjectController = SandboxedModule.require(MODULE_PATH, {
|
this.ProjectController = SandboxedModule.require(MODULE_PATH, {
|
||||||
|
|
Loading…
Reference in a new issue