mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #2449 from overleaf/ew-user-helper-docs-and-tweaks
add docs on UserHelper and tweak a few things GitOrigin-RevId: 410be6b3cdf32cc72e14e26569f56369ce30c0a2
This commit is contained in:
parent
f2ad7ebfc3
commit
1e8fc5337c
2 changed files with 147 additions and 52 deletions
|
@ -9,6 +9,13 @@ chai.should()
|
||||||
chai.use(chaiAsPromised)
|
chai.use(chaiAsPromised)
|
||||||
|
|
||||||
describe('UserHelper', function() {
|
describe('UserHelper', function() {
|
||||||
|
// Disable all tests unless the public-registration feature is enabled
|
||||||
|
beforeEach(function() {
|
||||||
|
if (!Features.hasFeature('public-registration')) {
|
||||||
|
this.skip()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
describe('UserHelper.createUser', function() {
|
describe('UserHelper.createUser', function() {
|
||||||
describe('with no args', function() {
|
describe('with no args', function() {
|
||||||
it('should create new user with default username and password', async function() {
|
it('should create new user with default username and password', async function() {
|
||||||
|
@ -51,7 +58,7 @@ describe('UserHelper', function() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('fetching existing user', function() {
|
describe('UserHelper.getUser', function() {
|
||||||
let user
|
let user
|
||||||
|
|
||||||
beforeEach(async function() {
|
beforeEach(async function() {
|
||||||
|
@ -73,34 +80,50 @@ describe('UserHelper', function() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('getCsrfToken', function() {
|
describe('UserHelper.loginUser', function() {
|
||||||
describe('when the csrfToken is not cached', function() {
|
let userHelper
|
||||||
it('should fetch csrfToken', async function() {
|
|
||||||
const userHelper = new UserHelper()
|
beforeEach(async function() {
|
||||||
await userHelper.getCsrfToken()
|
userHelper = await UserHelper.createUser()
|
||||||
expect(userHelper.csrfToken).to.be.a.string
|
})
|
||||||
|
|
||||||
|
describe('with email and password', function() {
|
||||||
|
it('should login user', async function() {
|
||||||
|
const newUserHelper = await UserHelper.loginUser({
|
||||||
|
email: userHelper.getDefaultEmail(),
|
||||||
|
password: userHelper.getDefaultPassword()
|
||||||
|
})
|
||||||
|
newUserHelper.user.email.should.equal(userHelper.user.email)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('when the csrfToken is cached', function() {
|
describe('without email', function() {
|
||||||
it('should fetch csrfToken', async function() {
|
it('should throw error', async function() {
|
||||||
let userHelper = new UserHelper()
|
await UserHelper.loginUser({
|
||||||
await userHelper.getCsrfToken()
|
password: userHelper.getDefaultPassword()
|
||||||
const csrfToken = userHelper._csrfToken
|
}).should.be.rejectedWith('email and password required')
|
||||||
await userHelper.getCsrfToken()
|
})
|
||||||
expect(csrfToken).to.equal(userHelper._csrfToken)
|
})
|
||||||
|
|
||||||
|
describe('without password', function() {
|
||||||
|
it('should throw error', async function() {
|
||||||
|
await UserHelper.loginUser({
|
||||||
|
email: userHelper.getDefaultEmail()
|
||||||
|
}).should.be.rejectedWith('email and password required')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('without email and password', function() {
|
||||||
|
it('should throw error', async function() {
|
||||||
|
await UserHelper.loginUser().should.be.rejectedWith(
|
||||||
|
'email and password required'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('registerUser', function() {
|
describe('UserHelper.registerUser', function() {
|
||||||
describe('with no args', function() {
|
describe('with no args', function() {
|
||||||
before(function() {
|
|
||||||
if (!Features.hasFeature('public-registration')) {
|
|
||||||
this.skip()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create new user with default username and password', async function() {
|
it('should create new user with default username and password', async function() {
|
||||||
const userHelper = await UserHelper.registerUser()
|
const userHelper = await UserHelper.registerUser()
|
||||||
userHelper.user.email.should.equal(userHelper.getDefaultEmail())
|
userHelper.user.email.should.equal(userHelper.getDefaultEmail())
|
||||||
|
@ -113,12 +136,6 @@ describe('UserHelper', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('with email', function() {
|
describe('with email', function() {
|
||||||
before(function() {
|
|
||||||
if (!Features.hasFeature('public-registration')) {
|
|
||||||
this.skip()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create new user with provided email and default password', async function() {
|
it('should create new user with provided email and default password', async function() {
|
||||||
const userHelper = await UserHelper.registerUser({
|
const userHelper = await UserHelper.registerUser({
|
||||||
email: 'foo2@test.com'
|
email: 'foo2@test.com'
|
||||||
|
@ -133,12 +150,6 @@ describe('UserHelper', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('with password', function() {
|
describe('with password', function() {
|
||||||
before(function() {
|
|
||||||
if (!Features.hasFeature('public-registration')) {
|
|
||||||
this.skip()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create new user with provided password and default email', async function() {
|
it('should create new user with provided password and default email', async function() {
|
||||||
const userHelper = await UserHelper.registerUser({
|
const userHelper = await UserHelper.registerUser({
|
||||||
password: 'foofoofoo'
|
password: 'foofoofoo'
|
||||||
|
@ -153,13 +164,28 @@ describe('UserHelper', function() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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 return cached csrfToken', async function() {
|
||||||
|
let userHelper = new UserHelper()
|
||||||
|
await userHelper.getCsrfToken()
|
||||||
|
const csrfToken = userHelper._csrfToken
|
||||||
|
await userHelper.getCsrfToken()
|
||||||
|
expect(csrfToken).to.equal(userHelper._csrfToken)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('after logout', function() {
|
describe('after logout', function() {
|
||||||
let userHelper, oldCsrfToken
|
let userHelper, oldCsrfToken
|
||||||
before(function() {
|
|
||||||
if (!Features.hasFeature('public-registration')) {
|
|
||||||
this.skip()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async function() {
|
beforeEach(async function() {
|
||||||
userHelper = await UserHelper.registerUser()
|
userHelper = await UserHelper.registerUser()
|
||||||
|
|
|
@ -6,7 +6,11 @@ const request = require('request-promise-native')
|
||||||
|
|
||||||
let globalUserNum = 1
|
let globalUserNum = 1
|
||||||
|
|
||||||
module.exports = class UserHelper {
|
class UserHelper {
|
||||||
|
/**
|
||||||
|
* Create UserHelper
|
||||||
|
* @param {object} [user] - Mongo User object
|
||||||
|
*/
|
||||||
constructor(user = null) {
|
constructor(user = null) {
|
||||||
// used for constructing default emails, etc
|
// used for constructing default emails, etc
|
||||||
this.userNum = globalUserNum++
|
this.userNum = globalUserNum++
|
||||||
|
@ -18,22 +22,41 @@ module.exports = class UserHelper {
|
||||||
|
|
||||||
/* sync functions */
|
/* sync functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate default email from unique (per instantiation) user number
|
||||||
|
* @returns {string} email
|
||||||
|
*/
|
||||||
getDefaultEmail() {
|
getDefaultEmail() {
|
||||||
return `test.user.${this.userNum}@example.com`
|
return `test.user.${this.userNum}@example.com`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate email, password args object. Default values will be used if
|
||||||
|
* email and password are not passed in args.
|
||||||
|
* @param {object} [userData]
|
||||||
|
* @param {string} [userData.email] email to use
|
||||||
|
* @param {string} [userData.password] password to use
|
||||||
|
* @returns {object} email, password object
|
||||||
|
*/
|
||||||
getDefaultEmailPassword(userData = {}) {
|
getDefaultEmailPassword(userData = {}) {
|
||||||
return {
|
return {
|
||||||
email: this.getDefaultEmail(),
|
email: this.getDefaultEmail(),
|
||||||
password: this.getDefaultPassword(this.userNum),
|
password: this.getDefaultPassword(),
|
||||||
...userData
|
...userData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate default password from unique (per instantiation) user number
|
||||||
|
* @returns {string} password
|
||||||
|
*/
|
||||||
getDefaultPassword() {
|
getDefaultPassword() {
|
||||||
return `new-password-${this.userNum}!`
|
return `New-Password-${this.userNum}!`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re)set internal state of UserHelper object.
|
||||||
|
*/
|
||||||
reset() {
|
reset() {
|
||||||
// cached csrf token
|
// cached csrf token
|
||||||
this._csrfToken = ''
|
this._csrfToken = ''
|
||||||
|
@ -44,22 +67,27 @@ module.exports = class UserHelper {
|
||||||
// create new request instance
|
// create new request instance
|
||||||
this.request = request.defaults({})
|
this.request = request.defaults({})
|
||||||
// initialize request instance with default options
|
// initialize request instance with default options
|
||||||
this.setRequestDefaults()
|
this.setRequestDefaults({
|
||||||
}
|
|
||||||
|
|
||||||
setRequestDefaults(defaults = {}) {
|
|
||||||
// request-promise instance for making requests
|
|
||||||
this.request = this.request.defaults({
|
|
||||||
baseUrl: UserHelper.baseUrl(),
|
baseUrl: UserHelper.baseUrl(),
|
||||||
followRedirect: false,
|
followRedirect: false,
|
||||||
jar: this.jar,
|
jar: this.jar,
|
||||||
resolveWithFullResponse: true,
|
resolveWithFullResponse: true
|
||||||
...defaults
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set defaults for request object. Applied over existing defaults.
|
||||||
|
* @param {object} [defaults]
|
||||||
|
*/
|
||||||
|
setRequestDefaults(defaults = {}) {
|
||||||
|
// request-promise instance for making requests
|
||||||
|
this.request = this.request.defaults(defaults)
|
||||||
|
}
|
||||||
|
|
||||||
/* async http api call methods */
|
/* async http api call methods */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests csrf token unless already cached in internal state
|
||||||
|
*/
|
||||||
async getCsrfToken() {
|
async getCsrfToken() {
|
||||||
if (this._csrfToken) {
|
if (this._csrfToken) {
|
||||||
return
|
return
|
||||||
|
@ -73,6 +101,11 @@ module.exports = class UserHelper {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make request to POST /logout
|
||||||
|
* @param {object} [options] options to pass to request
|
||||||
|
* @returns {object} http response
|
||||||
|
*/
|
||||||
async logout(options = {}) {
|
async logout(options = {}) {
|
||||||
// do not throw exception on 302
|
// do not throw exception on 302
|
||||||
options.simple = false
|
options.simple = false
|
||||||
|
@ -84,20 +117,30 @@ module.exports = class UserHelper {
|
||||||
) {
|
) {
|
||||||
throw new Error('logout failed')
|
throw new Error('logout failed')
|
||||||
}
|
}
|
||||||
// clear out internal state
|
// after logout CSRF token becomes invalid
|
||||||
this.reset()
|
this._csrfToken = ''
|
||||||
// resolve with http request response
|
// resolve with http request response
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static sync methods */
|
/* static sync methods */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates base URL from env options
|
||||||
|
* @returns {string} baseUrl
|
||||||
|
*/
|
||||||
static baseUrl() {
|
static baseUrl() {
|
||||||
return `http://${process.env['HTTP_TEST_HOST'] || 'localhost'}:3000`
|
return `http://${process.env['HTTP_TEST_HOST'] || 'localhost'}:3000`
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static async instantiation methods */
|
/* static async instantiation methods */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new user via UserCreator and return UserHelper instance
|
||||||
|
* @param {object} attributes user data for UserCreator
|
||||||
|
* @param {object} options options for UserCreator
|
||||||
|
* @returns {UserHelper}
|
||||||
|
*/
|
||||||
static async createUser(attributes = {}, options = {}) {
|
static async createUser(attributes = {}, options = {}) {
|
||||||
const userHelper = new UserHelper()
|
const userHelper = new UserHelper()
|
||||||
attributes = userHelper.getDefaultEmailPassword(attributes)
|
attributes = userHelper.getDefaultEmailPassword(attributes)
|
||||||
|
@ -122,14 +165,30 @@ module.exports = class UserHelper {
|
||||||
return userHelper
|
return userHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get existing user via UserGetter and return UserHelper instance.
|
||||||
|
* All args passed to UserGetter.getUser.
|
||||||
|
* @returns {UserHelper}
|
||||||
|
*/
|
||||||
static async getUser(...args) {
|
static async getUser(...args) {
|
||||||
const user = await UserGetter.promises.getUser(...args)
|
const user = await UserGetter.promises.getUser(...args)
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new Error(`no user found for args: ${JSON.stringify([...args])}`)
|
||||||
|
}
|
||||||
|
|
||||||
return new UserHelper(user)
|
return new UserHelper(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login to existing account via request and return UserHelper instance
|
||||||
|
* @param {object} userData
|
||||||
|
* @param {string} userData.email
|
||||||
|
* @param {string} userData.password
|
||||||
|
* @returns {UserHelper}
|
||||||
|
*/
|
||||||
static async loginUser(userData) {
|
static async loginUser(userData) {
|
||||||
if (!userData.email || !userData.password) {
|
if (!userData || !userData.email || !userData.password) {
|
||||||
throw new Error('email and password required')
|
throw new Error('email and password required')
|
||||||
}
|
}
|
||||||
const userHelper = new UserHelper()
|
const userHelper = new UserHelper()
|
||||||
|
@ -153,6 +212,14 @@ module.exports = class UserHelper {
|
||||||
return userHelper
|
return userHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register new account via request and return UserHelper instance.
|
||||||
|
* If userData is not provided the default email and password will be used.
|
||||||
|
* @param {object} [userData]
|
||||||
|
* @param {string} [userData.email]
|
||||||
|
* @param {string} [userData.password]
|
||||||
|
* @returns {UserHelper}
|
||||||
|
*/
|
||||||
static async registerUser(userData, options = {}) {
|
static async registerUser(userData, options = {}) {
|
||||||
const userHelper = new UserHelper()
|
const userHelper = new UserHelper()
|
||||||
await userHelper.getCsrfToken()
|
await userHelper.getCsrfToken()
|
||||||
|
@ -177,3 +244,5 @@ module.exports = class UserHelper {
|
||||||
return userHelper
|
return userHelper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = UserHelper
|
||||||
|
|
Loading…
Reference in a new issue