Ver Fonte

Merge pull request #19778 from overleaf/jpa-e2e-reuse-sessions

[server-pro] tests: implement session re-usage

GitOrigin-RevId: 81f2feb39e413c858eb287784e378cf43423d0a4
Jakob Ackermann há 2 anos atrás
pai
commit
37f486ca9a

+ 3 - 0
server-ce/test/accounts.spec.ts

@@ -11,6 +11,9 @@ describe('Accounts', function () {
     cy.visit('/project')
     cy.findByText('Account').click()
     cy.findByText('Log Out').click()
+    cy.url().should('include', '/login')
+    cy.visit('/project')
+    cy.url().should('include', '/login')
   })
 
   it('should render the email on the user activate screen', () => {

+ 6 - 7
server-ce/test/admin.spec.ts

@@ -134,9 +134,8 @@ describe('admin panel', function () {
     })
 
     describe('manage site', () => {
-      let resumeAdminSession: () => void
       beforeEach(() => {
-        resumeAdminSession = login(admin)
+        login(admin)
         cy.visit('/project')
         cy.get('nav').findByText('Admin').click()
         cy.get('nav').findByText('Manage Site').click()
@@ -151,12 +150,12 @@ describe('admin panel', function () {
         cy.get('button').contains('Post Message').click()
         cy.findByText(message)
 
-        const resumeUser1Session = login(user1)
+        login(user1)
         cy.visit('/project')
         cy.findByText(message)
 
         cy.log('clear system messages')
-        resumeAdminSession()
+        login(admin)
         cy.visit('/project')
         cy.get('nav').findByText('Admin').click()
         cy.get('nav').findByText('Manage Site').click()
@@ -164,7 +163,7 @@ describe('admin panel', function () {
         cy.get('button').contains('Clear all messages').click()
 
         cy.log('verify system messages are no longer displayed')
-        resumeUser1Session()
+        login(user1)
         cy.visit('/project')
         cy.findByText(message).should('not.exist')
       })
@@ -260,7 +259,7 @@ describe('admin panel', function () {
     })
 
     it('restore deleted projects', () => {
-      const resumeUserSession = login(user1)
+      login(user1)
       cy.visit('/project')
 
       cy.log('select project to delete')
@@ -299,7 +298,7 @@ describe('admin panel', function () {
       cy.url().should('contain', `/admin/project/${projectToDeleteId}`)
 
       cy.log('login as the user and verify the project is restored')
-      resumeUserSession()
+      login(user1)
       cy.visit('/project')
       cy.get('.project-list-sidebar-react').within(() => {
         cy.findByText('Trashed Projects').click()

+ 7 - 9
server-ce/test/editor.spec.ts

@@ -66,11 +66,9 @@ describe('editor', () => {
 
   describe('collaboration', () => {
     let projectId: string
-    let resumeUserSession: () => void
-    let resumeCollaboratorSession: () => void
 
     beforeEach(() => {
-      resumeUserSession = login('user@example.com')
+      login('user@example.com')
       cy.visit(`/project`)
       createProject('test-editor', { type: 'Example Project' }).then(
         (id: string) => {
@@ -86,7 +84,7 @@ describe('editor', () => {
             .should('contain.text', 'http://') // wait for the link to appear
             .then(el => {
               const linkSharingReadAndWrite = el.text()
-              resumeCollaboratorSession = login('collaborator@example.com')
+              login('collaborator@example.com')
               cy.visit(linkSharingReadAndWrite)
               cy.get('button').contains('Join Project').click()
               cy.log(
@@ -95,7 +93,7 @@ describe('editor', () => {
               cy.visit('/project')
             })
 
-          resumeUserSession()
+          login('user@example.com')
           cy.visit(`/project/${projectId}`)
         }
       )
@@ -112,7 +110,7 @@ describe('editor', () => {
         .within(() => cy.get('.input-switch').click())
       cy.wait('@enableTrackChanges')
 
-      resumeCollaboratorSession()
+      login('collaborator@example.com')
       cy.visit(`/project/${projectId}`)
 
       cy.log('make changes in main file')
@@ -127,7 +125,7 @@ describe('editor', () => {
       cy.log('recompile to force flush')
       cy.findByText('Recompile').click()
 
-      resumeUserSession()
+      login('user@example.com')
       cy.visit(`/project/${projectId}`)
 
       cy.log('reject changes')
@@ -151,7 +149,7 @@ describe('editor', () => {
         .within(() => cy.get('.input-switch').click())
       cy.wait('@enableTrackChanges')
 
-      resumeCollaboratorSession()
+      login('collaborator@example.com')
       cy.visit(`/project/${projectId}`)
 
       cy.log('enable visual editor and make changes in main file')
@@ -168,7 +166,7 @@ describe('editor', () => {
       cy.log('recompile to force flush')
       cy.findByText('Recompile').click()
 
-      resumeUserSession()
+      login('user@example.com')
       cy.visit(`/project/${projectId}`)
 
       cy.log('reject changes')

+ 14 - 4
server-ce/test/helpers/config.ts

@@ -19,7 +19,7 @@ export function isExcludedBySharding(
   return SHARD && shard !== SHARD
 }
 
-let lastConfig: string
+let previousConfigFrontend: string
 
 export function startWith({
   pro = false,
@@ -36,18 +36,28 @@ export function startWith({
       version,
       vars,
       withDataDir,
+      resetData,
     })
     if (resetData) {
       resetCreatedUsersCache()
       resetActivateUserRateLimit()
       // no return here, always reconfigure when resetting data
-    } else if (lastConfig === cfg) {
+    } else if (previousConfigFrontend === cfg) {
       return
     }
 
     this.timeout(STARTUP_TIMEOUT)
-    await reconfigure({ pro, version, vars, withDataDir, resetData })
-    lastConfig = cfg
+    const { previousConfigServer } = await reconfigure({
+      pro,
+      version,
+      vars,
+      withDataDir,
+      resetData,
+    })
+    if (previousConfigServer !== cfg) {
+      await Cypress.session.clearAllSavedSessions()
+    }
+    previousConfigFrontend = cfg
   })
 }
 

+ 5 - 5
server-ce/test/helpers/hostAdminClient.ts

@@ -15,7 +15,7 @@ export async function reconfigure({
   vars = {},
   withDataDir = false,
   resetData = false,
-}) {
+}): Promise<{ previousConfigServer: string }> {
   return await fetchJSON(`${hostAdminUrl}/reconfigure`, {
     method: 'POST',
     body: JSON.stringify({
@@ -28,15 +28,15 @@ export async function reconfigure({
   })
 }
 
-async function fetchJSON(
+async function fetchJSON<T = { stdout: string; stderr: string }>(
   input: RequestInfo,
   init?: RequestInit
-): Promise<{ stdout: string; stderr: string }> {
+): Promise<T> {
   if (init?.body) {
     init.headers = { 'Content-Type': 'application/json' }
   }
   const res = await fetch(input, init)
-  const { error, stdout, stderr } = await res.json()
+  const { error, stdout, stderr, ...rest } = await res.json()
   if (error) {
     console.error(input, init, 'failed:', error)
     if (stdout) console.log(stdout)
@@ -45,7 +45,7 @@ async function fetchJSON(
     Object.assign(err, error)
     throw err
   }
-  return { stdout, stderr }
+  return { stdout, stderr, ...rest }
 }
 
 export async function runScript({

+ 15 - 7
server-ce/test/helpers/login.ts

@@ -56,18 +56,26 @@ export function ensureUserExists({
 }
 
 export function login(username: string, password = DEFAULT_PASSWORD) {
-  const id = [username, password, new Date()]
-  function startOrResumeSession() {
-    cy.session(id, () => {
+  cy.session(
+    [username, password],
+    () => {
       cy.visit('/login')
       cy.get('input[name="email"]').type(username)
       cy.get('input[name="password"]').type(password)
       cy.findByRole('button', { name: 'Login' }).click()
       cy.url().should('contain', '/project')
-    })
-  }
-  startOrResumeSession()
-  return startOrResumeSession
+    },
+    {
+      cacheAcrossSpecs: true,
+      async validate() {
+        cy.request({ url: '/project', followRedirect: false }).then(
+          response => {
+            expect(response.status).to.equal(200)
+          }
+        )
+      },
+    }
+  )
 }
 
 let activateRateLimitState = { count: 0, reset: 0 }

+ 5 - 1
server-ce/test/host-admin.js

@@ -29,6 +29,7 @@ const IMAGES = {
   PRO: process.env.IMAGE_TAG_PRO.replace(/:.+/, ''),
 }
 
+let previousConfig = ''
 let mongoIsInitialized = false
 
 function readDockerComposeOverride() {
@@ -295,6 +296,7 @@ function maybeResetData(resetData, callback) {
         return callback(error)
       }
 
+      previousConfig = ''
       mongoIsInitialized = false
       runDockerCompose(
         'down',
@@ -336,7 +338,9 @@ app.post(
           'up',
           ['--detach', '--wait', 'sharelatex'],
           (error, stdout, stderr) => {
-            res.json({ error, stdout, stderr })
+            const previousConfigServer = previousConfig
+            previousConfig = JSON.stringify(req.body)
+            res.json({ error, stdout, stderr, previousConfigServer })
           }
         )
       })

+ 3 - 2
server-ce/test/templates.spec.ts

@@ -48,7 +48,7 @@ describe('Templates', () => {
     })
 
     it('should have templates feature', () => {
-      const resumeTemplatesUserSession = login(TEMPLATES_USER)
+      login(TEMPLATES_USER)
       const name = `Template ${Date.now()}`
       const description = `Template Description ${Date.now()}`
 
@@ -182,7 +182,8 @@ describe('Templates', () => {
       cy.findByText('Manage Template').click()
       cy.findByText('Unpublish')
 
-      resumeTemplatesUserSession()
+      // Back to templates user
+      login(TEMPLATES_USER)
 
       // Unpublish via editor
       cy.get('@templateProjectId').then(projectId =>