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

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

GitOrigin-RevId: 81f2feb39e413c858eb287784e378cf43423d0a4
This commit is contained in:
Jakob Ackermann 2024-08-06 11:10:03 +02:00 committed by Copybot
parent 399e834e36
commit 37f486ca9a
8 changed files with 58 additions and 35 deletions

View file

@ -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', () => {

View file

@ -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()

View file

@ -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')

View file

@ -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
})
}

View file

@ -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({

View file

@ -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')
})
},
{
cacheAcrossSpecs: true,
async validate() {
cy.request({ url: '/project', followRedirect: false }).then(
response => {
expect(response.status).to.equal(200)
}
startOrResumeSession()
return startOrResumeSession
)
},
}
)
}
let activateRateLimitState = { count: 0, reset: 0 }

View file

@ -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 })
}
)
})

View file

@ -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 =>