Merge pull request #9956 from overleaf/em-node-fetch-web

Replace request-promise with fetch in web acceptance tests

GitOrigin-RevId: f50357cdea2d1353d7a82c5346b149018f91823f
This commit is contained in:
Eric Mc Sween 2022-10-17 09:53:55 -04:00 committed by Copybot
parent 00b051e2d7
commit fe963ba692
9 changed files with 368 additions and 453 deletions

89
package-lock.json generated
View file

@ -25893,49 +25893,6 @@
"throttleit": "^1.0.0" "throttleit": "^1.0.0"
} }
}, },
"node_modules/request-promise-core": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
"dependencies": {
"lodash": "^4.17.19"
},
"engines": {
"node": ">=0.10.0"
},
"peerDependencies": {
"request": "^2.34"
}
},
"node_modules/request-promise-native": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
"integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
"deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142",
"dependencies": {
"request-promise-core": "1.1.4",
"stealthy-require": "^1.1.1",
"tough-cookie": "^2.3.3"
},
"engines": {
"node": ">=0.12.0"
},
"peerDependencies": {
"request": "^2.34"
}
},
"node_modules/request-promise-native/node_modules/tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/request/node_modules/form-data": { "node_modules/request/node_modules/form-data": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
@ -28212,14 +28169,6 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/stream-buffers": { "node_modules/stream-buffers": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz",
@ -35066,7 +35015,6 @@
"recurly": "^4.0.0", "recurly": "^4.0.0",
"referer-parser": "0.0.3", "referer-parser": "0.0.3",
"request": "^2.88.2", "request": "^2.88.2",
"request-promise-native": "^1.0.8",
"requestretry": "^6.0.0", "requestretry": "^6.0.0",
"rimraf": "2.2.6", "rimraf": "2.2.6",
"rolling-rate-limiter": "^0.2.10", "rolling-rate-limiter": "^0.2.10",
@ -35169,6 +35117,7 @@
"terser-webpack-plugin": "^5.3.1", "terser-webpack-plugin": "^5.3.1",
"timekeeper": "^2.2.0", "timekeeper": "^2.2.0",
"to-string-loader": "^1.2.0", "to-string-loader": "^1.2.0",
"tough-cookie": "^4.0.0",
"typescript": "^4.5.5", "typescript": "^4.5.5",
"val-loader": "^4.0.0", "val-loader": "^4.0.0",
"webpack": "^5.71.0", "webpack": "^5.71.0",
@ -42853,7 +42802,6 @@
"recurly": "^4.0.0", "recurly": "^4.0.0",
"referer-parser": "0.0.3", "referer-parser": "0.0.3",
"request": "^2.88.2", "request": "^2.88.2",
"request-promise-native": "^1.0.8",
"requestretry": "^6.0.0", "requestretry": "^6.0.0",
"requirejs": "^2.3.6", "requirejs": "^2.3.6",
"rimraf": "2.2.6", "rimraf": "2.2.6",
@ -42870,6 +42818,7 @@
"terser-webpack-plugin": "^5.3.1", "terser-webpack-plugin": "^5.3.1",
"timekeeper": "^2.2.0", "timekeeper": "^2.2.0",
"to-string-loader": "^1.2.0", "to-string-loader": "^1.2.0",
"tough-cookie": "^4.0.0",
"tsscmp": "^1.0.6", "tsscmp": "^1.0.6",
"typescript": "^4.5.5", "typescript": "^4.5.5",
"underscore": "^1.13.1", "underscore": "^1.13.1",
@ -61749,35 +61698,6 @@
"throttleit": "^1.0.0" "throttleit": "^1.0.0"
} }
}, },
"request-promise-core": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
"requires": {
"lodash": "^4.17.19"
}
},
"request-promise-native": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
"integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
"requires": {
"request-promise-core": "1.1.4",
"stealthy-require": "^1.1.1",
"tough-cookie": "^2.3.3"
},
"dependencies": {
"tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"requires": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
}
}
}
},
"requestretry": { "requestretry": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/requestretry/-/requestretry-4.1.2.tgz", "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-4.1.2.tgz",
@ -63594,11 +63514,6 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
}, },
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"stream-buffers": { "stream-buffers": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz",

View file

@ -9,9 +9,10 @@ describe('Launchpad', function () {
const user = new UserHelper() const user = new UserHelper()
it('should show the launchpad page', async function () { it('should show the launchpad page', async function () {
const response = await user.request.get('/launchpad') const response = await user.fetch('/launchpad')
expect(response.statusCode).to.equal(200) expect(response.status).to.equal(200)
const $ = cheerio.load(response.body) const body = await response.text()
const $ = cheerio.load(body)
expect($('h2').first().text()).to.equal('Create the first Admin account') expect($('h2').first().text()).to.equal('Create the first Admin account')
expect($('form[name="email"]').first()).to.exist expect($('form[name="email"]').first()).to.exist
expect($('form[name="password"]').first()).to.exist expect($('form[name="password"]').first()).to.exist
@ -19,45 +20,54 @@ describe('Launchpad', function () {
it('should allow for creation of the first admin user', async function () { it('should allow for creation of the first admin user', async function () {
// Load the launchpad page // Load the launchpad page
const initialPageResponse = await user.request.get('/launchpad') const initialPageResponse = await user.fetch('/launchpad')
expect(initialPageResponse.statusCode).to.equal(200) expect(initialPageResponse.status).to.equal(200)
const $ = cheerio.load(initialPageResponse.body) const initialPageBody = await initialPageResponse.text()
const $ = cheerio.load(initialPageBody)
expect($('h2').first().text()).to.equal('Create the first Admin account') expect($('h2').first().text()).to.equal('Create the first Admin account')
expect($('form[name="email"]').first()).to.exist expect($('form[name="email"]').first()).to.exist
expect($('form[name="password"]').first()).to.exist expect($('form[name="password"]').first()).to.exist
// Submit the form // Submit the form
let csrfToken = await user.getCsrfToken() let csrfToken = await user.getCsrfToken()
const postResponse = await user.request.post({ const postResponse = await user.fetch('/launchpad/register_admin', {
url: '/launchpad/register_admin', method: 'POST',
json: { headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
_csrf: csrfToken, _csrf: csrfToken,
email: adminEmail, email: adminEmail,
password: adminPassword, password: adminPassword,
}, }),
}) })
expect(postResponse.statusCode).to.equal(200) expect(postResponse.status).to.equal(200)
expect(postResponse.body).to.deep.equal({ redir: '/launchpad' }) const postBody = await postResponse.json()
expect(postBody).to.deep.equal({ redir: '/launchpad' })
// Try to load the page again // Try to load the page again
const secondPageResponse = await user.request.get('/launchpad', { const secondPageResponse = await user.fetch('/launchpad')
simple: false, expect(secondPageResponse.status).to.equal(302)
}) expect(secondPageResponse.headers.get('location')).to.equal(
expect(secondPageResponse.statusCode).to.equal(302) UserHelper.url('/login').toString()
expect(secondPageResponse.headers.location).to.equal('/login') )
// Forbid submitting the form again // Forbid submitting the form again
csrfToken = await user.getCsrfToken() csrfToken = await user.getCsrfToken()
const badPostResponse = await user.request.post({ const badPostResponse = await user.fetch('/launchpad/register_admin', {
url: '/launchpad/register_admin', method: 'POST',
json: { headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
_csrf: csrfToken, _csrf: csrfToken,
email: adminEmail + '1', email: adminEmail + '1',
password: adminPassword + '1', password: adminPassword + '1',
}, }),
simple: false,
}) })
expect(badPostResponse.statusCode).to.equal(403) expect(badPostResponse.status).to.equal(403)
// Log in as this new admin user // Log in as this new admin user
const adminUser = await UserHelper.loginUser({ const adminUser = await UserHelper.loginUser({

View file

@ -206,7 +206,6 @@
"recurly": "^4.0.0", "recurly": "^4.0.0",
"referer-parser": "0.0.3", "referer-parser": "0.0.3",
"request": "^2.88.2", "request": "^2.88.2",
"request-promise-native": "^1.0.8",
"requestretry": "^6.0.0", "requestretry": "^6.0.0",
"rimraf": "2.2.6", "rimraf": "2.2.6",
"rolling-rate-limiter": "^0.2.10", "rolling-rate-limiter": "^0.2.10",
@ -309,6 +308,7 @@
"terser-webpack-plugin": "^5.3.1", "terser-webpack-plugin": "^5.3.1",
"timekeeper": "^2.2.0", "timekeeper": "^2.2.0",
"to-string-loader": "^1.2.0", "to-string-loader": "^1.2.0",
"tough-cookie": "^4.0.0",
"typescript": "^4.5.5", "typescript": "^4.5.5",
"val-loader": "^4.0.0", "val-loader": "^4.0.0",
"webpack": "^5.71.0", "webpack": "^5.71.0",

View file

@ -13,31 +13,21 @@ describe('BetaProgram', function () {
}) })
}) })
it('should opt in', async function () { it('should opt in', async function () {
const response = await userHelper.request.post('/beta/opt-in', { const response = await userHelper.fetch('/beta/opt-in', { method: 'POST' })
simple: false, expect(response.status).to.equal(302)
}) expect(response.headers.get('location')).to.equal(
expect(response.statusCode).to.equal(302) UserHelper.url('/beta/participate').toString()
response.statusCode.should.equal(302) )
expect(response.headers.location).to.equal('/beta/participate') const user = (await UserHelper.getUser({ email })).user
const user = (
await UserHelper.getUser({
email,
})
).user
expect(user.betaProgram).to.equal(true) expect(user.betaProgram).to.equal(true)
}) })
it('should opt out', async function () { it('should opt out', async function () {
const response = await userHelper.request.post('/beta/opt-out', { const response = await userHelper.fetch('/beta/opt-out', { method: 'POST' })
simple: false, expect(response.status).to.equal(302)
}) expect(response.headers.get('location')).to.equal(
expect(response.statusCode).to.equal(302) UserHelper.url('/beta/participate').toString()
response.statusCode.should.equal(302) )
expect(response.headers.location).to.equal('/beta/participate') const user = (await UserHelper.getUser({ email })).user
const user = (
await UserHelper.getUser({
email,
})
).user
expect(user.betaProgram).to.equal(false) expect(user.betaProgram).to.equal(false)
}) })
}) })

View file

@ -13,10 +13,9 @@ describe('PasswordReset', function () {
// generate the token // generate the token
await userHelper.getCsrfToken() await userHelper.getCsrfToken()
response = await userHelper.request.post('/user/password/reset', { response = await userHelper.fetch('/user/password/reset', {
form: { method: 'POST',
email, body: new URLSearchParams({ email }),
},
}) })
token = ( token = (
@ -32,20 +31,20 @@ describe('PasswordReset', function () {
email, email,
password: userHelper.getDefaultPassword(), password: userHelper.getDefaultPassword(),
}) })
response = await userHelper.request.get( response = await userHelper.fetch(
`/user/password/set?passwordResetToken=${token}&email=${email}`, `/user/password/set?passwordResetToken=${token}&email=${email}`
{ simple: false }
) )
expect(response.statusCode).to.equal(302) expect(response.status).to.equal(302)
expect(response.headers.location).to.equal( expect(response.headers.get('location')).to.equal(
`/user/password/set${emailQuery}` UserHelper.url(`/user/password/set${emailQuery}`).toString()
) )
// send reset request // send reset request
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: 'a-password', password: 'a-password',
}, }),
}) })
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
user = userHelper.user user = userHelper.user
@ -75,20 +74,20 @@ describe('PasswordReset', function () {
email: otherUserEmail, email: otherUserEmail,
password: userHelper.getDefaultPassword(), password: userHelper.getDefaultPassword(),
}) })
response = await userHelper.request.get( response = await userHelper.fetch(
`/user/password/set?passwordResetToken=${token}&email=${email}`, `/user/password/set?passwordResetToken=${token}&email=${email}`
{ simple: false }
) )
expect(response.statusCode).to.equal(302) expect(response.status).to.equal(302)
expect(response.headers.location).to.equal( expect(response.headers.get('location')).to.equal(
`/user/password/set${emailQuery}` UserHelper.url(`/user/password/set${emailQuery}`).toString()
) )
// send reset request // send reset request
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: 'a-password', password: 'a-password',
}, }),
}) })
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
user = userHelper.user user = userHelper.user
@ -110,20 +109,20 @@ describe('PasswordReset', function () {
}) })
describe('when not logged in', function () { describe('when not logged in', function () {
beforeEach(async function () { beforeEach(async function () {
response = await userHelper.request.get( response = await userHelper.fetch(
`/user/password/set?passwordResetToken=${token}&email=${email}`, `/user/password/set?passwordResetToken=${token}&email=${email}`
{ simple: false }
) )
expect(response.statusCode).to.equal(302) expect(response.status).to.equal(302)
expect(response.headers.location).to.equal( expect(response.headers.get('location')).to.equal(
`/user/password/set${emailQuery}` UserHelper.url(`/user/password/set${emailQuery}`).toString()
) )
// send reset request // send reset request
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: 'a-password', password: 'a-password',
}, }),
}) })
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
user = userHelper.user user = userHelper.user
@ -144,24 +143,23 @@ describe('PasswordReset', function () {
}) })
describe('password checks', function () { describe('password checks', function () {
beforeEach(async function () { beforeEach(async function () {
response = await userHelper.request.get( response = await userHelper.fetch(
`/user/password/set?passwordResetToken=${token}&email=${email}`, `/user/password/set?passwordResetToken=${token}&email=${email}`
{ simple: false }
) )
expect(response.statusCode).to.equal(302) expect(response.status).to.equal(302)
expect(response.headers.location).to.equal( expect(response.headers.get('location')).to.equal(
`/user/password/set${emailQuery}` UserHelper.url(`/user/password/set${emailQuery}`).toString()
) )
}) })
it('without a password should return 400 and not log the change', async function () { it('without a password should return 400 and not log the change', async function () {
// send reset request // send reset request
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
}, }),
simple: false,
}) })
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()
@ -170,14 +168,14 @@ describe('PasswordReset', function () {
it('without a valid password should return 400 and not log the change', async function () { it('without a valid password should return 400 and not log the change', async function () {
// send reset request // send reset request
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: 'short', password: 'short',
}, }),
simple: false,
}) })
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()
@ -187,41 +185,45 @@ describe('PasswordReset', function () {
it('should flag email in password', async function () { it('should flag email in password', async function () {
const localPart = email.split('@').shift() const localPart = email.split('@').shift()
// send bad password // send bad password
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
passwordResetToken: token, passwordResetToken: token,
password: localPart, password: localPart,
email, email,
}, }),
json: true,
simple: false,
}) })
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
expect(response.body).to.deep.equal({ const body = await response.json()
expect(body).to.deep.equal({
message: { text: 'password contains part of email address' }, message: { text: 'password contains part of email address' },
}) })
}) })
it('should be able to retry after providing an invalid password', async function () { it('should be able to retry after providing an invalid password', async function () {
// send bad password // send bad password
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: 'short', password: 'short',
}, }),
simple: false,
}) })
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
// send good password // send good password
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: 'SomeThingVeryStrong!11', password: 'SomeThingVeryStrong!11',
}, }),
simple: false,
}) })
expect(response.statusCode).to.equal(200) expect(response.status).to.equal(200)
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()
@ -230,17 +232,16 @@ describe('PasswordReset', function () {
it('when the password is the same as current, should return 400 and log the change', async function () { it('when the password is the same as current, should return 400 and log the change', async function () {
// send reset request // send reset request
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: userHelper.getDefaultPassword(), password: userHelper.getDefaultPassword(),
}, }),
simple: false,
}) })
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
expect(JSON.parse(response.body).message.key).to.equal( const body = await response.json()
'password-must-be-different' expect(body.message.key).to.equal('password-must-be-different')
)
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()
@ -251,80 +252,81 @@ describe('PasswordReset', function () {
describe('multiple attempts to set the password, reaching attempt limit', async function () { describe('multiple attempts to set the password, reaching attempt limit', async function () {
beforeEach(async function () { beforeEach(async function () {
response = await userHelper.request.get( response = await userHelper.fetch(
`/user/password/set?passwordResetToken=${token}&email=${email}`, `/user/password/set?passwordResetToken=${token}&email=${email}`
{ simple: false }
) )
expect(response.statusCode).to.equal(302) expect(response.status).to.equal(302)
expect(response.headers.location).to.equal( expect(response.headers.get('location')).to.equal(
`/user/password/set${emailQuery}` UserHelper.url(`/user/password/set${emailQuery}`).toString()
) )
}) })
it('should allow multiple attempts with same-password error, then deny further attempts', async function () { it('should allow multiple attempts with same-password error, then deny further attempts', async function () {
const sendSamePasswordRequest = async function () { const sendSamePasswordRequest = async function () {
return userHelper.request.post('/user/password/set', { return userHelper.fetch('/user/password/set', {
form: { method: 'POST',
headers: {
Accept: 'application/json',
},
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: userHelper.getDefaultPassword(), password: userHelper.getDefaultPassword(),
}, }),
simple: false,
}) })
} }
// Three attempts at setting the password, all rejected for being the same as // Three attempts at setting the password, all rejected for being the same as
// the current password // the current password
const response1 = await sendSamePasswordRequest() const response1 = await sendSamePasswordRequest()
expect(response1.statusCode).to.equal(400) expect(response1.status).to.equal(400)
expect(JSON.parse(response1.body).message.key).to.equal( const body1 = await response1.json()
'password-must-be-different' expect(body1.message.key).to.equal('password-must-be-different')
)
const response2 = await sendSamePasswordRequest() const response2 = await sendSamePasswordRequest()
expect(response2.statusCode).to.equal(400) expect(response2.status).to.equal(400)
expect(JSON.parse(response2.body).message.key).to.equal( const body2 = await response2.json()
'password-must-be-different' expect(body2.message.key).to.equal('password-must-be-different')
)
const response3 = await sendSamePasswordRequest() const response3 = await sendSamePasswordRequest()
expect(response3.statusCode).to.equal(400) expect(response3.status).to.equal(400)
expect(JSON.parse(response3.body).message.key).to.equal( const body3 = await response3.json()
'password-must-be-different' expect(body3.message.key).to.equal('password-must-be-different')
)
// Fourth attempt is rejected because the token has been used too many times // Fourth attempt is rejected because the token has been used too many times
const response4 = await sendSamePasswordRequest() const response4 = await sendSamePasswordRequest()
expect(response4.statusCode).to.equal(404) expect(response4.status).to.equal(404)
expect(JSON.parse(response4.body).message.key).to.equal('token-expired') const body4 = await response4.json()
expect(body4.message.key).to.equal('token-expired')
}) })
it('should allow multiple attempts with same-password error, then set the password', async function () { it('should allow multiple attempts with same-password error, then set the password', async function () {
const sendSamePasswordRequest = async function () { const sendSamePasswordRequest = async function () {
return userHelper.request.post('/user/password/set', { return userHelper.fetch('/user/password/set', {
form: { method: 'POST',
headers: {
Accept: 'application/json',
},
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: userHelper.getDefaultPassword(), password: userHelper.getDefaultPassword(),
}, }),
simple: false,
}) })
} }
// Two attempts at setting the password, all rejected for being the same as // Two attempts at setting the password, all rejected for being the same as
// the current password // the current password
const response1 = await sendSamePasswordRequest() const response1 = await sendSamePasswordRequest()
expect(response1.statusCode).to.equal(400) expect(response1.status).to.equal(400)
expect(JSON.parse(response1.body).message.key).to.equal( const body1 = await response1.json()
'password-must-be-different' expect(body1.message.key).to.equal('password-must-be-different')
)
const response2 = await sendSamePasswordRequest() const response2 = await sendSamePasswordRequest()
expect(response2.statusCode).to.equal(400) expect(response2.status).to.equal(400)
expect(JSON.parse(response2.body).message.key).to.equal( const body2 = await response2.json()
'password-must-be-different' expect(body2.message.key).to.equal('password-must-be-different')
)
// Third attempt is succeeds // Third attempt is succeeds
const response3 = await userHelper.request.post('/user/password/set', { const response3 = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
password: 'some-new-password', password: 'some-new-password',
}, }),
simple: false,
}) })
expect(response3.statusCode).to.equal(200) expect(response3.status).to.equal(200)
// Check the user and audit log // Check the user and audit log
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
user = userHelper.user user = userHelper.user
@ -342,83 +344,79 @@ describe('PasswordReset', function () {
describe('without a valid token', function () { describe('without a valid token', function () {
it('no token should redirect to page to re-request reset token', async function () { it('no token should redirect to page to re-request reset token', async function () {
response = await userHelper.request.get( response = await userHelper.fetch(`/user/password/set?&email=${email}`)
`/user/password/set?&email=${email}`, expect(response.status).to.equal(302)
{ simple: false } expect(response.headers.get('location')).to.equal(
UserHelper.url('/user/password/reset').toString()
) )
expect(response.statusCode).to.equal(302)
expect(response.headers.location).to.equal('/user/password/reset')
}) })
it('should show error for invalid tokens and return 404 if used', async function () { it('should show error for invalid tokens and return 404 if used', async function () {
const invalidToken = 'not-real-token' const invalidToken = 'not-real-token'
response = await userHelper.request.get( response = await userHelper.fetch(
`/user/password/set?&passwordResetToken=${invalidToken}&email=${email}`, `/user/password/set?&passwordResetToken=${invalidToken}&email=${email}`
{ simple: false }
) )
expect(response.statusCode).to.equal(302) expect(response.status).to.equal(302)
expect(response.headers.location).to.equal( expect(response.headers.get('location')).to.equal(
`/user/password/reset?error=token_expired` UserHelper.url('/user/password/reset?error=token_expired').toString()
) )
// send reset request // send reset request
response = await userHelper.request.post('/user/password/set', { response = await userHelper.fetch('/user/password/set', {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: invalidToken, passwordResetToken: invalidToken,
password: 'a-password', password: 'a-password',
}, }),
simple: false,
}) })
expect(response.statusCode).to.equal(404) expect(response.status).to.equal(404)
}) })
}) })
describe('password reset', function () { describe('password reset', function () {
it('should return 200 if email field is valid', async function () { it('should return 200 if email field is valid', async function () {
response = await userHelper.request.post(`/user/password/reset`, { response = await userHelper.fetch(`/user/password/reset`, {
form: { method: 'POST',
email, body: new URLSearchParams({ email }),
},
}) })
expect(response.statusCode).to.equal(200) expect(response.status).to.equal(200)
}) })
it('should return 400 if email field is missing', async function () { it('should return 400 if email field is missing', async function () {
response = await userHelper.request.post(`/user/password/reset`, { response = await userHelper.fetch(`/user/password/reset`, {
form: { method: 'POST',
mail: email, body: new URLSearchParams({ mail: email }),
},
simple: false,
}) })
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
}) })
}) })
describe('password set', function () { describe('password set', function () {
it('should return 200 if password and passwordResetToken fields are valid', async function () { it('should return 200 if password and passwordResetToken fields are valid', async function () {
response = await userHelper.request.post(`/user/password/set`, { response = await userHelper.fetch(`/user/password/set`, {
form: { method: 'POST',
body: new URLSearchParams({
password: 'new-password', password: 'new-password',
passwordResetToken: token, passwordResetToken: token,
}, }),
}) })
expect(response.statusCode).to.equal(200) expect(response.status).to.equal(200)
}) })
it('should return 400 if password field is missing', async function () { it('should return 400 if password field is missing', async function () {
response = await userHelper.request.post(`/user/password/set`, { response = await userHelper.fetch(`/user/password/set`, {
form: { method: 'POST',
body: new URLSearchParams({
passwordResetToken: token, passwordResetToken: token,
}, }),
simple: false,
}) })
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
}) })
it('should return 400 if passwordResetToken field is missing', async function () { it('should return 400 if passwordResetToken field is missing', async function () {
response = await userHelper.request.post(`/user/password/set`, { response = await userHelper.fetch(`/user/password/set`, {
form: { method: 'POST',
body: new URLSearchParams({
password: 'new-password', password: 'new-password',
}, }),
simple: false,
}) })
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
}) })
}) })
}) })

View file

@ -23,19 +23,19 @@ describe('PasswordUpdate', function () {
}) })
describe('success', function () { describe('success', function () {
beforeEach(async function () { beforeEach(async function () {
response = await userHelper.request.post('/user/password/update', { response = await userHelper.fetch('/user/password/update', {
form: { method: 'POST',
body: new URLSearchParams({
currentPassword: password, currentPassword: password,
newPassword1: 'new-password', newPassword1: 'new-password',
newPassword2: 'new-password', newPassword2: 'new-password',
}, }),
simple: false,
}) })
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
user = userHelper.user user = userHelper.user
}) })
it('should return 200', async function () { it('should return 200', async function () {
expect(response.statusCode).to.equal(200) expect(response.status).to.equal(200)
}) })
it('should update the audit log', function () { it('should update the audit log', function () {
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()
@ -50,17 +50,17 @@ describe('PasswordUpdate', function () {
describe('errors', function () { describe('errors', function () {
describe('missing current password', function () { describe('missing current password', function () {
beforeEach(async function () { beforeEach(async function () {
response = await userHelper.request.post('/user/password/update', { response = await userHelper.fetch('/user/password/update', {
form: { method: 'POST',
body: new URLSearchParams({
newPassword1: 'new-password', newPassword1: 'new-password',
newPassword2: 'new-password', newPassword2: 'new-password',
}, }),
simple: false,
}) })
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
}) })
it('should return 500', async function () { it('should return 500', async function () {
expect(response.statusCode).to.equal(500) expect(response.status).to.equal(500)
}) })
it('should not update audit log', async function () { it('should not update audit log', async function () {
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()
@ -69,18 +69,18 @@ describe('PasswordUpdate', function () {
}) })
describe('wrong current password', function () { describe('wrong current password', function () {
beforeEach(async function () { beforeEach(async function () {
response = await userHelper.request.post('/user/password/update', { response = await userHelper.fetch('/user/password/update', {
form: { method: 'POST',
body: new URLSearchParams({
currentPassword: 'wrong-password', currentPassword: 'wrong-password',
newPassword1: 'new-password', newPassword1: 'new-password',
newPassword2: 'new-password', newPassword2: 'new-password',
}, }),
simple: false,
}) })
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
}) })
it('should return 400', async function () { it('should return 400', async function () {
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
}) })
it('should not update audit log', async function () { it('should not update audit log', async function () {
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()
@ -89,22 +89,26 @@ describe('PasswordUpdate', function () {
}) })
describe('newPassword1 does not match newPassword2', function () { describe('newPassword1 does not match newPassword2', function () {
beforeEach(async function () { beforeEach(async function () {
response = await userHelper.request.post('/user/password/update', { response = await userHelper.fetch('/user/password/update', {
form: { method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
currentPassword: password, currentPassword: password,
newPassword1: 'new-password', newPassword1: 'new-password',
newPassword2: 'oops-password', newPassword2: 'oops-password',
}, }),
json: true,
simple: false,
}) })
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
}) })
it('should return 400', async function () { it('should return 400', async function () {
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
}) })
it('should return error message', async function () { it('should return error message', async function () {
expect(response.body.message).to.equal('Passwords do not match') const body = await response.json()
expect(body.message).to.equal('Passwords do not match')
}) })
it('should not update audit log', async function () { it('should not update audit log', async function () {
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()
@ -113,22 +117,26 @@ describe('PasswordUpdate', function () {
}) })
describe('new password is not valid', function () { describe('new password is not valid', function () {
beforeEach(async function () { beforeEach(async function () {
response = await userHelper.request.post('/user/password/update', { response = await userHelper.fetch('/user/password/update', {
form: { method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
currentPassword: password, currentPassword: password,
newPassword1: 'short', newPassword1: 'short',
newPassword2: 'short', newPassword2: 'short',
}, }),
json: true,
simple: false,
}) })
userHelper = await UserHelper.getUser({ email }) userHelper = await UserHelper.getUser({ email })
}) })
it('should return 400', async function () { it('should return 400', async function () {
expect(response.statusCode).to.equal(400) expect(response.status).to.equal(400)
}) })
it('should return error message', async function () { it('should return error message', async function () {
expect(response.body.message).to.equal('password is too short') const body = await response.json()
expect(body.message).to.equal('password is too short')
}) })
it('should not update audit log', async function () { it('should not update audit log', async function () {
const auditLog = userHelper.getAuditLogWithoutNoise() const auditLog = userHelper.getAuditLogWithoutNoise()

View file

@ -43,19 +43,18 @@ describe('PrimaryEmailCheck', function () {
describe('redirections', function () { describe('redirections', function () {
describe('when the user has signed up recently', function () { describe('when the user has signed up recently', function () {
it("shouldn't be redirected from project list to the primary email check page", async function () { it("shouldn't be redirected from project list to the primary email check page", async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch('/project' + SPLIT_TEST_QUERY)
'/project' + SPLIT_TEST_QUERY expect(response.status).to.equal(200)
)
expect(response.statusCode).to.equal(200)
}) })
it('should be redirected from the primary email check page to the project list', async function () { it('should be redirected from the primary email check page to the project list', async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch(
'/user/emails/primary-email-check' + SPLIT_TEST_QUERY, '/user/emails/primary-email-check' + SPLIT_TEST_QUERY
{ simple: false } )
expect(response.status).to.equal(302)
expect(response.headers.get('location')).to.equal(
UserHelper.url('/project').toString()
) )
expect(response.statusCode).to.equal(302)
expect(response.headers.location).to.equal('/project')
}) })
}) })
@ -68,19 +67,18 @@ describe('PrimaryEmailCheck', function () {
}) })
it("shouldn't be redirected from project list to the primary email check page", async function () { it("shouldn't be redirected from project list to the primary email check page", async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch('/project' + SPLIT_TEST_QUERY)
'/project' + SPLIT_TEST_QUERY expect(response.status).to.equal(200)
)
expect(response.statusCode).to.equal(200)
}) })
it('should be redirected from the primary email check page to the project list', async function () { it('should be redirected from the primary email check page to the project list', async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch(
'/user/emails/primary-email-check' + SPLIT_TEST_QUERY, '/user/emails/primary-email-check' + SPLIT_TEST_QUERY
{ simple: false } )
expect(response.status).to.equal(302)
expect(response.headers.get('location')).to.equal(
UserHelper.url('/project').toString()
) )
expect(response.statusCode).to.equal(302)
expect(response.headers.location).to.equal('/project')
}) })
}) })
@ -100,19 +98,18 @@ describe('PrimaryEmailCheck', function () {
}) })
it("shouldn't be redirected from project list to the primary email check page", async function () { it("shouldn't be redirected from project list to the primary email check page", async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch('/project' + SPLIT_TEST_QUERY)
'/project' + SPLIT_TEST_QUERY expect(response.status).to.equal(200)
)
expect(response.statusCode).to.equal(200)
}) })
it('should be redirected from the primary email check page to the project list', async function () { it('should be redirected from the primary email check page to the project list', async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch(
'/user/emails/primary-email-check' + SPLIT_TEST_QUERY, '/user/emails/primary-email-check' + SPLIT_TEST_QUERY
{ simple: false } )
expect(response.status).to.equal(302)
expect(response.headers.get('location')).to.equal(
UserHelper.url('/project').toString()
) )
expect(response.statusCode).to.equal(302)
expect(response.headers.location).to.equal('/project')
}) })
}) })
@ -125,21 +122,18 @@ describe('PrimaryEmailCheck', function () {
}) })
it('should be redirected from project list to the primary email check page', async function () { it('should be redirected from project list to the primary email check page', async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch('/project' + SPLIT_TEST_QUERY)
'/project' + SPLIT_TEST_QUERY, expect(response.status).to.equal(302)
{ simple: false } expect(response.headers.get('location')).to.equal(
) UserHelper.url('/user/emails/primary-email-check').toString()
expect(response.statusCode).to.equal(302)
expect(response.headers.location).to.equal(
'/user/emails/primary-email-check'
) )
}) })
it('can visit the primary email check page', async function () { it('can visit the primary email check page', async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch(
'/user/emails/primary-email-check' '/user/emails/primary-email-check'
) )
expect(response.statusCode).to.equal(200) expect(response.status).to.equal(200)
}) })
}) })
}) })
@ -154,34 +148,32 @@ describe('PrimaryEmailCheck', function () {
$set: { lastPrimaryEmailCheck: new Date(time) }, $set: { lastPrimaryEmailCheck: new Date(time) },
}) })
checkResponse = await userHelper.request.post( checkResponse = await userHelper.fetch(
'/user/emails/primary-email-check' + SPLIT_TEST_QUERY, '/user/emails/primary-email-check' + SPLIT_TEST_QUERY,
{ { method: 'POST' }
form: {},
simple: false,
}
) )
}) })
it('should be redirected to the project list page', function () { it('should be redirected to the project list page', function () {
expect(checkResponse.statusCode).to.equal(302) expect(checkResponse.status).to.equal(302)
expect(checkResponse.headers.location).to.equal('/project') expect(checkResponse.headers.get('location')).to.equal(
UserHelper.url('/project').toString()
)
}) })
it("shouldn't be redirected from project list to the primary email check page any longer", async function () { it("shouldn't be redirected from project list to the primary email check page any longer", async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch('/project' + SPLIT_TEST_QUERY)
'/project' + SPLIT_TEST_QUERY expect(response.status).to.equal(200)
)
expect(response.statusCode).to.equal(200)
}) })
it('visiting the primary email check page should redirect to the project list page', async function () { it('visiting the primary email check page should redirect to the project list page', async function () {
const response = await userHelper.request.get( const response = await userHelper.fetch(
'/user/emails/primary-email-check', '/user/emails/primary-email-check'
{ simple: false } )
expect(response.status).to.equal(302)
expect(response.headers.get('location')).to.equal(
UserHelper.url('/project').toString()
) )
expect(response.statusCode).to.equal(302)
expect(response.headers.location).to.equal('/project')
}) })
}) })
}) })

View file

@ -668,15 +668,14 @@ describe('ProjectDuplicateNames', function () {
}) })
it('should handle characters that would cause an invalid regular expression', async function () { it('should handle characters that would cause an invalid regular expression', async function () {
const projectName = 'Example (test' const projectName = 'Example (test'
response = await userHelper.request.post('/project/new', { response = await userHelper.fetch('/project/new', {
simple: false, method: 'POST',
form: { projectName }, body: new URLSearchParams([['projectName', projectName]]),
}) })
expect(response.statusCode).to.equal(200) // can create project const body = await response.json()
response = await userHelper.request.get( expect(response.status).to.equal(200) // can create project
`/project/${JSON.parse(response.body).project_id}` response = await userHelper.fetch(`/project/${body.project_id}`)
) expect(response.status).to.equal(200) // can open project
expect(response.statusCode).to.equal(200) // can open project
}) })
}) })
}) })

View file

@ -1,4 +1,5 @@
const { expect } = require('chai') const { expect } = require('chai')
const { CookieJar } = require('tough-cookie')
const AuthenticationManager = require('../../../../app/src/Features/Authentication/AuthenticationManager') const AuthenticationManager = require('../../../../app/src/Features/Authentication/AuthenticationManager')
const Settings = require('@overleaf/settings') const Settings = require('@overleaf/settings')
const InstitutionsAPI = require('../../../../app/src/Features/Institutions/InstitutionsAPI') const InstitutionsAPI = require('../../../../app/src/Features/Institutions/InstitutionsAPI')
@ -6,7 +7,7 @@ const UserCreator = require('../../../../app/src/Features/User/UserCreator')
const UserGetter = require('../../../../app/src/Features/User/UserGetter') const UserGetter = require('../../../../app/src/Features/User/UserGetter')
const UserUpdater = require('../../../../app/src/Features/User/UserUpdater') const UserUpdater = require('../../../../app/src/Features/User/UserUpdater')
const moment = require('moment') const moment = require('moment')
const request = require('request-promise-native') const fetch = require('node-fetch')
const { db } = require('../../../../app/src/infrastructure/mongodb') const { db } = require('../../../../app/src/infrastructure/mongodb')
const { ObjectId } = require('mongodb') const { ObjectId } = require('mongodb')
const { const {
@ -82,43 +83,33 @@ class UserHelper {
// used to store mongo user object once created/loaded // used to store mongo user object once created/loaded
this.user = null this.user = null
// cookie jar // cookie jar
this.jar = request.jar() this.jar = new CookieJar()
// create new request instance
this.request = request.defaults({})
// initialize request instance with default options
this.setRequestDefaults({
baseUrl: UserHelper.baseUrl(),
followRedirect: false,
jar: this.jar,
resolveWithFullResponse: true,
})
} }
/* Set defaults for request object. Applied over existing defaults. async fetch(url, opts = {}) {
* @param {object} [defaults] url = UserHelper.url(url)
*/ const headers = {}
setRequestDefaults(defaults = {}) { const cookieString = this.jar.getCookieStringSync(url)
// request-promise instance for making requests if (cookieString) {
this.request = this.request.defaults(defaults) headers.Cookie = cookieString
}
/**
* Make a request for the user and run expectations on the response.
* @param {object} [requestOptions] options to pass to request
* @param {object} [responseExpectations] expectations:
* - {Int} statusCode the expected status code
* - {RegEx} message a matcher for the message
*/
async expectErrorOnRequest(requestOptions, responseExpectations) {
let error
try {
await this.request(requestOptions)
} catch (e) {
error = e
} }
expect(error).to.exist if (this._csrfToken) {
expect(error.statusCode).to.equal(responseExpectations.statusCode) headers['x-csrf-token'] = this._csrfToken
expect(error.message).to.match(responseExpectations.message) }
const response = await fetch(url, {
redirect: 'manual',
...opts,
headers: { ...headers, ...opts.headers },
})
// From https://www.npmjs.com/package/node-fetch#extract-set-cookie-header
const cookies = response.headers.raw()['set-cookie']
if (cookies != null) {
for (const cookie of cookies) {
this.jar.setCookieSync(cookie, url)
}
}
return response
} }
/* async http api call methods */ /* async http api call methods */
@ -128,12 +119,8 @@ class UserHelper {
*/ */
async getCsrfToken() { async getCsrfToken() {
// get csrf token from api and store // get csrf token from api and store
const response = await this.request.get('/dev/csrf') const response = await this.fetch('/dev/csrf')
this._csrfToken = response.body this._csrfToken = await response.text()
// use csrf token for requests
this.setRequestDefaults({
headers: { 'x-csrf-token': this._csrfToken },
})
} }
/** /**
@ -142,13 +129,11 @@ class UserHelper {
* @returns {object} http response * @returns {object} http response
*/ */
async logout(options = {}) { async logout(options = {}) {
// do not throw exception on 302
options.simple = false
// post logout // post logout
const response = await this.request.post('/logout', options) const response = await this.fetch('/logout', { method: 'POST', ...options })
if ( if (
response.statusCode !== 302 || response.status !== 302 ||
!response.headers.location.includes('/login') !response.headers.get('location').includes('/login')
) { ) {
throw new Error('logout failed') throw new Error('logout failed')
} }
@ -168,6 +153,13 @@ class UserHelper {
return `http://${process.env.HTTP_TEST_HOST || 'localhost'}:23000` return `http://${process.env.HTTP_TEST_HOST || 'localhost'}:23000`
} }
/**
* Generates a full URL given a path
*/
static url(path) {
return new URL(path, UserHelper.baseUrl())
}
/* static async instantiation methods */ /* static async instantiation methods */
/** /**
@ -247,17 +239,30 @@ class UserHelper {
const userHelper = new UserHelper() const userHelper = new UserHelper()
const loginPath = Settings.enableLegacyLogin ? '/login/legacy' : '/login' const loginPath = Settings.enableLegacyLogin ? '/login/legacy' : '/login'
await userHelper.getCsrfToken() await userHelper.getCsrfToken()
const response = await userHelper.request.post(loginPath, { const response = await userHelper.fetch(loginPath, {
json: { method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
'g-recaptcha-response': 'valid', 'g-recaptcha-response': 'valid',
...userData, ...userData,
}, }),
}) })
if (response.statusCode !== 200 || response.body.redir !== '/project') { if (!response.ok) {
const error = new Error('login failed') const error = new Error('login failed')
error.response = response error.response = response
throw error throw error
} }
const body = await response.json()
if (body.redir !== '/project') {
const error = new Error('login failed')
error.response = response
throw error
}
userHelper.user = await UserGetter.promises.getUser({ userHelper.user = await UserGetter.promises.getUser({
email: userData.email, email: userData.email,
}) })
@ -274,10 +279,10 @@ class UserHelper {
* @returns {Boolean} * @returns {Boolean}
*/ */
async isLoggedIn() { async isLoggedIn() {
const response = await this.request.get('/user/sessions', { const response = await this.fetch('/user/sessions', {
followRedirect: true, redirect: 'follow',
}) })
return response.request.path === '/user/sessions' return !response.redirected
} }
/** /**
@ -292,8 +297,16 @@ class UserHelper {
const userHelper = new UserHelper() const userHelper = new UserHelper()
await userHelper.getCsrfToken() await userHelper.getCsrfToken()
userData = userHelper.getDefaultEmailPassword(userData) userData = userHelper.getDefaultEmailPassword(userData)
options.json = userData const response = await userHelper.fetch('/register', {
const { body } = await userHelper.request.post('/register', options) method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(userData),
...options,
})
const body = await response.json()
if (body.message && body.message.type === 'error') { if (body.message && body.message.type === 'error') {
throw new Error(`register api error: ${body.message.text}`) throw new Error(`register api error: ${body.message.text}`)
} }
@ -321,14 +334,11 @@ class UserHelper {
} }
async addEmail(email) { async addEmail(email) {
const response = await this.request.post({ const response = await this.fetch('/user/emails', {
form: { method: 'POST',
email, body: new URLSearchParams([['email', email]]),
},
simple: false,
uri: '/user/emails',
}) })
expect(response.statusCode).to.equal(204) expect(response.status).to.equal(204)
} }
async addEmailAndConfirm(userId, email) { async addEmailAndConfirm(userId, email) {
@ -393,16 +403,12 @@ class UserHelper {
} }
async confirmEmail(userId, email) { async confirmEmail(userId, email) {
let response
// UserHelper.createUser does not create a confirmation token // UserHelper.createUser does not create a confirmation token
response = await this.request.post({ let response = await this.fetch('/user/emails/resend_confirmation', {
form: { method: 'POST',
email, body: new URLSearchParams([['email', email]]),
},
simple: false,
uri: '/user/emails/resend_confirmation',
}) })
expect(response.statusCode).to.equal(200) expect(response.status).to.equal(200)
const tokenData = await db.tokens const tokenData = await db.tokens
.find({ .find({
use: 'email_confirmation', use: 'email_confirmation',
@ -411,14 +417,11 @@ class UserHelper {
usedAt: { $exists: false }, usedAt: { $exists: false },
}) })
.next() .next()
response = await this.request.post({ response = await this.fetch('/user/emails/confirm', {
form: { method: 'POST',
token: tokenData.token, body: new URLSearchParams([['token', tokenData.token]]),
},
simple: false,
uri: '/user/emails/confirm',
}) })
expect(response.statusCode).to.equal(200) expect(response.status).to.equal(200)
} }
} }