2019-05-29 05:21:06 -04:00
const SandboxedModule = require ( 'sandboxed-module' )
const path = require ( 'path' )
const sinon = require ( 'sinon' )
const modulePath = path . join (
_ _dirname ,
'../../../../app/src/Features/User/UserUpdater'
)
const tk = require ( 'timekeeper' )
2020-02-20 11:08:40 -05:00
const { expect } = require ( 'chai' )
2020-10-06 06:31:34 -04:00
const { normalizeQuery } = require ( '../../../../app/src/Features/Helpers/Mongo' )
2019-05-29 05:21:06 -04:00
2021-04-14 09:17:21 -04:00
describe ( 'UserUpdater' , function ( ) {
beforeEach ( function ( ) {
2019-05-29 05:21:06 -04:00
tk . freeze ( Date . now ( ) )
2020-10-01 04:30:26 -04:00
this . mongodb = {
2019-05-29 05:21:06 -04:00
db : { } ,
ObjectId ( id ) {
return id
2021-04-27 03:52:58 -04:00
} ,
2019-05-29 05:21:06 -04:00
}
this . UserGetter = {
getUserEmail : sinon . stub ( ) ,
getUserByAnyEmail : sinon . stub ( ) ,
2020-08-12 10:18:45 -04:00
promises : {
2020-09-14 09:54:19 -04:00
ensureUniqueEmailAddress : sinon . stub ( ) ,
2021-04-27 03:52:58 -04:00
getUser : sinon . stub ( ) ,
2022-01-12 11:19:30 -05:00
getUserByMainEmail : sinon . stub ( ) ,
2022-04-14 05:18:15 -04:00
getUserFullEmails : sinon . stub ( ) ,
2021-04-27 03:52:58 -04:00
} ,
2019-05-29 05:21:06 -04:00
}
this . addAffiliation = sinon . stub ( ) . yields ( )
this . removeAffiliation = sinon . stub ( ) . callsArgWith ( 2 , null )
this . refreshFeatures = sinon . stub ( ) . yields ( )
2020-08-12 10:18:45 -04:00
this . NewsletterManager = {
promises : {
2021-04-27 03:52:58 -04:00
changeEmail : sinon . stub ( ) ,
} ,
2020-08-12 10:18:45 -04:00
}
this . RecurlyWrapper = {
promises : {
2021-04-27 03:52:58 -04:00
updateAccountEmailAddress : sinon . stub ( ) ,
} ,
2020-08-12 10:18:45 -04:00
}
2022-02-03 06:37:34 -05:00
this . AnalyticsManager = {
recordEventForUser : sinon . stub ( ) ,
}
2019-05-29 05:21:06 -04:00
this . UserUpdater = SandboxedModule . require ( modulePath , {
requires : {
2020-10-06 06:31:34 -04:00
'../Helpers/Mongo' : { normalizeQuery } ,
2020-10-01 04:30:26 -04:00
'../../infrastructure/mongodb' : this . mongodb ,
2020-10-30 04:10:50 -04:00
'@overleaf/metrics' : {
2021-04-27 03:52:58 -04:00
timeAsyncMethod : sinon . stub ( ) ,
2019-05-29 05:21:06 -04:00
} ,
'./UserGetter' : this . UserGetter ,
2020-09-14 09:54:19 -04:00
'../Institutions/InstitutionsAPI' : ( this . InstitutionsAPI = {
2019-05-29 05:21:06 -04:00
addAffiliation : this . addAffiliation ,
2020-09-14 09:54:19 -04:00
removeAffiliation : this . removeAffiliation ,
promises : {
2021-04-27 03:52:58 -04:00
addAffiliation : sinon . stub ( ) ,
2022-01-12 11:19:30 -05:00
removeAffiliation : sinon . stub ( ) ,
2021-04-27 03:52:58 -04:00
} ,
2020-09-14 09:54:19 -04:00
} ) ,
2020-08-12 10:19:55 -04:00
'../Email/EmailHandler' : ( this . EmailHandler = {
promises : {
2021-04-27 03:52:58 -04:00
sendEmail : sinon . stub ( ) ,
} ,
2020-08-12 10:19:55 -04:00
} ) ,
2020-02-20 11:08:40 -05:00
'../../infrastructure/Features' : ( this . Features = {
2021-04-27 03:52:58 -04:00
hasFeature : sinon . stub ( ) . returns ( false ) ,
2020-02-20 11:08:40 -05:00
} ) ,
2020-11-30 09:57:18 -05:00
'../Subscription/FeaturesUpdater' : ( this . FeaturesUpdater = {
refreshFeatures : this . refreshFeatures ,
promises : {
2021-04-27 03:52:58 -04:00
refreshFeatures : sinon . stub ( ) . resolves ( ) ,
} ,
2020-11-30 09:57:18 -05:00
} ) ,
2021-07-07 05:38:56 -04:00
'@overleaf/settings' : ( this . settings = { } ) ,
2019-05-29 05:21:06 -04:00
request : ( this . request = { } ) ,
2020-02-27 07:46:07 -05:00
'../Newsletter/NewsletterManager' : this . NewsletterManager ,
2020-08-12 10:19:33 -04:00
'../Subscription/RecurlyWrapper' : this . RecurlyWrapper ,
'./UserAuditLogHandler' : ( this . UserAuditLogHandler = {
promises : {
2021-04-27 03:52:58 -04:00
addEntry : sinon . stub ( ) . resolves ( ) ,
} ,
} ) ,
2022-02-03 06:37:34 -05:00
'../Analytics/AnalyticsManager' : this . AnalyticsManager ,
2021-04-27 03:52:58 -04:00
} ,
2019-05-29 05:21:06 -04:00
} )
2020-11-30 09:57:18 -05:00
this . stubbedUserEmail = 'hello@world.com'
2019-05-29 05:21:06 -04:00
this . stubbedUser = {
_id : '3131231' ,
name : 'bob' ,
2020-11-30 09:57:18 -05:00
email : this . stubbedUserEmail ,
emails : [
{
2021-04-27 03:52:58 -04:00
email : this . stubbedUserEmail ,
} ,
] ,
2019-05-29 05:21:06 -04:00
}
2019-07-22 12:55:35 -04:00
this . newEmail = 'bob@bob.com'
this . callback = sinon . stub ( )
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
afterEach ( function ( ) {
2019-08-07 10:04:04 -04:00
return tk . reset ( )
} )
2019-05-29 05:21:06 -04:00
2021-04-14 09:17:21 -04:00
describe ( 'addAffiliationForNewUser' , function ( done ) {
beforeEach ( function ( ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . updateUser = sinon
. stub ( )
2021-10-28 04:35:02 -04:00
. yields ( null , { matchedCount : 1 , modifiedCount : 1 } )
2020-02-20 11:08:40 -05:00
} )
2021-04-14 09:17:21 -04:00
it ( 'should not remove affiliationUnchecked flag if v1 returns an error' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . addAffiliation . yields ( true )
this . UserUpdater . addAffiliationForNewUser (
this . stubbedUser . _id ,
this . newEmail ,
( error , updated ) => {
expect ( error ) . to . exist
expect ( updated ) . to . be . undefined
sinon . assert . notCalled ( this . UserUpdater . updateUser )
done ( )
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'should remove affiliationUnchecked flag if v1 does not return an error' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . addAffiliation . yields ( )
this . UserUpdater . addAffiliationForNewUser (
this . stubbedUser . _id ,
this . newEmail ,
2020-08-11 05:35:08 -04:00
error => {
2021-03-31 08:20:55 -04:00
expect ( error ) . not . to . exist
2020-02-20 11:08:40 -05:00
sinon . assert . calledOnce ( this . UserUpdater . updateUser )
sinon . assert . calledWithMatch (
this . UserUpdater . updateUser ,
{ _id : this . stubbedUser . _id , 'emails.email' : this . newEmail } ,
{ $unset : { 'emails.$.affiliationUnchecked' : 1 } }
)
done ( )
}
)
} )
} )
2021-04-14 09:17:21 -04:00
describe ( 'changeEmailAddress' , function ( ) {
beforeEach ( function ( ) {
2020-08-12 10:19:33 -04:00
this . auditLog = {
initiatorId : 'abc123' ,
2021-04-27 03:52:58 -04:00
ipAddress : '0:0:0:0' ,
2020-08-12 10:19:33 -04:00
}
2019-05-29 05:21:06 -04:00
this . UserGetter . getUserEmail . callsArgWith ( 1 , null , this . stubbedUser . email )
2020-09-14 09:54:19 -04:00
this . UserUpdater . addEmailAddress = sinon . stub ( ) . callsArgWith ( 4 )
2019-07-22 12:55:35 -04:00
this . UserUpdater . setDefaultEmailAddress = sinon . stub ( ) . yields ( )
2020-02-20 11:08:40 -05:00
this . UserUpdater . removeEmailAddress = sinon . stub ( ) . callsArgWith ( 2 )
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'change email' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . changeEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2019-05-29 05:21:06 -04:00
this . UserUpdater . addEmailAddress
2020-09-14 09:54:19 -04:00
. calledWith ( this . stubbedUser . _id , this . newEmail , { } , this . auditLog )
2019-05-29 05:21:06 -04:00
. should . equal ( true )
this . UserUpdater . setDefaultEmailAddress
2020-08-12 10:19:55 -04:00
. calledWith (
this . stubbedUser . _id ,
this . newEmail ,
true ,
this . auditLog ,
true
)
2019-05-29 05:21:06 -04:00
. should . equal ( true )
this . UserUpdater . removeEmailAddress
. calledWith ( this . stubbedUser . _id , this . stubbedUser . email )
. should . equal ( true )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'validates email' , function ( done ) {
2020-08-12 10:19:33 -04:00
this . UserUpdater . changeEmailAddress (
this . stubbedUser . _id ,
'foo' ,
this . auditLog ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2020-08-12 10:19:33 -04:00
done ( )
}
)
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'handle error' , function ( done ) {
2019-05-29 05:21:06 -04:00
this . UserUpdater . removeEmailAddress . callsArgWith ( 2 , new Error ( 'nope' ) )
2020-02-20 11:08:40 -05:00
this . UserUpdater . changeEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
} )
2021-04-14 09:17:21 -04:00
describe ( 'addEmailAddress' , function ( ) {
beforeEach ( function ( ) {
2020-09-14 09:54:19 -04:00
this . UserGetter . promises . ensureUniqueEmailAddress = sinon
. stub ( )
. resolves ( )
this . UserUpdater . promises . updateUser = sinon . stub ( ) . resolves ( )
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'add email' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . addEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
2020-09-14 09:54:19 -04:00
{ } ,
{ initiatorId : this . stubbedUser . _id , ipAddress : '127:0:0:0' } ,
2019-05-29 05:21:06 -04:00
err => {
2020-09-14 09:54:19 -04:00
this . UserGetter . promises . ensureUniqueEmailAddress . called . should . equal (
true
)
expect ( err ) . to . not . exist
2019-05-29 05:21:06 -04:00
const reversedHostname = this . newEmail
. split ( '@' ) [ 1 ]
. split ( '' )
. reverse ( )
. join ( '' )
2020-09-14 09:54:19 -04:00
this . UserUpdater . promises . updateUser
2019-05-29 05:21:06 -04:00
. calledWith ( this . stubbedUser . _id , {
$push : {
emails : {
email : this . newEmail ,
createdAt : sinon . match . date ,
2021-04-27 03:52:58 -04:00
reversedHostname ,
} ,
} ,
2019-05-29 05:21:06 -04:00
} )
. should . equal ( true )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'add affiliation' , function ( done ) {
2019-05-29 05:21:06 -04:00
const affiliationOptions = {
university : { id : 1 } ,
role : 'Prof' ,
2021-04-27 03:52:58 -04:00
department : 'Math' ,
2019-05-29 05:21:06 -04:00
}
2020-02-20 11:08:40 -05:00
this . UserUpdater . addEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
affiliationOptions ,
2020-09-14 09:54:19 -04:00
{ initiatorId : this . stubbedUser . _id , ipAddress : '127:0:0:0' } ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2020-09-14 09:54:19 -04:00
this . InstitutionsAPI . promises . addAffiliation . calledOnce . should . equal (
true
)
const { args } = this . InstitutionsAPI . promises . addAffiliation . lastCall
2019-05-29 05:21:06 -04:00
args [ 0 ] . should . equal ( this . stubbedUser . _id )
args [ 1 ] . should . equal ( this . newEmail )
args [ 2 ] . should . equal ( affiliationOptions )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'handle affiliation error' , function ( done ) {
2020-09-14 09:54:19 -04:00
this . InstitutionsAPI . promises . addAffiliation . rejects ( new Error ( 'nope' ) )
2020-02-20 11:08:40 -05:00
this . UserUpdater . addEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
2020-09-14 09:54:19 -04:00
{ } ,
{ initiatorId : this . stubbedUser . _id , ipAddress : '127:0:0:0' } ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2020-09-14 09:54:19 -04:00
this . UserUpdater . promises . updateUser . called . should . equal ( false )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'validates email' , function ( done ) {
2020-09-14 09:54:19 -04:00
this . UserUpdater . addEmailAddress (
this . stubbedUser . _id ,
'bar' ,
{ } ,
{ initiatorId : this . stubbedUser . _id , ipAddress : '127:0:0:0' } ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2020-09-14 09:54:19 -04:00
done ( )
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'updates the audit log' , function ( done ) {
2020-09-14 09:54:19 -04:00
this . ip = '127:0:0:0'
this . UserUpdater . addEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
{ } ,
{ initiatorId : this . stubbedUser . _id , ipAddress : this . ip } ,
error => {
expect ( error ) . to . not . exist
this . InstitutionsAPI . promises . addAffiliation . calledOnce . should . equal (
true
)
const { args } = this . UserAuditLogHandler . promises . addEntry . lastCall
expect ( args [ 0 ] ) . to . equal ( this . stubbedUser . _id )
expect ( args [ 1 ] ) . to . equal ( 'add-email' )
expect ( args [ 2 ] ) . to . equal ( this . stubbedUser . _id )
expect ( args [ 3 ] ) . to . equal ( this . ip )
expect ( args [ 4 ] ) . to . deep . equal ( {
2021-04-27 03:52:58 -04:00
newSecondaryEmail : this . newEmail ,
2020-09-14 09:54:19 -04:00
} )
done ( )
}
)
} )
2021-04-14 09:17:21 -04:00
describe ( 'errors' , function ( ) {
describe ( 'via UserAuditLogHandler' , function ( ) {
2020-09-14 09:54:19 -04:00
const anError = new Error ( 'oops' )
2021-04-14 09:17:21 -04:00
beforeEach ( function ( ) {
2020-09-14 09:54:19 -04:00
this . UserAuditLogHandler . promises . addEntry . throws ( anError )
} )
2021-04-14 09:17:21 -04:00
it ( 'should not add email and should return error' , function ( done ) {
2020-09-14 09:54:19 -04:00
this . UserUpdater . addEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
{ } ,
{ initiatorId : this . stubbedUser . _id , ipAddress : '127:0:0:0' } ,
error => {
expect ( error ) . to . exist
expect ( error ) . to . equal ( anError )
expect ( this . UserUpdater . promises . updateUser ) . to . not . have . been
. called
done ( )
}
)
} )
2020-02-20 11:08:40 -05:00
} )
2019-05-29 05:21:06 -04:00
} )
} )
2021-04-14 09:17:21 -04:00
describe ( 'removeEmailAddress' , function ( ) {
beforeEach ( function ( ) {
2022-01-12 11:19:30 -05:00
this . UserUpdater . promises . updateUser = sinon
2019-05-29 05:21:06 -04:00
. stub ( )
2022-01-12 11:19:30 -05:00
. returns ( { matchedCount : 1 } )
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'remove email' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . removeEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2022-01-12 11:19:30 -05:00
this . UserUpdater . promises . updateUser
2019-05-29 05:21:06 -04:00
. calledWith (
{ _id : this . stubbedUser . _id , email : { $ne : this . newEmail } } ,
{ $pull : { emails : { email : this . newEmail } } }
)
. should . equal ( true )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'remove affiliation' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . removeEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2022-01-12 11:19:30 -05:00
this . InstitutionsAPI . promises . removeAffiliation . calledOnce . should . equal (
true
)
2022-01-12 11:40:54 -05:00
const { args } =
this . InstitutionsAPI . promises . removeAffiliation . lastCall
2019-05-29 05:21:06 -04:00
args [ 0 ] . should . equal ( this . stubbedUser . _id )
args [ 1 ] . should . equal ( this . newEmail )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'refresh features' , function ( done ) {
2020-06-04 04:47:02 -04:00
this . UserUpdater . removeEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2022-01-12 11:19:30 -05:00
sinon . assert . calledWith (
this . FeaturesUpdater . promises . refreshFeatures ,
this . stubbedUser . _id
)
2020-06-04 04:47:02 -04:00
done ( )
}
)
} )
2022-01-12 11:19:30 -05:00
it ( 'handle error from updateUser' , function ( done ) {
const anError = new Error ( 'nope' )
this . UserUpdater . promises . updateUser . rejects ( anError )
2019-05-29 05:21:06 -04:00
2020-02-20 11:08:40 -05:00
this . UserUpdater . removeEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2022-01-12 11:19:30 -05:00
expect ( err ) . to . deep . equal ( anError )
expect ( err . _oErrorTags [ 0 ] . message ) . to . equal (
'problem removing users email'
)
expect (
this . FeaturesUpdater . promises . refreshFeatures . callCount
) . to . equal ( 0 )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'handle missed update' , function ( done ) {
2022-01-12 11:19:30 -05:00
this . UserUpdater . promises . updateUser = sinon
2021-10-28 04:35:02 -04:00
. stub ( )
2022-01-12 11:19:30 -05:00
. returns ( { matchedCount : 0 } )
2019-05-29 05:21:06 -04:00
2020-02-20 11:08:40 -05:00
this . UserUpdater . removeEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2022-01-12 11:19:30 -05:00
expect ( err . message ) . to . equal ( 'Cannot remove email' )
expect (
this . FeaturesUpdater . promises . refreshFeatures . callCount
) . to . equal ( 0 )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'handle affiliation error' , function ( done ) {
2022-01-12 11:19:30 -05:00
const anError = new Error ( 'nope' )
this . InstitutionsAPI . promises . removeAffiliation . rejects ( anError )
this . UserUpdater . removeEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
err => {
expect ( err ) . to . exist
expect ( err ) . to . deep . equal ( anError )
this . UserUpdater . promises . updateUser . called . should . equal ( false )
expect (
this . FeaturesUpdater . promises . refreshFeatures . callCount
) . to . equal ( 0 )
done ( )
}
)
} )
it ( 'returns error when removing primary email' , function ( done ) {
this . UserGetter . promises . getUserByMainEmail = sinon
. stub ( )
. returns ( { _id : '123abc' } )
2020-02-20 11:08:40 -05:00
this . UserUpdater . removeEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2022-01-12 11:19:30 -05:00
expect ( err . message ) . to . deep . equal ( 'cannot remove primary email' )
expect ( this . UserUpdater . promises . updateUser . callCount ) . to . equal ( 0 )
expect (
this . FeaturesUpdater . promises . refreshFeatures . callCount
) . to . equal ( 0 )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'validates email' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . removeEmailAddress ( this . stubbedUser . _id , 'baz' , err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2022-01-12 11:19:30 -05:00
expect ( err . message ) . to . equal ( 'invalid email' )
2020-02-20 11:08:40 -05:00
done ( )
} )
2019-05-29 05:21:06 -04:00
} )
2022-01-12 11:19:30 -05:00
it ( 'skip email validation when skipParseEmail included' , function ( done ) {
const skipParseEmail = true
this . UserUpdater . removeEmailAddress (
this . stubbedUser . _id ,
'baz' ,
skipParseEmail ,
err => {
expect ( err ) . to . not . exist
done ( )
}
)
} )
it ( 'returns an error when skipParseEmail included but email is not a string' , function ( done ) {
const skipParseEmail = true
this . UserUpdater . removeEmailAddress (
this . stubbedUser . _id ,
1 ,
skipParseEmail ,
err => {
expect ( err ) . to . exist
expect ( err . message ) . to . equal ( 'email must be a string' )
done ( )
}
)
} )
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
describe ( 'setDefaultEmailAddress' , function ( ) {
2022-04-14 05:18:15 -04:00
function setStubbedUserEmails ( test , emails ) {
test . stubbedUser . emails = emails
test . UserGetter . promises . getUserFullEmails . resolves (
test . stubbedUser . emails
)
}
2021-04-14 09:17:21 -04:00
beforeEach ( function ( ) {
2020-08-12 10:19:33 -04:00
this . auditLog = {
initiatorId : this . stubbedUser ,
2021-04-27 03:52:58 -04:00
ipAddress : '0:0:0:0' ,
2020-08-12 10:19:33 -04:00
}
2022-04-14 05:18:15 -04:00
setStubbedUserEmails ( this , [
2019-07-22 12:55:35 -04:00
{
email : this . newEmail ,
2021-04-27 03:52:58 -04:00
confirmedAt : new Date ( ) ,
} ,
2022-04-14 05:18:15 -04:00
] )
2020-08-12 10:18:45 -04:00
this . UserGetter . promises . getUser . resolves ( this . stubbedUser )
this . NewsletterManager . promises . changeEmail . callsArgWith ( 2 , null )
this . RecurlyWrapper . promises . updateAccountEmailAddress . resolves ( )
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'set default' , function ( done ) {
2021-10-28 04:35:02 -04:00
this . UserUpdater . promises . updateUser = sinon
. stub ( )
. resolves ( { matchedCount : 1 } )
2019-05-29 05:21:06 -04:00
2019-07-22 12:55:35 -04:00
this . UserUpdater . setDefaultEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
2020-08-12 10:18:45 -04:00
false ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2020-08-12 10:18:45 -04:00
this . UserUpdater . promises . updateUser
2019-05-29 05:21:06 -04:00
. calledWith (
{ _id : this . stubbedUser . _id , 'emails.email' : this . newEmail } ,
2022-02-03 06:37:34 -05:00
{
$set : {
email : this . newEmail ,
lastPrimaryEmailCheck : sinon . match . date ,
} ,
}
2019-05-29 05:21:06 -04:00
)
. should . equal ( true )
2019-07-22 12:55:35 -04:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'set changed the email in newsletter' , function ( done ) {
2021-10-28 04:35:02 -04:00
this . UserUpdater . promises . updateUser = sinon
. stub ( )
. resolves ( { matchedCount : 1 } )
2019-05-29 05:21:06 -04:00
2019-07-22 12:55:35 -04:00
this . UserUpdater . setDefaultEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
2020-08-12 10:18:45 -04:00
false ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2020-08-12 10:18:45 -04:00
this . NewsletterManager . promises . changeEmail
2019-09-25 10:27:38 -04:00
. calledWith ( this . stubbedUser , this . newEmail )
2019-05-29 05:21:06 -04:00
. should . equal ( true )
2020-08-12 10:18:45 -04:00
this . RecurlyWrapper . promises . updateAccountEmailAddress
2020-02-27 07:46:07 -05:00
. calledWith ( this . stubbedUser . _id , this . newEmail )
. should . equal ( true )
2019-07-22 12:55:35 -04:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'handle error' , function ( done ) {
2020-08-12 10:18:45 -04:00
this . UserUpdater . promises . updateUser = sinon . stub ( ) . rejects ( Error ( 'nope' ) )
2019-05-29 05:21:06 -04:00
2019-07-22 12:55:35 -04:00
this . UserUpdater . setDefaultEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
2020-08-12 10:18:45 -04:00
false ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2019-07-22 12:55:35 -04:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'handle missed update' , function ( done ) {
2021-10-28 04:35:02 -04:00
this . UserUpdater . promises . updateUser = sinon
. stub ( )
. resolves ( { matchedCount : 0 } )
2019-05-29 05:21:06 -04:00
2019-07-22 12:55:35 -04:00
this . UserUpdater . setDefaultEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
2020-08-12 10:18:45 -04:00
false ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2019-07-22 12:55:35 -04:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'validates email' , function ( done ) {
2019-07-22 12:55:35 -04:00
this . UserUpdater . setDefaultEmailAddress (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
'.edu' ,
2020-08-12 10:18:45 -04:00
false ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2019-07-22 12:55:35 -04:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2019-07-22 12:55:35 -04:00
2021-04-14 09:17:21 -04:00
it ( 'updates audit log' , function ( done ) {
2021-10-28 04:35:02 -04:00
this . UserUpdater . promises . updateUser = sinon
. stub ( )
. resolves ( { matchedCount : 1 } )
2020-08-12 10:19:33 -04:00
this . UserUpdater . setDefaultEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
false ,
this . auditLog ,
error => {
expect ( error ) . to . not . exist
expect (
this . UserAuditLogHandler . promises . addEntry
) . to . have . been . calledWith (
this . stubbedUser . _id ,
'change-primary-email' ,
this . auditLog . initiatorId ,
this . auditLog . ipAddress ,
{
newPrimaryEmail : this . newEmail ,
2021-04-27 03:52:58 -04:00
oldPrimaryEmail : this . stubbedUser . email ,
2020-08-12 10:19:33 -04:00
}
)
done ( )
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'blocks email update if audit log returns an error' , function ( done ) {
2020-08-12 10:19:33 -04:00
this . UserUpdater . promises . updateUser = sinon . stub ( )
this . UserAuditLogHandler . promises . addEntry . rejects ( new Error ( 'oops' ) )
this . UserUpdater . setDefaultEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
false ,
this . auditLog ,
error => {
expect ( error ) . to . exist
expect ( this . UserUpdater . promises . updateUser ) . to . not . have . been . called
done ( )
}
)
} )
2021-04-14 09:17:21 -04:00
describe ( 'when email not confirmed' , function ( ) {
beforeEach ( function ( ) {
2022-04-14 05:18:15 -04:00
setStubbedUserEmails ( this , [
2019-07-22 12:55:35 -04:00
{
email : this . newEmail ,
2021-04-27 03:52:58 -04:00
confirmedAt : null ,
} ,
2022-04-14 05:18:15 -04:00
] )
2020-08-12 10:18:45 -04:00
this . UserUpdater . promises . updateUser = sinon . stub ( )
2019-07-22 12:55:35 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'should callback with error' , function ( ) {
2019-07-22 12:55:35 -04:00
this . UserUpdater . setDefaultEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
2020-08-12 10:18:45 -04:00
false ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2020-08-12 10:18:45 -04:00
error => {
expect ( error ) . to . exist
expect ( error . name ) . to . equal ( 'UnconfirmedEmailError' )
this . UserUpdater . promises . updateUser . callCount . should . equal ( 0 )
this . NewsletterManager . promises . changeEmail . callCount . should . equal (
0
)
}
2019-07-22 12:55:35 -04:00
)
} )
} )
2022-04-14 05:18:15 -04:00
describe ( 'securityAlertPrimaryEmailChangedExtraRecipients' , function ( ) {
it ( 'should be empty for unaffiliated user with single email' , function ( ) {
const recipients =
this . UserUpdater . securityAlertPrimaryEmailChangedExtraRecipients (
this . stubbedUser . emails ,
this . stubbedUser . email ,
this . newEmail
)
expect ( recipients ) . to . have . same . members ( [ ] )
} )
it ( 'should be most recently (re-)confirmed emails grouped by institution and by domain for unaffiliated emails as recipients' , function ( ) {
setStubbedUserEmails ( this , [
{
email : '1@a1.uni' ,
confirmedAt : new Date ( 2020 , 0 , 1 ) ,
reConfirmedAt : new Date ( 2021 , 2 , 11 ) ,
lastConfirmedAt : new Date ( 2021 , 2 , 11 ) ,
default : false ,
affiliation : {
institution : {
id : 123 ,
name : 'A1 University' ,
} ,
cachedConfirmedAt : '2020-01-01T18:25:01.639Z' ,
cachedReconfirmedAt : '2021-03-11T18:25:01.639Z' ,
} ,
} ,
{
email : '2@a1.uni' ,
confirmedAt : new Date ( 2019 , 0 , 1 ) ,
reConfirmedAt : new Date ( 2022 , 2 , 11 ) ,
lastConfirmedAt : new Date ( 2022 , 2 , 11 ) ,
default : false ,
affiliation : {
institution : {
id : 123 ,
name : 'A1 University' ,
} ,
cachedConfirmedAt : '2019-01-01T18:25:01.639Z' ,
cachedReconfirmedAt : '2022-03-11T18:25:01.639Z' ,
} ,
} ,
{
email : '2020@foo.bar' ,
confirmedAt : new Date ( 2020 , 6 , 1 ) ,
lastConfirmedAt : new Date ( 2020 , 6 , 1 ) ,
} ,
{
email : '2021@foo.bar' ,
confirmedAt : new Date ( 2021 , 6 , 1 ) ,
lastConfirmedAt : new Date ( 2021 , 6 , 1 ) ,
} ,
{
email : this . stubbedUser . email ,
confirmedAt : new Date ( 2021 , 6 , 1 ) ,
lastConfirmedAt : new Date ( 2021 , 6 , 1 ) ,
} ,
] )
const recipients =
this . UserUpdater . securityAlertPrimaryEmailChangedExtraRecipients (
this . stubbedUser . emails ,
this . stubbedUser . email ,
this . newEmail
)
expect ( recipients ) . to . have . same . members ( [ '2@a1.uni' , '2021@foo.bar' ] )
} )
it ( 'should be most recently (re-)confirmed emails grouped by institution and by domain for unaffiliated emails as recipients (multiple institutions and unaffiliated email domains)' , function ( ) {
setStubbedUserEmails ( this , [
{
email : '1@a1.uni' ,
confirmedAt : new Date ( 2020 , 0 , 1 ) ,
reConfirmedAt : new Date ( 2021 , 2 , 11 ) ,
lastConfirmedAt : new Date ( 2021 , 2 , 11 ) ,
default : false ,
affiliation : {
institution : {
id : 123 ,
name : 'A1 University' ,
} ,
cachedConfirmedAt : '2020-01-01T18:25:01.639Z' ,
cachedReconfirmedAt : '2021-03-11T18:25:01.639Z' ,
} ,
} ,
{
email : '1@b2.uni' ,
confirmedAt : new Date ( 2019 , 0 , 1 ) ,
reConfirmedAt : new Date ( 2022 , 2 , 11 ) ,
lastConfirmedAt : new Date ( 2022 , 2 , 11 ) ,
default : false ,
affiliation : {
institution : {
id : 234 ,
name : 'B2 University' ,
} ,
cachedConfirmedAt : '2019-01-01T18:25:01.639Z' ,
cachedReconfirmedAt : '2022-03-11T18:25:01.639Z' ,
} ,
} ,
{
email : '2020@foo.bar' ,
confirmedAt : new Date ( 2020 , 6 , 1 ) ,
lastConfirmedAt : new Date ( 2020 , 6 , 1 ) ,
} ,
{
email : '2021@bar.foo' ,
confirmedAt : new Date ( 2021 , 6 , 1 ) ,
lastConfirmedAt : new Date ( 2021 , 6 , 1 ) ,
} ,
{
email : this . stubbedUser . email ,
confirmedAt : new Date ( 2021 , 6 , 1 ) ,
lastConfirmedAt : new Date ( 2021 , 6 , 1 ) ,
} ,
] )
const recipients =
this . UserUpdater . securityAlertPrimaryEmailChangedExtraRecipients (
this . stubbedUser . emails ,
this . stubbedUser . email ,
this . newEmail
)
expect ( recipients ) . to . have . same . members ( [
'1@a1.uni' ,
'1@b2.uni' ,
'2020@foo.bar' ,
'2021@bar.foo' ,
] )
} )
} )
2021-04-14 09:17:21 -04:00
describe ( 'when email does not belong to user' , function ( ) {
beforeEach ( function ( ) {
2022-04-14 05:18:15 -04:00
setStubbedUserEmails ( this , [ ] )
2020-08-12 10:18:45 -04:00
this . UserGetter . promises . getUser . resolves ( this . stubbedUser )
this . UserUpdater . promises . updateUser = sinon . stub ( )
2019-07-22 12:55:35 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'should callback with error' , function ( ) {
2019-07-22 12:55:35 -04:00
this . UserUpdater . setDefaultEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
2020-08-12 10:18:45 -04:00
false ,
2020-08-12 10:19:33 -04:00
this . auditLog ,
2020-08-12 10:18:45 -04:00
error => {
expect ( error ) . to . exist
expect ( error . name ) . to . equal ( 'Error' )
this . UserUpdater . promises . updateUser . callCount . should . equal ( 0 )
this . NewsletterManager . promises . changeEmail . callCount . should . equal (
0
)
}
2019-07-22 12:55:35 -04:00
)
} )
} )
2020-08-12 10:19:55 -04:00
2021-04-14 09:17:21 -04:00
describe ( 'security alert' , function ( ) {
it ( 'should be sent to old and new email when sendSecurityAlert=true' , function ( done ) {
2020-08-12 10:19:55 -04:00
// this.UserGetter.promises.getUser.resolves(this.stubbedUser)
2021-10-28 04:35:02 -04:00
this . UserUpdater . promises . updateUser = sinon
. stub ( )
. resolves ( { matchedCount : 1 } )
2020-08-12 10:19:55 -04:00
this . UserUpdater . setDefaultEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
false ,
this . auditLog ,
true ,
error => {
expect ( error ) . to . not . exist
this . EmailHandler . promises . sendEmail . callCount . should . equal ( 2 )
2022-01-10 05:23:05 -05:00
const toOldEmailAlert =
this . EmailHandler . promises . sendEmail . firstCall
2020-08-12 10:19:55 -04:00
expect ( toOldEmailAlert . args [ 0 ] ) . to . equal ( 'securityAlert' )
2022-01-10 05:23:05 -05:00
const toNewEmailAlert =
this . EmailHandler . promises . sendEmail . lastCall
2020-08-12 10:19:55 -04:00
expect ( toOldEmailAlert . args [ 1 ] . to ) . to . equal ( this . stubbedUser . email )
expect ( toNewEmailAlert . args [ 0 ] ) . to . equal ( 'securityAlert' )
expect ( toNewEmailAlert . args [ 1 ] . to ) . to . equal ( this . newEmail )
done ( )
}
)
} )
2021-04-14 09:17:21 -04:00
describe ( 'errors' , function ( ) {
2020-09-29 10:05:12 -04:00
const anError = new Error ( 'oops' )
2021-04-14 09:17:21 -04:00
describe ( 'EmailHandler' , function ( ) {
beforeEach ( function ( ) {
2020-09-29 10:05:12 -04:00
this . EmailHandler . promises . sendEmail . rejects ( anError )
this . UserUpdater . promises . updateUser = sinon
. stub ( )
2021-10-28 04:35:02 -04:00
. resolves ( { matchedCount : 1 } )
2020-09-29 10:05:12 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'should log but not pass back the error' , function ( done ) {
2020-09-29 10:05:12 -04:00
this . UserUpdater . setDefaultEmailAddress (
this . stubbedUser . _id ,
this . newEmail ,
false ,
this . auditLog ,
true ,
error => {
expect ( error ) . to . not . exist
const loggerCall = this . logger . error . firstCall
expect ( loggerCall . args [ 0 ] ) . to . deep . equal ( {
error : anError ,
2021-04-27 03:52:58 -04:00
userId : this . stubbedUser . _id ,
2020-09-29 10:05:12 -04:00
} )
expect ( loggerCall . args [ 1 ] ) . to . contain (
'could not send security alert email when primary email changed'
)
done ( )
}
)
} )
} )
} )
2020-08-12 10:19:55 -04:00
} )
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
describe ( 'confirmEmail' , function ( ) {
beforeEach ( function ( ) {
2021-10-28 04:35:02 -04:00
this . UserUpdater . promises . updateUser = sinon
. stub ( )
. resolves ( { matchedCount : 1 } )
2019-05-29 05:21:06 -04:00
} )
2021-04-14 09:17:21 -04:00
it ( 'should update the email record' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . confirmEmail (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
2020-11-30 09:57:18 -05:00
this . stubbedUserEmail ,
2019-05-29 05:21:06 -04:00
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2020-11-30 09:57:18 -05:00
this . UserUpdater . promises . updateUser
2019-05-29 05:21:06 -04:00
. calledWith (
2020-11-30 09:57:18 -05:00
{
_id : this . stubbedUser . _id ,
2021-04-27 03:52:58 -04:00
'emails.email' : this . stubbedUserEmail ,
2020-11-30 09:57:18 -05:00
} ,
{
$set : {
2021-04-27 03:52:58 -04:00
'emails.$.reconfirmedAt' : new Date ( ) ,
2021-01-07 09:21:54 -05:00
} ,
$min : {
2021-04-27 03:52:58 -04:00
'emails.$.confirmedAt' : new Date ( ) ,
} ,
2020-11-30 09:57:18 -05:00
}
2019-05-29 05:21:06 -04:00
)
. should . equal ( true )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'add affiliation' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . confirmEmail (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2020-11-30 09:57:18 -05:00
this . InstitutionsAPI . promises . addAffiliation . calledOnce . should . equal (
true
)
2019-05-29 05:21:06 -04:00
sinon . assert . calledWith (
2020-11-30 09:57:18 -05:00
this . InstitutionsAPI . promises . addAffiliation ,
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
{ confirmedAt : new Date ( ) }
)
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'handle error' , function ( done ) {
2020-11-30 09:57:18 -05:00
this . UserUpdater . promises . updateUser = sinon
2019-05-29 05:21:06 -04:00
. stub ( )
2020-11-30 09:57:18 -05:00
. throws ( new Error ( 'nope' ) )
2019-05-29 05:21:06 -04:00
2020-02-20 11:08:40 -05:00
this . UserUpdater . confirmEmail (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'handle missed update' , function ( done ) {
2021-10-28 04:35:02 -04:00
this . UserUpdater . promises . updateUser = sinon
. stub ( )
. resolves ( { matchedCount : 0 } )
2019-05-29 05:21:06 -04:00
2020-02-20 11:08:40 -05:00
this . UserUpdater . confirmEmail (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'validates email' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . confirmEmail ( this . stubbedUser . _id , '@' , err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
} )
} )
2021-04-14 09:17:21 -04:00
it ( 'handle affiliation error' , function ( done ) {
2020-11-30 09:57:18 -05:00
this . InstitutionsAPI . promises . addAffiliation . throws ( Error ( 'nope' ) )
2020-02-20 11:08:40 -05:00
this . UserUpdater . confirmEmail (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . to . exist
2020-11-30 09:57:18 -05:00
this . UserUpdater . promises . updateUser . called . should . equal ( false )
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
2021-04-14 09:17:21 -04:00
it ( 'refresh features' , function ( done ) {
2020-02-20 11:08:40 -05:00
this . UserUpdater . confirmEmail (
2019-05-29 05:21:06 -04:00
this . stubbedUser . _id ,
this . newEmail ,
err => {
2021-03-31 08:20:55 -04:00
expect ( err ) . not . to . exist
2020-11-30 09:57:18 -05:00
sinon . assert . calledWith (
this . FeaturesUpdater . promises . refreshFeatures ,
this . stubbedUser . _id
)
2020-02-20 11:08:40 -05:00
done ( )
2019-05-29 05:21:06 -04:00
}
)
} )
} )
} )