Merge pull request #17907 from overleaf/ab-split-test-assignments-optim-pt1
[web] Read anonymous split test assignments in session from both old&new fields GitOrigin-RevId: 5235bb3e7d72d5ff9e89c6543b70fb80e9f1213c
This commit is contained in:
committed by
Copybot
parent
945e51b8ed
commit
bee4c95c28
@@ -23,14 +23,14 @@ describe('BetaProgramController', function () {
|
||||
user: this.user,
|
||||
},
|
||||
}
|
||||
this.SplitTestHandler = {
|
||||
this.SplitTestSessionHandler = {
|
||||
promises: {
|
||||
sessionMaintenance: sinon.stub(),
|
||||
},
|
||||
}
|
||||
this.BetaProgramController = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'../SplitTests/SplitTestHandler': this.SplitTestHandler,
|
||||
'../SplitTests/SplitTestSessionHandler': this.SplitTestSessionHandler,
|
||||
'./BetaProgramHandler': (this.BetaProgramHandler = {
|
||||
promises: {
|
||||
optIn: sinon.stub().resolves(),
|
||||
@@ -76,7 +76,7 @@ describe('BetaProgramController', function () {
|
||||
|
||||
it('should invoke the session maintenance', function (done) {
|
||||
this.res.callback = () => {
|
||||
this.SplitTestHandler.promises.sessionMaintenance.should.have.been.calledWith(
|
||||
this.SplitTestSessionHandler.promises.sessionMaintenance.should.have.been.calledWith(
|
||||
this.req
|
||||
)
|
||||
done()
|
||||
@@ -130,7 +130,7 @@ describe('BetaProgramController', function () {
|
||||
|
||||
it('should invoke the session maintenance', function (done) {
|
||||
this.res.callback = () => {
|
||||
this.SplitTestHandler.promises.sessionMaintenance.should.have.been.calledWith(
|
||||
this.SplitTestSessionHandler.promises.sessionMaintenance.should.have.been.calledWith(
|
||||
this.req,
|
||||
null
|
||||
)
|
||||
|
||||
@@ -136,6 +136,8 @@ describe('ProjectController', function () {
|
||||
getAssignment: sinon.stub().resolves({ variant: 'default' }),
|
||||
},
|
||||
getAssignment: sinon.stub().yields(null, { variant: 'default' }),
|
||||
}
|
||||
this.SplitTestSessionHandler = {
|
||||
sessionMaintenance: sinon.stub().yields(),
|
||||
}
|
||||
this.InstitutionsFeatures = {
|
||||
@@ -160,6 +162,7 @@ describe('ProjectController', function () {
|
||||
'@overleaf/settings': this.settings,
|
||||
'@overleaf/metrics': this.Metrics,
|
||||
'../SplitTests/SplitTestHandler': this.SplitTestHandler,
|
||||
'../SplitTests/SplitTestSessionHandler': this.SplitTestSessionHandler,
|
||||
'./ProjectDeleter': this.ProjectDeleter,
|
||||
'./ProjectDuplicator': this.ProjectDuplicator,
|
||||
'./ProjectCreationHandler': this.ProjectCreationHandler,
|
||||
@@ -536,7 +539,7 @@ describe('ProjectController', function () {
|
||||
|
||||
it('should invoke the session maintenance for logged in user', function (done) {
|
||||
this.res.render = () => {
|
||||
this.SplitTestHandler.sessionMaintenance.should.have.been.calledWith(
|
||||
this.SplitTestSessionHandler.sessionMaintenance.should.have.been.calledWith(
|
||||
this.req,
|
||||
this.user
|
||||
)
|
||||
@@ -548,7 +551,7 @@ describe('ProjectController', function () {
|
||||
it('should invoke the session maintenance for anonymous user', function (done) {
|
||||
this.SessionManager.getLoggedInUserId.returns(null)
|
||||
this.res.render = () => {
|
||||
this.SplitTestHandler.sessionMaintenance.should.have.been.calledWith(
|
||||
this.SplitTestSessionHandler.sessionMaintenance.should.have.been.calledWith(
|
||||
this.req
|
||||
)
|
||||
done()
|
||||
|
||||
@@ -102,10 +102,14 @@ describe('ProjectListController', function () {
|
||||
}
|
||||
this.SplitTestHandler = {
|
||||
promises: {
|
||||
sessionMaintenance: sinon.stub().resolves(),
|
||||
getAssignment: sinon.stub().resolves({ variant: 'default' }),
|
||||
},
|
||||
}
|
||||
this.SplitTestSessionHandler = {
|
||||
promises: {
|
||||
sessionMaintenance: sinon.stub().resolves(),
|
||||
},
|
||||
}
|
||||
this.SubscriptionViewModelBuilder = {
|
||||
promises: {
|
||||
getBestSubscription: sinon.stub().resolves({ type: 'free' }),
|
||||
@@ -141,6 +145,7 @@ describe('ProjectListController', function () {
|
||||
'@overleaf/settings': this.settings,
|
||||
'@overleaf/metrics': this.Metrics,
|
||||
'../SplitTests/SplitTestHandler': this.SplitTestHandler,
|
||||
'../SplitTests/SplitTestSessionHandler': this.SplitTestSessionHandler,
|
||||
'../User/UserController': this.UserController,
|
||||
'./ProjectHelper': this.ProjectHelper,
|
||||
'../Subscription/LimitationsManager': this.LimitationsManager,
|
||||
@@ -223,7 +228,7 @@ describe('ProjectListController', function () {
|
||||
it('should invoke the session maintenance', function (done) {
|
||||
this.Features.hasFeature.withArgs('saas').returns(true)
|
||||
this.res.render = () => {
|
||||
this.SplitTestHandler.promises.sessionMaintenance.should.have.been.calledWith(
|
||||
this.SplitTestSessionHandler.promises.sessionMaintenance.should.have.been.calledWith(
|
||||
this.req,
|
||||
this.user
|
||||
)
|
||||
|
||||
@@ -27,12 +27,6 @@ describe('SplitTestHandler', function () {
|
||||
this.cachedSplitTests.set(splitTest.name, splitTest)
|
||||
}
|
||||
|
||||
this.UserGetter = {
|
||||
promises: {
|
||||
getUser: sinon.stub().resolves(null),
|
||||
},
|
||||
}
|
||||
|
||||
this.SplitTest = {
|
||||
find: sinon.stub().returns({
|
||||
exec: sinon.stub().resolves(this.splitTests),
|
||||
@@ -54,11 +48,20 @@ describe('SplitTestHandler', function () {
|
||||
}
|
||||
this.AnalyticsManager = {
|
||||
getIdsFromSession: sinon.stub(),
|
||||
setUserPropertyForAnalyticsId: sinon.stub(),
|
||||
}
|
||||
this.LocalsHelper = {
|
||||
setSplitTestVariant: sinon.stub(),
|
||||
setSplitTestInfo: sinon.stub(),
|
||||
}
|
||||
this.SplitTestSessionHandler = {
|
||||
collectSessionStats: sinon.stub(),
|
||||
}
|
||||
this.SplitTestUserGetter = {
|
||||
promises: {
|
||||
getUser: sinon.stub().resolves(null),
|
||||
},
|
||||
}
|
||||
|
||||
this.SplitTestHandler = SandboxedModule.require(MODULE_PATH, {
|
||||
requires: {
|
||||
@@ -68,6 +71,8 @@ describe('SplitTestHandler', function () {
|
||||
'../User/UserUpdater': {},
|
||||
'../Analytics/AnalyticsManager': this.AnalyticsManager,
|
||||
'./LocalsHelper': this.LocalsHelper,
|
||||
'./SplitTestSessionHandler': this.SplitTestSessionHandler,
|
||||
'./SplitTestUserGetter': this.SplitTestUserGetter,
|
||||
'@overleaf/settings': this.Settings,
|
||||
},
|
||||
})
|
||||
@@ -100,9 +105,7 @@ describe('SplitTestHandler', function () {
|
||||
],
|
||||
},
|
||||
}
|
||||
this.UserGetter.promises.getUser
|
||||
.withArgs(this.user._id)
|
||||
.resolves(this.user)
|
||||
this.SplitTestUserGetter.promises.getUser.resolves(this.user)
|
||||
this.assignments =
|
||||
await this.SplitTestHandler.promises.getActiveAssignmentsForUser(
|
||||
this.user._id
|
||||
@@ -164,9 +167,7 @@ describe('SplitTestHandler', function () {
|
||||
describe('with a user without assignments', function () {
|
||||
beforeEach(async function () {
|
||||
this.user = { _id: new ObjectId() }
|
||||
this.UserGetter.promises.getUser
|
||||
.withArgs(this.user._id)
|
||||
.resolves(this.user)
|
||||
this.SplitTestUserGetter.promises.getUser.resolves(this.user)
|
||||
this.assignments =
|
||||
await this.SplitTestHandler.promises.getActiveAssignmentsForUser(
|
||||
this.user._id
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
const Path = require('path')
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const sinon = require('sinon')
|
||||
const { expect } = require('chai')
|
||||
|
||||
const MODULE_PATH = Path.join(
|
||||
__dirname,
|
||||
'../../../../app/src/Features/SplitTests/SplitTestSessionHandler'
|
||||
)
|
||||
|
||||
describe('SplitTestSessionHandler', function () {
|
||||
beforeEach(function () {
|
||||
this.SplitTestCache = {
|
||||
get: sinon.stub().resolves(),
|
||||
}
|
||||
this.SplitTestUserGetter = {}
|
||||
this.Metrics = {}
|
||||
this.SplitTestSessionHandler = SandboxedModule.require(MODULE_PATH, {
|
||||
requires: {
|
||||
'./SplitTestCache': this.SplitTestCache,
|
||||
'./SplitTestUserGetter': this.SplitTestUserGetter,
|
||||
'@overleaf/metrics': this.Metrics,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('should read from the splitTests field', async function () {
|
||||
const session = {
|
||||
splitTests: {
|
||||
'anon-test-1': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712872800000), // 2024-04-11 22:00:00
|
||||
},
|
||||
],
|
||||
'anon-test-2': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712307600000), // 2024-04-05 09:00:00
|
||||
},
|
||||
{
|
||||
variantName: 'v-2',
|
||||
versionNumber: 2,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712581200000), // 2024-04-08 13:00:00
|
||||
},
|
||||
],
|
||||
},
|
||||
sta: ``,
|
||||
}
|
||||
|
||||
const assignments =
|
||||
await this.SplitTestSessionHandler.promises.getAssignments(session)
|
||||
expect(assignments).to.deep.equal({
|
||||
'anon-test-1': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712872800000),
|
||||
},
|
||||
],
|
||||
'anon-test-2': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712307600000),
|
||||
},
|
||||
{
|
||||
variantName: 'v-2',
|
||||
versionNumber: 2,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712581200000),
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should not read from the sta field', async function () {
|
||||
this.SplitTestCache.get = sinon.stub().resolves(
|
||||
new Map(
|
||||
Object.entries({
|
||||
'anon-test-1': {
|
||||
_id: '661f92a4669764bb03f73e37',
|
||||
name: 'anon-test-1',
|
||||
versions: [
|
||||
{
|
||||
versionNumber: 1,
|
||||
variants: [
|
||||
{
|
||||
name: 'enabled',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
'anon-test-2': {
|
||||
_id: '661f92a9d68ea711d6bf2df4',
|
||||
name: 'anon-test-2',
|
||||
versions: [
|
||||
{
|
||||
versionNumber: 1,
|
||||
variants: [
|
||||
{
|
||||
name: 'v-1',
|
||||
},
|
||||
{
|
||||
name: 'v-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
)
|
||||
)
|
||||
const session = {
|
||||
sta: `Zh+SpGaXZLsD9z43_1=d:sbrvs0;Zh+SqdaOpxHWvy30_1=d:sbtqg0;Zh+SqdaOpxHWvy30_2=1:sbsi00`,
|
||||
}
|
||||
|
||||
const assignments =
|
||||
await this.SplitTestSessionHandler.promises.getAssignments(session)
|
||||
expect(assignments).to.deep.equal({
|
||||
'anon-test-1': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712829600000),
|
||||
},
|
||||
],
|
||||
'anon-test-2': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712916000000),
|
||||
},
|
||||
{
|
||||
variantName: 'v-2',
|
||||
versionNumber: 2,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712858400000),
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should merge assignments from both splitTests and sta fields', async function () {
|
||||
this.SplitTestCache.get = sinon.stub().resolves(
|
||||
new Map(
|
||||
Object.entries({
|
||||
'anon-test-1': {
|
||||
_id: '661f92a4669764bb03f73e37',
|
||||
name: 'anon-test-1',
|
||||
versions: [
|
||||
{
|
||||
versionNumber: 1,
|
||||
variants: [
|
||||
{
|
||||
name: 'enabled',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
'anon-test-2': {
|
||||
_id: '661f92a9d68ea711d6bf2df4',
|
||||
name: 'anon-test-2',
|
||||
versions: [
|
||||
{
|
||||
versionNumber: 1,
|
||||
variants: [
|
||||
{
|
||||
name: 'v-1',
|
||||
},
|
||||
{
|
||||
name: 'v-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
)
|
||||
)
|
||||
const session = {
|
||||
splitTests: {
|
||||
'anon-test-1': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712872800000),
|
||||
},
|
||||
],
|
||||
'anon-test-2': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712307600000),
|
||||
},
|
||||
],
|
||||
},
|
||||
sta: `Zh+SqdaOpxHWvy30_2=1:sbsi00`,
|
||||
}
|
||||
|
||||
const assignments =
|
||||
await this.SplitTestSessionHandler.promises.getAssignments(session)
|
||||
expect(assignments).to.deep.equal({
|
||||
'anon-test-1': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712872800000),
|
||||
},
|
||||
],
|
||||
'anon-test-2': [
|
||||
{
|
||||
variantName: 'default',
|
||||
versionNumber: 1,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712307600000),
|
||||
},
|
||||
{
|
||||
variantName: 'v-2',
|
||||
versionNumber: 2,
|
||||
phase: 'release',
|
||||
assignedAt: new Date(1712858400000),
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user