mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-14 20:40:17 -05:00
Merge pull request #19719 from overleaf/jpa-e2e-register
[server-pro] add e2e tests for registering users via GUI/script/email GitOrigin-RevId: 25243532038c8df72f1360c433af215b3a551f3a
This commit is contained in:
parent
fa8161d4ce
commit
05ecfa2e23
6 changed files with 129 additions and 18 deletions
|
@ -1,10 +1,105 @@
|
|||
import { isExcludedBySharding, startWith } from './helpers/config'
|
||||
import { activateUser, ensureUserExists, login } from './helpers/login'
|
||||
import {
|
||||
activateUser,
|
||||
createMongoUser,
|
||||
ensureUserExists,
|
||||
login,
|
||||
} from './helpers/login'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
import { createProject } from './helpers/project'
|
||||
import { beforeWithReRunOnTestRetry } from './helpers/beforeWithReRunOnTestRetry'
|
||||
import { openEmail } from './helpers/email'
|
||||
|
||||
describe('admin panel', function () {
|
||||
function registrationTests() {
|
||||
it('via GUI and opening URL manually', () => {
|
||||
const user = `${uuid()}@example.com`
|
||||
cy.get('input[name="email"]').type(user + '{enter}')
|
||||
|
||||
cy.get('td')
|
||||
.contains(/\/user\/activate/)
|
||||
.then($td => {
|
||||
const url = $td.text().trim()
|
||||
activateUser(url)
|
||||
})
|
||||
})
|
||||
|
||||
it('via GUI and email', () => {
|
||||
const user = `${uuid()}@example.com`
|
||||
cy.get('input[name="email"]').type(user + '{enter}')
|
||||
|
||||
let url: string
|
||||
cy.get('td')
|
||||
.contains(/\/user\/activate/)
|
||||
.then($td => {
|
||||
url = $td.text().trim()
|
||||
})
|
||||
|
||||
cy.then(() => {
|
||||
openEmail(
|
||||
'Activate your Overleaf Community Edition Account',
|
||||
(frame, { url }) => {
|
||||
frame.contains('Set password').then(el => {
|
||||
expect(el.attr('href')!).to.equal(url)
|
||||
})
|
||||
},
|
||||
{ url }
|
||||
)
|
||||
// Run activateUser in the main origin instead of inside openEmail. See docs on openEmail.
|
||||
activateUser(url)
|
||||
})
|
||||
})
|
||||
it('via script and opening URL manually', () => {
|
||||
const user = `${uuid()}@example.com`
|
||||
let url: string
|
||||
cy.then(async () => {
|
||||
;({ url } = await createMongoUser({ email: user }))
|
||||
})
|
||||
cy.then(() => {
|
||||
activateUser(url)
|
||||
})
|
||||
})
|
||||
it('via script and email', () => {
|
||||
const user = `${uuid()}@example.com`
|
||||
let url: string
|
||||
cy.then(async () => {
|
||||
;({ url } = await createMongoUser({ email: user }))
|
||||
})
|
||||
cy.then(() => {
|
||||
openEmail(
|
||||
'Activate your Overleaf Community Edition Account',
|
||||
(frame, { url }) => {
|
||||
frame.contains('Set password').then(el => {
|
||||
expect(el.attr('href')!).to.equal(url)
|
||||
})
|
||||
},
|
||||
{ url }
|
||||
)
|
||||
// Run activateUser in the main origin instead of inside openEmail. See docs on openEmail.
|
||||
activateUser(url)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe('in CE', () => {
|
||||
if (isExcludedBySharding('CE_DEFAULT')) return
|
||||
startWith({ pro: false, version: 'latest' })
|
||||
const admin = 'admin@example.com'
|
||||
const user = `user+${uuid()}@example.com`
|
||||
ensureUserExists({ email: admin, isAdmin: true })
|
||||
ensureUserExists({ email: user })
|
||||
|
||||
describe('create users', () => {
|
||||
beforeEach(() => {
|
||||
login(admin)
|
||||
cy.visit('/project')
|
||||
cy.get('nav').findByText('Admin').click()
|
||||
cy.get('nav').findByText('Manage Users').click()
|
||||
})
|
||||
registrationTests()
|
||||
})
|
||||
})
|
||||
|
||||
describe('in server pro', () => {
|
||||
const admin = 'admin@example.com'
|
||||
const user1 = 'user@example.com'
|
||||
|
@ -83,18 +178,11 @@ describe('admin panel', function () {
|
|||
cy.get('nav').findByText('Manage Users').click()
|
||||
})
|
||||
|
||||
it('create and login user', () => {
|
||||
const user = `${uuid()}@example.com`
|
||||
|
||||
describe('create users', () => {
|
||||
beforeEach(() => {
|
||||
cy.get('a').contains('New User').click()
|
||||
cy.get('input[name="email"]').type(user + '{enter}')
|
||||
|
||||
cy.get('td')
|
||||
.contains(/\/user\/activate/)
|
||||
.then($td => {
|
||||
const url = $td.text().trim()
|
||||
activateUser(url)
|
||||
})
|
||||
registrationTests()
|
||||
})
|
||||
|
||||
it('user list RegExp search', () => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { reconfigure } from './hostAdminClient'
|
||||
import { resetCreatedUsersCache } from './login'
|
||||
import { resetActivateUserRateLimit, resetCreatedUsersCache } from './login'
|
||||
|
||||
export const STARTUP_TIMEOUT =
|
||||
parseInt(Cypress.env('STARTUP_TIMEOUT'), 10) || 120_000
|
||||
|
@ -39,6 +39,7 @@ export function startWith({
|
|||
})
|
||||
if (resetData) {
|
||||
resetCreatedUsersCache()
|
||||
resetActivateUserRateLimit()
|
||||
// no return here, always reconfigure when resetting data
|
||||
} else if (lastConfig === cfg) {
|
||||
return
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
* Helper function for opening an email in Roundcube based mailtrap.
|
||||
* We need to cross an origin boundary, which complicates the use of variables.
|
||||
* Any variables need to be explicitly defined and the "runner" may only reference these and none from its scope.
|
||||
* It is not possible to use Cypress helper functions, e.g. from the testing library inside the "runner".
|
||||
* It is not possible to use Cypress helper functions, e.g. from the testing library or other functions like "activateUser", inside the "runner".
|
||||
* REF: https://github.com/testing-library/cypress-testing-library/issues/221
|
||||
*/
|
||||
export function openEmail<T>(
|
||||
subject: string | RegExp,
|
||||
runner: (frame: Cypress.Chainable<JQuery<any>>, args?: T) => void,
|
||||
runner: (frame: Cypress.Chainable<JQuery<any>>, args: T) => void,
|
||||
args?: T
|
||||
) {
|
||||
const runnerS = runner.toString()
|
||||
|
|
|
@ -21,7 +21,7 @@ export async function createMongoUser({
|
|||
script: 'modules/server-ce-scripts/scripts/create-user.js',
|
||||
args: [`--email=${email}`, `--admin=${isAdmin}`],
|
||||
})
|
||||
const [url] = stdout.match(/\/user\/activate\?token=\S+/)!
|
||||
const [url] = stdout.match(/http:\/\/.+\/user\/activate\?token=\S+/)!
|
||||
const userId = new URL(url, location.origin).searchParams.get('user_id')!
|
||||
const signupDate = parseInt(userId.slice(0, 8), 16)
|
||||
if (signupDate < t0) {
|
||||
|
@ -70,7 +70,27 @@ export function login(username: string, password = DEFAULT_PASSWORD) {
|
|||
return startOrResumeSession
|
||||
}
|
||||
|
||||
let activateRateLimitState = { count: 0, reset: 0 }
|
||||
export function resetActivateUserRateLimit() {
|
||||
activateRateLimitState = { count: 0, reset: 0 }
|
||||
}
|
||||
|
||||
function handleActivateUserRateLimit() {
|
||||
cy.then(() => {
|
||||
activateRateLimitState.count++
|
||||
if (activateRateLimitState.reset < Date.now()) {
|
||||
activateRateLimitState.reset = Date.now() + 65_000
|
||||
activateRateLimitState.count = 1
|
||||
} else if (activateRateLimitState.count >= 6) {
|
||||
cy.wait(activateRateLimitState.reset - Date.now())
|
||||
activateRateLimitState.count = 1
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function activateUser(url: string, password = DEFAULT_PASSWORD) {
|
||||
handleActivateUserRateLimit()
|
||||
|
||||
cy.session(url, () => {
|
||||
cy.visit(url)
|
||||
cy.url().then(url => {
|
||||
|
|
|
@ -159,6 +159,7 @@ const allowedVars = Joi.object(
|
|||
'OVERLEAF_LDAP_LAST_NAME_ATT',
|
||||
'OVERLEAF_LDAP_UPDATE_USER_DETAILS_ON_LOGIN',
|
||||
// Old branding, used for upgrade tests
|
||||
'SHARELATEX_SITE_URL',
|
||||
'SHARELATEX_MONGO_URL',
|
||||
'SHARELATEX_REDIS_HOST',
|
||||
].map(name => [name, Joi.string()])
|
||||
|
|
|
@ -145,7 +145,8 @@ describe('Upgrading', function () {
|
|||
const optionsFourDotTwo = {
|
||||
version: '4.2',
|
||||
vars: {
|
||||
// Add database vars with old branding
|
||||
// Add core vars with old branding
|
||||
SHARELATEX_SITE_URL: 'http://sharelatex',
|
||||
SHARELATEX_MONGO_URL: 'mongodb://mongo/sharelatex',
|
||||
SHARELATEX_REDIS_HOST: 'redis',
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue