mirror of
https://github.com/overleaf/overleaf.git
synced 2024-09-16 02:52:31 -04:00
new UserHelper class for acceptance tests
GitOrigin-RevId: 194593b8b70c74d2771f8e6f695faa47c84beeca
This commit is contained in:
parent
61d895c8fc
commit
3a7384c83f
3 changed files with 308 additions and 2 deletions
|
@ -1,4 +1,3 @@
|
|||
let AuthenticationManager
|
||||
const Settings = require('settings-sharelatex')
|
||||
const { User } = require('../../models/User')
|
||||
const { db, ObjectId } = require('../../infrastructure/mongojs')
|
||||
|
@ -9,6 +8,7 @@ const {
|
|||
InvalidEmailError,
|
||||
InvalidPasswordError
|
||||
} = require('./AuthenticationErrors')
|
||||
const util = require('util')
|
||||
|
||||
const BCRYPT_ROUNDS = Settings.security.bcryptRounds || 12
|
||||
const BCRYPT_MINOR_VERSION = Settings.security.bcryptMinorVersion || 'a'
|
||||
|
@ -22,7 +22,7 @@ const _checkWriteResult = function(result, callback) {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = AuthenticationManager = {
|
||||
const AuthenticationManager = {
|
||||
authenticate(query, password, callback) {
|
||||
// Using Mongoose for legacy reasons here. The returned User instance
|
||||
// gets serialized into the session and there may be subtle differences
|
||||
|
@ -217,3 +217,10 @@ module.exports = AuthenticationManager = {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
AuthenticationManager.promises = {
|
||||
authenticate: util.promisify(AuthenticationManager.authenticate),
|
||||
hashPassword: util.promisify(AuthenticationManager.hashPassword)
|
||||
}
|
||||
|
||||
module.exports = AuthenticationManager
|
||||
|
|
153
services/web/test/acceptance/src/UserHelperTests.js
Normal file
153
services/web/test/acceptance/src/UserHelperTests.js
Normal file
|
@ -0,0 +1,153 @@
|
|||
const AuthenticationManager = require('../../../app/src/Features/Authentication/AuthenticationManager')
|
||||
const UserHelper = require('./helpers/UserHelper')
|
||||
const chai = require('chai')
|
||||
const chaiAsPromised = require('chai-as-promised')
|
||||
|
||||
const expect = chai.expect
|
||||
chai.should()
|
||||
chai.use(chaiAsPromised)
|
||||
|
||||
describe('UserHelper', function() {
|
||||
describe('UserHelper.createUser', function() {
|
||||
describe('with no args', function() {
|
||||
it('should create new user with default username and password', async function() {
|
||||
const userHelper = await UserHelper.createUser()
|
||||
userHelper.user.email.should.equal(userHelper.getDefaultEmail())
|
||||
const authedUser = await AuthenticationManager.promises.authenticate(
|
||||
{ _id: userHelper.user._id },
|
||||
userHelper.getDefaultPassword()
|
||||
)
|
||||
expect(authedUser).to.not.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('with email', function() {
|
||||
it('should create new user with provided email and default password', async function() {
|
||||
const userHelper = await UserHelper.createUser({
|
||||
email: 'foo@test.com'
|
||||
})
|
||||
userHelper.user.email.should.equal('foo@test.com')
|
||||
const authedUser = await AuthenticationManager.promises.authenticate(
|
||||
{ _id: userHelper.user._id },
|
||||
userHelper.getDefaultPassword()
|
||||
)
|
||||
expect(authedUser).to.not.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('with password', function() {
|
||||
it('should create new user with provided password and default email', async function() {
|
||||
const userHelper = await UserHelper.createUser({
|
||||
password: 'foofoofoo'
|
||||
})
|
||||
userHelper.user.email.should.equal(userHelper.getDefaultEmail())
|
||||
const authedUser = await AuthenticationManager.promises.authenticate(
|
||||
{ _id: userHelper.user._id },
|
||||
'foofoofoo'
|
||||
)
|
||||
expect(authedUser).to.not.be.null
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('fetching existing user', function() {
|
||||
let user
|
||||
|
||||
beforeEach(async function() {
|
||||
user = (await UserHelper.createUser()).user
|
||||
})
|
||||
|
||||
describe('with string id', function() {
|
||||
it('should fetch user', async function() {
|
||||
const userHelper = await UserHelper.getUser(user._id.toString())
|
||||
userHelper.user.email.should.equal(user.email)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with _id', function() {
|
||||
it('should fetch user', async function() {
|
||||
const userHelper = await UserHelper.getUser({ _id: user._id })
|
||||
userHelper.user.email.should.equal(user.email)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getCsrfToken', function() {
|
||||
describe('when the csrfToken is not cached', function() {
|
||||
it('should fetch csrfToken', async function() {
|
||||
const userHelper = new UserHelper()
|
||||
await userHelper.getCsrfToken()
|
||||
expect(userHelper.csrfToken).to.be.a.string
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the csrfToken is cached', function() {
|
||||
it('should fetch csrfToken', async function() {
|
||||
let userHelper = new UserHelper()
|
||||
await userHelper.getCsrfToken()
|
||||
const csrfToken = userHelper._csrfToken
|
||||
await userHelper.getCsrfToken()
|
||||
expect(csrfToken).to.equal(userHelper._csrfToken)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('registerUser', function() {
|
||||
describe('with no args', function() {
|
||||
it('should create new user with default username and password', async function() {
|
||||
const userHelper = await UserHelper.registerUser()
|
||||
userHelper.user.email.should.equal(userHelper.getDefaultEmail())
|
||||
const authedUser = await AuthenticationManager.promises.authenticate(
|
||||
{ _id: userHelper.user._id },
|
||||
userHelper.getDefaultPassword()
|
||||
)
|
||||
expect(authedUser).to.not.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('with email', function() {
|
||||
it('should create new user with provided email and default password', async function() {
|
||||
const userHelper = await UserHelper.registerUser({
|
||||
email: 'foo2@test.com'
|
||||
})
|
||||
userHelper.user.email.should.equal('foo2@test.com')
|
||||
const authedUser = await AuthenticationManager.promises.authenticate(
|
||||
{ _id: userHelper.user._id },
|
||||
userHelper.getDefaultPassword()
|
||||
)
|
||||
expect(authedUser).to.not.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('with password', function() {
|
||||
it('should create new user with provided password and default email', async function() {
|
||||
const userHelper = await UserHelper.registerUser({
|
||||
password: 'foofoofoo'
|
||||
})
|
||||
userHelper.user.email.should.equal(userHelper.getDefaultEmail())
|
||||
const authedUser = await AuthenticationManager.promises.authenticate(
|
||||
{ _id: userHelper.user._id },
|
||||
'foofoofoo'
|
||||
)
|
||||
expect(authedUser).to.not.be.null
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('after logout', function() {
|
||||
let userHelper, oldCsrfToken
|
||||
|
||||
beforeEach(async function() {
|
||||
userHelper = await UserHelper.registerUser()
|
||||
oldCsrfToken = userHelper.csrfToken
|
||||
})
|
||||
|
||||
it('refreshes csrf token after logout', async function() {
|
||||
await userHelper.logout()
|
||||
expect(userHelper._csrfToken).to.equal('')
|
||||
await userHelper.getCsrfToken()
|
||||
expect(userHelper._csrfToken).to.not.equal('')
|
||||
expect(userHelper._csrfToken).to.not.equal(oldCsrfToken)
|
||||
})
|
||||
})
|
||||
})
|
146
services/web/test/acceptance/src/helpers/UserHelper.js
Normal file
146
services/web/test/acceptance/src/helpers/UserHelper.js
Normal file
|
@ -0,0 +1,146 @@
|
|||
const AuthenticationManager = require('../../../../app/src/Features/Authentication/AuthenticationManager')
|
||||
const UserCreator = require('../../../../app/src/Features/User/UserCreator')
|
||||
const UserGetter = require('../../../../app/src/Features/User/UserGetter')
|
||||
const request = require('request-promise-native')
|
||||
|
||||
let globalUserNum = 1
|
||||
|
||||
module.exports = class UserHelper {
|
||||
constructor(user = null) {
|
||||
// used for constructing default emails, etc
|
||||
this.userNum = globalUserNum++
|
||||
// initialize all internal state properties to defaults
|
||||
this.reset()
|
||||
// set user if passed in, may be null
|
||||
this.user = user
|
||||
}
|
||||
|
||||
/* sync functions */
|
||||
|
||||
getDefaultEmail() {
|
||||
return `test.user.${this.userNum}@example.com`
|
||||
}
|
||||
|
||||
getDefaultEmailPassword(userData = {}) {
|
||||
return {
|
||||
email: this.getDefaultEmail(),
|
||||
password: this.getDefaultPassword(this.userNum),
|
||||
...userData
|
||||
}
|
||||
}
|
||||
|
||||
getDefaultPassword() {
|
||||
return `new-password-${this.userNum}!`
|
||||
}
|
||||
|
||||
reset() {
|
||||
// cached csrf token
|
||||
this._csrfToken = ''
|
||||
// used to store mongo user object once created/loaded
|
||||
this.user = null
|
||||
// cookie jar
|
||||
this.jar = request.jar()
|
||||
// initialize request instance with default options
|
||||
this.setRequestDefaults()
|
||||
}
|
||||
|
||||
setRequestDefaults(defaults = {}) {
|
||||
// request-promise instance for making requests
|
||||
this.request = request.defaults({
|
||||
baseUrl: UserHelper.baseUrl(),
|
||||
followRedirect: false,
|
||||
jar: this.jar,
|
||||
resolveWithFullResponse: true,
|
||||
...defaults
|
||||
})
|
||||
}
|
||||
|
||||
/* async http api call methods */
|
||||
|
||||
async getCsrfToken() {
|
||||
if (this._csrfToken) {
|
||||
return
|
||||
}
|
||||
// get csrf token from api and store
|
||||
const response = await this.request.get('/dev/csrf')
|
||||
this._csrfToken = response.body
|
||||
// use csrf token for requests
|
||||
this.setRequestDefaults({
|
||||
headers: { 'x-csrf-token': this._csrfToken }
|
||||
})
|
||||
}
|
||||
|
||||
async logout(options = {}) {
|
||||
// do not throw exception on 302
|
||||
options.simple = false
|
||||
// post logout
|
||||
const response = await this.request.post('/logout', options)
|
||||
if (
|
||||
response.statusCode !== 302 ||
|
||||
!response.headers.location.includes('/login')
|
||||
) {
|
||||
throw new Error('logout failed')
|
||||
}
|
||||
// clear out internal state
|
||||
this.reset()
|
||||
// resolve with http request response
|
||||
return response
|
||||
}
|
||||
|
||||
/* static sync methods */
|
||||
|
||||
static baseUrl() {
|
||||
return `http://${process.env['HTTP_TEST_HOST'] || 'localhost'}:3000`
|
||||
}
|
||||
|
||||
/* static async instantiation methods */
|
||||
|
||||
static async createUser(attributes = {}, options = {}) {
|
||||
const userHelper = new UserHelper()
|
||||
attributes = userHelper.getDefaultEmailPassword(attributes)
|
||||
// skip creating affiliations by default because it requires an
|
||||
// API call that will usually not be mocked in testing env
|
||||
if (attributes.skip_affiliation !== false) {
|
||||
attributes.skip_affiliation = true
|
||||
}
|
||||
// hash password and delete plaintext if set
|
||||
if (attributes.password) {
|
||||
attributes.hashedPassword = await AuthenticationManager.promises.hashPassword(
|
||||
attributes.password
|
||||
)
|
||||
delete attributes.password
|
||||
}
|
||||
|
||||
userHelper.user = await UserCreator.promises.createNewUser(
|
||||
attributes,
|
||||
options
|
||||
)
|
||||
|
||||
return userHelper
|
||||
}
|
||||
|
||||
static async getUser(...args) {
|
||||
const user = await UserGetter.promises.getUser(...args)
|
||||
|
||||
return new UserHelper(user)
|
||||
}
|
||||
|
||||
static async registerUser(userData, options = {}) {
|
||||
const userHelper = new UserHelper()
|
||||
await userHelper.getCsrfToken()
|
||||
userData = userHelper.getDefaultEmailPassword(userData)
|
||||
options.json = userData
|
||||
const { body } = await userHelper.request.post('/register', options)
|
||||
if (body.message && body.message.type === 'error') {
|
||||
throw new Error(`register api error: ${body.message.text}`)
|
||||
}
|
||||
userHelper.user = await UserGetter.promises.getUser({
|
||||
email: userData.email
|
||||
})
|
||||
if (!userHelper.user) {
|
||||
throw new Error(`user not found for email: ${userData.email}`)
|
||||
}
|
||||
|
||||
return userHelper
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue