From fc44fc2a38cba62ec1540ad599d4ed296359f570 Mon Sep 17 00:00:00 2001 From: Alexandre Bourdin Date: Mon, 22 Apr 2024 12:27:05 +0200 Subject: [PATCH] Merge pull request #18017 from overleaf/ab-convert-assigned-at-date [web] Transform assignedAt back to date for conversion GitOrigin-RevId: bd0213b337f765d8512386f9f5d3fc6d03572e33 --- .../SplitTests/SplitTestSessionHandler.js | 4 +- .../test/acceptance/src/helpers/InitApp.js | 48 ++++++- .../web/test/acceptance/src/helpers/User.js | 135 +++++++++++++++++- .../test/acceptance/src/helpers/UserHelper.js | 16 +++ 4 files changed, 195 insertions(+), 8 deletions(-) diff --git a/services/web/app/src/Features/SplitTests/SplitTestSessionHandler.js b/services/web/app/src/Features/SplitTests/SplitTestSessionHandler.js index 5dde68a1e7..7510b6686a 100644 --- a/services/web/app/src/Features/SplitTests/SplitTestSessionHandler.js +++ b/services/web/app/src/Features/SplitTests/SplitTestSessionHandler.js @@ -224,7 +224,9 @@ function _buildAssignmentString(splitTest, assignment) { variantName === 'default' ? 'd' : _.findIndex(variants, { name: variantName }) - const timestamp = Math.floor(assignedAt.getTime() / 1000).toString(36) + const timestamp = Math.floor(new Date(assignedAt).getTime() / 1000).toString( + 36 + ) return `${splitTestId}${ID_VERSION_SEP}${versionNumber}${KEY_VALUE_SEP}${variantChar}${VARIANT_DATE_SEP}${timestamp}` } diff --git a/services/web/test/acceptance/src/helpers/InitApp.js b/services/web/test/acceptance/src/helpers/InitApp.js index c92a47ff3b..56c88758f2 100644 --- a/services/web/test/acceptance/src/helpers/InitApp.js +++ b/services/web/test/acceptance/src/helpers/InitApp.js @@ -10,6 +10,8 @@ const { } = require('../../../../app/src/infrastructure/GracefulShutdown') const { app } = require('../../../../app/src/infrastructure/Server') const { injectRouteAfter } = require('./injectRoute') +const SplitTestHandler = require('../../../../app/src/Features/SplitTests/SplitTestHandler') +const SplitTestSessionHandler = require('../../../../app/src/Features/SplitTests/SplitTestSessionHandler') logger.logger.level('error') @@ -20,8 +22,7 @@ MockReCAPTCHAApi.initialize(2222) let server before('start main app', function (done) { - // We expose a session route in the test environment so that we can - // use it to access email confirmation codes in acceptance tests. + // We expose addition routes in the test environment for acceptance tests. injectRouteAfter( app, route => route.path && route.path === '/dev/csrf', @@ -31,6 +32,49 @@ before('start main app', function (done) { }) } ) + injectRouteAfter( + app, + route => route.path && route.path === '/dev/csrf', + router => { + router.post('/dev/set_in_session', (req, res) => { + for (const [key, value] of Object.entries(req.body)) { + req.session[key] = value + } + return res.sendStatus(200) + }) + } + ) + injectRouteAfter( + app, + route => route.path && route.path === '/dev/csrf', + router => { + router.get('/dev/split_test/get_assignment', (req, res) => { + const { splitTestName } = req.query + SplitTestHandler.promises + .getAssignment(req, res, splitTestName, { + sync: true, + }) + .then(assignment => res.json(assignment)) + .catch(error => { + res.status(500).json({ error: JSON.stringify(error) }) + }) + }) + } + ) + injectRouteAfter( + app, + route => route.path && route.path === '/dev/csrf', + router => { + router.post('/dev/split_test/session_maintenance', (req, res) => { + SplitTestSessionHandler.promises + .sessionMaintenance(req) + .then(res.sendStatus(200)) + .catch(error => { + res.status(500).json({ error: JSON.stringify(error) }) + }) + }) + } + ) server = App.listen(23000, '127.0.0.1', done) }) diff --git a/services/web/test/acceptance/src/helpers/User.js b/services/web/test/acceptance/src/helpers/User.js index aeeb074cf1..011ba1f4de 100644 --- a/services/web/test/acceptance/src/helpers/User.js +++ b/services/web/test/acceptance/src/helpers/User.js @@ -57,6 +57,135 @@ class User { ) } + setInSession(params, callback) { + this.getCsrfToken(error => { + if (error != null) { + return callback(error) + } + this.request.post( + { + url: '/dev/set_in_session', + json: params, + }, + (err, response, body) => { + if (err != null) { + return callback(err) + } + if (response.statusCode !== 200) { + return callback( + new Error( + `post set in session failed: status=${ + response.statusCode + } body=${JSON.stringify(body)}` + ) + ) + } + callback(null) + } + ) + }) + } + + getSplitTestAssignment(splitTestName, query, callback) { + if (!callback) { + callback = query + } + const params = new URLSearchParams({ + splitTestName, + ...query, + }).toString() + this.request.get( + { + url: `/dev/split_test/get_assignment?${params}`, + }, + (err, response, body) => { + if (err != null) { + return callback(err) + } + if (response.statusCode !== 200) { + return callback( + new Error( + `get split test assignment failed: status=${ + response.statusCode + } body=${JSON.stringify(body)}` + ) + ) + } + const assignment = JSON.parse(response.body) + callback(null, assignment) + } + ) + } + + doSessionMaintenance(callback) { + this.request.post( + { + url: `/dev/split_test/session_maintenance`, + }, + (err, response, body) => { + if (err != null) { + return callback(err) + } + if (response.statusCode !== 200) { + return callback( + new Error( + `post session maintenance failed: status=${ + response.statusCode + } body=${JSON.stringify(body)}` + ) + ) + } + callback(null) + } + ) + } + + optIntoBeta(callback) { + this.request.post( + { + url: '/beta/opt-in', + }, + (err, response, body) => { + if (err != null) { + return callback(err) + } + if (response.statusCode !== 302) { + return callback( + new Error( + `post beta opt-in failed: status=${ + response.statusCode + } body=${JSON.stringify(body)}` + ) + ) + } + callback(null) + } + ) + } + + optOutOfBeta(callback) { + this.request.post( + { + url: '/beta/opt-out', + }, + (err, response, body) => { + if (err != null) { + return callback(err) + } + if (response.statusCode !== 302) { + return callback( + new Error( + `post beta opt-out failed: status=${ + response.statusCode + } body=${JSON.stringify(body)}` + ) + ) + } + callback(null) + } + ) + } + getEmailConfirmationCode(callback) { this.getSession((err, session) => { if (err != null) { @@ -317,16 +446,12 @@ class User { this.request.post( { url: '/logout', - json: { - email: this.email, - password: this.password, - }, }, (error, response, body) => { if (error != null) { return callback(error) } - if (response.statusCode !== 200) { + if (response.statusCode >= 400) { return callback( new Error( `logout failed: status=${ diff --git a/services/web/test/acceptance/src/helpers/UserHelper.js b/services/web/test/acceptance/src/helpers/UserHelper.js index 996751fc39..1ef1de7775 100644 --- a/services/web/test/acceptance/src/helpers/UserHelper.js +++ b/services/web/test/acceptance/src/helpers/UserHelper.js @@ -157,6 +157,22 @@ class UserHelper { return JSON.parse(body) } + async getSplitTestAssignment(splitTestName) { + const response = await this.fetch( + `/dev/split_test/get_assignment?splitTestName=${splitTestName}` + ) + const body = await response.text() + + if (response.status !== 200) { + throw new Error( + `get split test assignment failed: status=${response.status} body=${JSON.stringify( + body + )}` + ) + } + return JSON.parse(body) + } + async getEmailConfirmationCode() { const session = await this.getSession()