Просмотр исходного кода

Merge pull request #17530 from overleaf/dp-teardown-onboarding-flow-split-test

Teardown onboarding flow split test

GitOrigin-RevId: 48e95e4e736772074cb68d195fc950a9da3aebcf
David 2 лет назад
Родитель
Сommit
b1928cecef

+ 1 - 8
services/web/app/src/Features/StaticPages/HomeController.js

@@ -7,7 +7,6 @@ const fs = require('fs')
 const ErrorController = require('../Errors/ErrorController')
 const SessionManager = require('../Authentication/SessionManager')
 
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
 const { expressify } = require('@overleaf/promise-utils')
 const logger = require('@overleaf/logger')
 
@@ -32,17 +31,11 @@ async function index(req, res) {
 
 async function home(req, res) {
   if (Features.hasFeature('homepage') && homepageExists) {
-    const onboardingFlowAssignment =
-      await SplitTestHandler.promises.getAssignment(req, res, 'onboarding-flow')
     AnalyticsManager.recordEventForSession(req.session, 'home-page-view', {
       page: req.path,
     })
 
-    res.render('external/home/website-redesign/index', {
-      onboardingFlowVariant: onboardingFlowAssignment.variant,
-      hideNewsletterCheckbox:
-        onboardingFlowAssignment.variant === 'token-confirmation-odc',
-    })
+    res.render('external/home/website-redesign/index')
   } else {
     res.redirect('/login')
   }

+ 0 - 8
services/web/app/src/Features/User/UserCreator.js

@@ -7,7 +7,6 @@ const UserDeleter = require('./UserDeleter')
 const UserGetter = require('./UserGetter')
 const UserUpdater = require('./UserUpdater')
 const Analytics = require('../Analytics/AnalyticsManager')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
 const UserOnboardingEmailManager = require('./UserOnboardingEmailManager')
 const UserPostRegistrationAnalyticsManager = require('./UserPostRegistrationAnalyticsManager')
 const OError = require('@overleaf/o-error')
@@ -37,16 +36,9 @@ async function _addAffiliation(user, affiliationOptions) {
 }
 
 async function recordRegistrationEvent(user) {
-  const onboardingFlowAssignment =
-    await SplitTestHandler.promises.getAssignmentForUser(
-      user._id,
-      'onboarding-flow'
-    )
-
   try {
     const segmentation = {
       'home-registration': 'default',
-      'onboarding-flow': onboardingFlowAssignment.variant,
     }
     if (user.thirdPartyIdentifiers && user.thirdPartyIdentifiers.length > 0) {
       segmentation.provider = user.thirdPartyIdentifiers[0].providerId

+ 0 - 1
services/web/locales/da.json

@@ -945,7 +945,6 @@
   "new_tag": "Nyt tag",
   "new_tag_name": "Navn til nyt tag",
   "newsletter": "Nyhedsbrev",
-  "newsletter-accept": "Jeg vil gerne modtage e-mails om produkttilbud, virksomhedsnyheder og begivenheder.",
   "newsletter_info_note": "Du vil stadig modtage vigtige e-mails såsom projektinvitationer og sikkerhedsbeskeder (nulstilling af kode, kontoforbindelser, osv.).",
   "newsletter_info_subscribed": "Du er <0>tilmeldt</0> til __appName__s nyhedsbrev. Hvis du foretrækker ikke at modtage disse e-mails, kan du altid framelde dig.",
   "newsletter_info_summary": "Hvert par måneder sender vi et nyhedsbrev som opsummerer de nyeste tilgængelige funktioner.",

+ 0 - 1
services/web/locales/de.json

@@ -937,7 +937,6 @@
   "new_snippet_project": "Ohne Titel",
   "new_subscription_will_be_billed_immediately": "Dein neues Abonnement wird umgehend mit deiner aktuellen Zahlungsmethode abgerechnet.",
   "newsletter": "Newsletter",
-  "newsletter-accept": "Ich möchte E-Mails zu Produktangeboten, Neuigkeiten und Veranstaltungen des Unternehmens erhalten.",
   "newsletter_info_note": "Bitte beachte: Du erhältst weiterhin wichtige E-Mails wie Projekteinladungen und Sicherheitsbenachrichtigungen (Passwortzurücksetzung, Kontoverknüpfung usw.).",
   "newsletter_info_subscribed": "Du hast den __appName__-Newsletter <0>abonniert</0>. Wenn du diese E-Mails lieber nicht erhalten möchtest, kannst du dich jederzeit abmelden.",
   "newsletter_info_summary": "Alle paar Monate versenden wir einen Newsletter mit einer Zusammenfassung der neu verfügbaren Funktionen.",

+ 0 - 1
services/web/locales/en.json

@@ -1177,7 +1177,6 @@
   "new_tag": "New Tag",
   "new_tag_name": "New tag name",
   "newsletter": "Newsletter",
-  "newsletter-accept": "I’d like emails about product offers and company news and events.",
   "newsletter_info_note": "Please note: you will still receive important emails, such as project invites and security notifications (password resets, account linking, etc).",
   "newsletter_info_subscribed": "You are currently <0>subscribed</0> to the __appName__ newsletter. If you would prefer not to receive this email then you can unsubscribe at any time.",
   "newsletter_info_summary": "Every few months we send a newsletter out summarizing the new features available.",

+ 0 - 1
services/web/locales/fr.json

@@ -606,7 +606,6 @@
   "new_password": "Nouveau mot de passe",
   "new_project": "Nouveau projet",
   "new_snippet_project": "Sans titre",
-  "newsletter-accept": "Je souhaite recevoir des courriels portant sur des offres de produits et sur les actualités et événements de notre entreprise.",
   "next_payment_of_x_collectected_on_y": "Le prochain paiement de  <0>__paymentAmmount__</0> sera débité le <1>__collectionDate__</1>.",
   "nl": "Hollandais",
   "no": "Norvégien",

+ 0 - 1
services/web/locales/pt.json

@@ -413,7 +413,6 @@
   "new_name": "Novo Nome",
   "new_password": "Nova Senha",
   "new_project": "Novo Projeto",
-  "newsletter-accept": "Gostaria de receber e-mails sobre ofertas de produtos, notícias e eventos da empresa.",
   "next_payment_of_x_collectected_on_y": "O próximo pagamento de <0>__paymentAmmount__</0> será coletado em <1>__collectionDate__</1>",
   "nl": "Holandês",
   "no": "Noroeguês",

+ 0 - 1
services/web/locales/sv.json

@@ -579,7 +579,6 @@
   "new_password": "Nytt lösenord",
   "new_project": "Nytt projekt",
   "new_snippet_project": "Namnlös",
-  "newsletter-accept": "Jag vill få e-post om produkterbjudanden, nyheter och evenemang från företaget.",
   "next_payment_of_x_collectected_on_y": "Nästa betalning på <0>__paymentAmmount__</0> kommer att genomföras den <1>__collectionDate__</1>",
   "nl": "Holländska",
   "no": "Norska",

+ 0 - 1
services/web/locales/zh-CN.json

@@ -1153,7 +1153,6 @@
   "new_tag": "新建标签",
   "new_tag_name": "新标签名",
   "newsletter": "电子邮件",
-  "newsletter-accept": "我想要关于产品报价和公司新闻和事件的电子邮件。",
   "newsletter_info_note": "请注意:您仍然会收到重要的电子邮件,例如项目邀请和安全通知(密码重置、帐户链接等)。",
   "newsletter_info_subscribed": "您当前<0>订阅了</0>__appName__ 新闻资讯。 如果您不想收到此电子邮件,则可以随时取消订阅。",
   "newsletter_info_summary": "每隔几个月,我们就会发送一份简讯,总结可用的新功能。",

+ 45 - 0
services/web/test/acceptance/src/helpers/InitApp.js

@@ -8,6 +8,50 @@ const MockReCAPTCHAApi = require('../mocks/MockReCaptchaApi')
 const {
   gracefulShutdown,
 } = require('../../../../app/src/infrastructure/GracefulShutdown')
+const { app } = require('../../../../app/src/infrastructure/Server')
+
+/**
+ * Inject an endpoint to get the current users session into our app. This
+ * endpoint should only be available when running in the test environment.
+ * It is used to retrieve an email confirmation code when registering a
+ * new user account in acceptance tests.
+ */
+const addSessionEndpoint = app => {
+  const stack = app._router.stack
+
+  stack.forEach(layer => {
+    if (layer.name !== 'router' || !layer.handle || !layer.handle.stack) {
+      return
+    }
+
+    // We want to position our /dev/session endpoint next to the /dev/csrf
+    // endpoint so we check each router for the presence of this path.
+    const newRouteIndex = layer.handle.stack.findIndex(
+      route =>
+        route &&
+        route.route &&
+        route.route.path &&
+        route.route.path === '/dev/csrf'
+    )
+
+    if (newRouteIndex !== -1) {
+      // We add our new endpoint to the end of the router stack.
+      layer.handle.get('/dev/session', (req, res) => {
+        return res.json(req.session)
+      })
+
+      const routeStack = layer.handle.stack
+      const sessionRoute = routeStack[routeStack.length - 1]
+
+      // Then we reposition it next to the /dev/csrf endpoint.
+      layer.handle.stack = [
+        ...routeStack.slice(0, newRouteIndex),
+        sessionRoute,
+        ...routeStack.slice(newRouteIndex, routeStack.length - 1),
+      ]
+    }
+  })
+}
 
 logger.logger.level('error')
 
@@ -18,6 +62,7 @@ MockReCAPTCHAApi.initialize(2222)
 let server
 
 before('start main app', function (done) {
+  addSessionEndpoint(app)
   server = App.listen(23000, 'localhost', done)
 })
 

+ 71 - 3
services/web/test/acceptance/src/helpers/User.js

@@ -32,6 +32,46 @@ class User {
     })
   }
 
+  getSession(callback) {
+    this.request.get(
+      {
+        url: '/dev/session',
+      },
+      (err, response, body) => {
+        if (err != null) {
+          return callback(err)
+        }
+        if (response.statusCode !== 200) {
+          return callback(
+            new Error(
+              `get session failed: status=${
+                response.statusCode
+              } body=${JSON.stringify(body)}`
+            )
+          )
+        }
+
+        const session = JSON.parse(response.body)
+        callback(null, session)
+      }
+    )
+  }
+
+  getEmailConfirmationCode(callback) {
+    this.getSession((err, session) => {
+      if (err != null) {
+        return callback(err)
+      }
+
+      const code = session.pendingUserRegistration?.confirmCode
+      if (!code) {
+        return callback(new Error('No confirmation code found in session'))
+      }
+
+      callback(null, code)
+    })
+  }
+
   resetCookies() {
     this.jar = request.jar()
     this.request = request.defaults({
@@ -114,12 +154,40 @@ class User {
               )
             )
           }
-          db.users.findOne({ email: this.email }, (error, user) => {
+
+          this.getEmailConfirmationCode((error, code) => {
             if (error != null) {
               return callback(error)
             }
-            this.setExtraAttributes(user)
-            callback(null, user)
+
+            this.request.post(
+              {
+                url: '/registration/confirm-email',
+                json: { code },
+              },
+              (error, response, body) => {
+                if (error != null) {
+                  return callback(error)
+                }
+                if (response.statusCode !== 200) {
+                  return callback(
+                    new Error(
+                      `email confirmation failed: status=${
+                        response.statusCode
+                      } body=${JSON.stringify(body)}`
+                    )
+                  )
+                }
+
+                db.users.findOne({ email: this.email }, (error, user) => {
+                  if (error != null) {
+                    return callback(error)
+                  }
+                  this.setExtraAttributes(user)
+                  callback(null, user)
+                })
+              }
+            )
           })
         }
       )

+ 51 - 0
services/web/test/acceptance/src/helpers/UserHelper.js

@@ -140,6 +140,33 @@ class UserHelper {
     this._csrfToken = body
   }
 
+  /**
+   * Requests user session
+   */
+  async getSession() {
+    const response = await this.fetch('/dev/session')
+    const body = await response.text()
+
+    if (response.status !== 200) {
+      throw new Error(
+        `get session failed: status=${response.status} body=${JSON.stringify(
+          body
+        )}`
+      )
+    }
+    return JSON.parse(body)
+  }
+
+  async getEmailConfirmationCode() {
+    const session = await this.getSession()
+
+    const code = session.pendingUserRegistration?.confirmCode
+    if (!code) {
+      throw new Error('No confirmation code found in session')
+    }
+    return code
+  }
+
   /**
    * Make request to POST /logout
    * @param {object} [options] options to pass to request
@@ -353,6 +380,30 @@ class UserHelper {
         `cannot register intitutional email: ${options.json.email}`
       )
     }
+
+    const code = await userHelper.getEmailConfirmationCode()
+
+    const confirmationResponse = await userHelper.fetch(
+      '/registration/confirm-email',
+      {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+          Accept: 'application/json',
+        },
+        body: JSON.stringify({ code }),
+        ...options,
+      }
+    )
+
+    if (confirmationResponse.status !== 200) {
+      throw new Error(
+        `email confirmation failed: status=${
+          response.status
+        } body=${JSON.stringify(body)}`
+      )
+    }
+
     userHelper.user = await UserGetter.promises.getUser({
       email: userData.email,
     })