[web] Migrate some User and UserMembership files to ESM (#29181)
* Rename files to mjs * Migrate files to ESM * Fix imports * Misc. fixes: Fixup InsititutionsAPI import, ObjectId import, ... * Rename test files to mjs * Convert test files to ESM * Fix tests * Update UserMembershipErrors imports * Convert some tests: sinon -> vitest * Fixup UserMembershipHandler.test.mjs * Convert UserMembershipErrors to ESM GitOrigin-RevId: 05d34c7e112a567f9c59398740ae0830ef93d32f
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import { vi, expect } from 'vitest'
|
||||
import sinon from 'sinon'
|
||||
|
||||
const MODULE_PATH =
|
||||
'../../../../app/src/Features/User/UserOnboardingEmailManager'
|
||||
|
||||
describe('UserOnboardingEmailManager', function () {
|
||||
beforeEach(async function (ctx) {
|
||||
ctx.fakeUserId = '123abc'
|
||||
ctx.fakeUserEmail = 'frog@overleaf.com'
|
||||
ctx.onboardingEmailsQueue = {
|
||||
add: sinon.stub().resolves(),
|
||||
process: callback => {
|
||||
ctx.queueProcessFunction = callback
|
||||
},
|
||||
}
|
||||
ctx.Queues = {
|
||||
createScheduledJob: sinon.stub().resolves(),
|
||||
}
|
||||
ctx.UserGetter = {
|
||||
promises: {
|
||||
getUser: sinon.stub().resolves(null),
|
||||
},
|
||||
}
|
||||
ctx.UserGetter.promises.getUser.withArgs({ _id: ctx.fakeUserId }).resolves({
|
||||
_id: ctx.fakeUserId,
|
||||
email: ctx.fakeUserEmail,
|
||||
})
|
||||
ctx.EmailHandler = {
|
||||
promises: {
|
||||
sendEmail: sinon.stub().resolves(),
|
||||
},
|
||||
}
|
||||
ctx.UserUpdater = {
|
||||
promises: {
|
||||
updateUser: sinon.stub().resolves(),
|
||||
},
|
||||
}
|
||||
|
||||
vi.doMock('../../../../app/src/infrastructure/Queues', () => ({
|
||||
default: ctx.Queues,
|
||||
}))
|
||||
|
||||
vi.doMock('../../../../app/src/Features/Email/EmailHandler', () => ({
|
||||
default: ctx.EmailHandler,
|
||||
}))
|
||||
|
||||
vi.doMock('../../../../app/src/Features/User/UserGetter', () => ({
|
||||
default: ctx.UserGetter,
|
||||
}))
|
||||
|
||||
vi.doMock('../../../../app/src/Features/User/UserUpdater', () => ({
|
||||
default: ctx.UserUpdater,
|
||||
}))
|
||||
|
||||
vi.doMock('@overleaf/settings', () => ({
|
||||
default: (ctx.Settings = {
|
||||
enableOnboardingEmails: true,
|
||||
}),
|
||||
}))
|
||||
|
||||
ctx.UserOnboardingEmailManager = (await import(MODULE_PATH)).default
|
||||
})
|
||||
|
||||
describe('scheduleOnboardingEmail', function () {
|
||||
it('should schedule delayed job on queue', async function (ctx) {
|
||||
await ctx.UserOnboardingEmailManager.scheduleOnboardingEmail({
|
||||
_id: ctx.fakeUserId,
|
||||
})
|
||||
sinon.assert.calledWith(
|
||||
ctx.Queues.createScheduledJob,
|
||||
'emails-onboarding',
|
||||
{ data: { userId: ctx.fakeUserId } },
|
||||
24 * 60 * 60 * 1000
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('sendOnboardingEmail', function () {
|
||||
describe('when onboarding emails are disabled', function () {
|
||||
beforeEach(function (ctx) {
|
||||
ctx.Settings.enableOnboardingEmails = false
|
||||
})
|
||||
it('should not send onboarding email', async function (ctx) {
|
||||
await ctx.UserOnboardingEmailManager.sendOnboardingEmail(ctx.fakeUserId)
|
||||
expect(ctx.EmailHandler.promises.sendEmail).not.to.have.been.called
|
||||
expect(ctx.UserUpdater.promises.updateUser).not.to.have.been.called
|
||||
})
|
||||
})
|
||||
describe('when onboarding emails are enabled', function () {
|
||||
it('should send onboarding email and update user', async function (ctx) {
|
||||
await ctx.UserOnboardingEmailManager.sendOnboardingEmail(ctx.fakeUserId)
|
||||
expect(ctx.EmailHandler.promises.sendEmail).to.have.been.calledWith(
|
||||
'userOnboardingEmail',
|
||||
{
|
||||
to: ctx.fakeUserEmail,
|
||||
}
|
||||
)
|
||||
expect(ctx.UserUpdater.promises.updateUser).to.have.been.calledWith(
|
||||
ctx.fakeUserId,
|
||||
{ $set: { onboardingEmailSentAt: sinon.match.date } }
|
||||
)
|
||||
})
|
||||
|
||||
it('should stop if user is not found', async function (ctx) {
|
||||
await ctx.UserOnboardingEmailManager.sendOnboardingEmail({
|
||||
data: { userId: 'deleted-user' },
|
||||
})
|
||||
expect(ctx.EmailHandler.promises.sendEmail).not.to.have.been.called
|
||||
expect(ctx.UserUpdater.promises.updateUser).not.to.have.been.called
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,112 +0,0 @@
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const path = require('path')
|
||||
const sinon = require('sinon')
|
||||
const { expect } = require('chai')
|
||||
|
||||
const MODULE_PATH = path.join(
|
||||
__dirname,
|
||||
'../../../../app/src/Features/User/UserOnboardingEmailManager'
|
||||
)
|
||||
|
||||
describe('UserOnboardingEmailManager', function () {
|
||||
beforeEach(function () {
|
||||
this.fakeUserId = '123abc'
|
||||
this.fakeUserEmail = 'frog@overleaf.com'
|
||||
this.onboardingEmailsQueue = {
|
||||
add: sinon.stub().resolves(),
|
||||
process: callback => {
|
||||
this.queueProcessFunction = callback
|
||||
},
|
||||
}
|
||||
this.Queues = {
|
||||
createScheduledJob: sinon.stub().resolves(),
|
||||
}
|
||||
this.UserGetter = {
|
||||
promises: {
|
||||
getUser: sinon.stub().resolves(null),
|
||||
},
|
||||
}
|
||||
this.UserGetter.promises.getUser
|
||||
.withArgs({ _id: this.fakeUserId })
|
||||
.resolves({
|
||||
_id: this.fakeUserId,
|
||||
email: this.fakeUserEmail,
|
||||
})
|
||||
this.EmailHandler = {
|
||||
promises: {
|
||||
sendEmail: sinon.stub().resolves(),
|
||||
},
|
||||
}
|
||||
this.UserUpdater = {
|
||||
promises: {
|
||||
updateUser: sinon.stub().resolves(),
|
||||
},
|
||||
}
|
||||
|
||||
this.UserOnboardingEmailManager = SandboxedModule.require(MODULE_PATH, {
|
||||
requires: {
|
||||
'../../infrastructure/Queues': this.Queues,
|
||||
'../Email/EmailHandler': this.EmailHandler,
|
||||
'./UserGetter': this.UserGetter,
|
||||
'./UserUpdater': this.UserUpdater,
|
||||
'@overleaf/settings': (this.Settings = {
|
||||
enableOnboardingEmails: true,
|
||||
}),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('scheduleOnboardingEmail', function () {
|
||||
it('should schedule delayed job on queue', async function () {
|
||||
await this.UserOnboardingEmailManager.scheduleOnboardingEmail({
|
||||
_id: this.fakeUserId,
|
||||
})
|
||||
sinon.assert.calledWith(
|
||||
this.Queues.createScheduledJob,
|
||||
'emails-onboarding',
|
||||
{ data: { userId: this.fakeUserId } },
|
||||
24 * 60 * 60 * 1000
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('sendOnboardingEmail', function () {
|
||||
describe('when onboarding emails are disabled', function () {
|
||||
beforeEach(function () {
|
||||
this.Settings.enableOnboardingEmails = false
|
||||
})
|
||||
it('should not send onboarding email', async function () {
|
||||
await this.UserOnboardingEmailManager.sendOnboardingEmail(
|
||||
this.fakeUserId
|
||||
)
|
||||
expect(this.EmailHandler.promises.sendEmail).not.to.have.been.called
|
||||
expect(this.UserUpdater.promises.updateUser).not.to.have.been.called
|
||||
})
|
||||
})
|
||||
describe('when onboarding emails are enabled', function () {
|
||||
it('should send onboarding email and update user', async function () {
|
||||
await this.UserOnboardingEmailManager.sendOnboardingEmail(
|
||||
this.fakeUserId
|
||||
)
|
||||
expect(this.EmailHandler.promises.sendEmail).to.have.been.calledWith(
|
||||
'userOnboardingEmail',
|
||||
{
|
||||
to: this.fakeUserEmail,
|
||||
}
|
||||
)
|
||||
expect(this.UserUpdater.promises.updateUser).to.have.been.calledWith(
|
||||
this.fakeUserId,
|
||||
{ $set: { onboardingEmailSentAt: sinon.match.date } }
|
||||
)
|
||||
})
|
||||
|
||||
it('should stop if user is not found', async function () {
|
||||
await this.UserOnboardingEmailManager.sendOnboardingEmail({
|
||||
data: { userId: 'deleted-user' },
|
||||
})
|
||||
expect(this.EmailHandler.promises.sendEmail).not.to.have.been.called
|
||||
expect(this.UserUpdater.promises.updateUser).not.to.have.been.called
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,125 @@
|
||||
import { vi, expect } from 'vitest'
|
||||
import sinon from 'sinon'
|
||||
|
||||
const MODULE_PATH =
|
||||
'../../../../app/src/Features/User/UserPostRegistrationAnalyticsManager'
|
||||
|
||||
describe('UserPostRegistrationAnalyticsManager', function () {
|
||||
beforeEach(async function (ctx) {
|
||||
ctx.fakeUserId = '123abc'
|
||||
ctx.Queues = {
|
||||
createScheduledJob: sinon.stub().resolves(),
|
||||
}
|
||||
ctx.UserGetter = {
|
||||
promises: {
|
||||
getUser: sinon.stub().resolves(),
|
||||
},
|
||||
}
|
||||
ctx.UserGetter.promises.getUser
|
||||
.withArgs({ _id: ctx.fakeUserId })
|
||||
.resolves({ _id: ctx.fakeUserId })
|
||||
ctx.InstitutionsAPI = {
|
||||
promises: {
|
||||
getUserAffiliations: sinon.stub().resolves([]),
|
||||
},
|
||||
}
|
||||
ctx.AnalyticsManager = {
|
||||
setUserPropertyForUser: sinon.stub().resolves(),
|
||||
}
|
||||
|
||||
vi.doMock('../../../../app/src/infrastructure/Queues', () => ({
|
||||
default: ctx.Queues,
|
||||
}))
|
||||
|
||||
vi.doMock('../../../../app/src/Features/User/UserGetter', () => ({
|
||||
default: ctx.UserGetter,
|
||||
}))
|
||||
|
||||
vi.doMock(
|
||||
'../../../../app/src/Features/Institutions/InstitutionsAPI',
|
||||
() => ({
|
||||
default: ctx.InstitutionsAPI,
|
||||
})
|
||||
)
|
||||
|
||||
vi.doMock(
|
||||
'../../../../app/src/Features/Analytics/AnalyticsManager',
|
||||
() => ({
|
||||
default: ctx.AnalyticsManager,
|
||||
})
|
||||
)
|
||||
|
||||
ctx.UserPostRegistrationAnalyticsManager = (
|
||||
await import(MODULE_PATH)
|
||||
).default
|
||||
})
|
||||
|
||||
describe('schedulePostRegistrationAnalytics', function () {
|
||||
it('should schedule delayed job on queue', async function (ctx) {
|
||||
await ctx.UserPostRegistrationAnalyticsManager.schedulePostRegistrationAnalytics(
|
||||
{
|
||||
_id: ctx.fakeUserId,
|
||||
}
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
ctx.Queues.createScheduledJob,
|
||||
'post-registration-analytics',
|
||||
{ data: { userId: ctx.fakeUserId } },
|
||||
24 * 60 * 60 * 1000
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('postRegistrationAnalytics', function () {
|
||||
it('stops without errors if user is not found', async function (ctx) {
|
||||
await ctx.UserPostRegistrationAnalyticsManager.postRegistrationAnalytics(
|
||||
'not-a-user'
|
||||
)
|
||||
expect(ctx.InstitutionsAPI.promises.getUserAffiliations).not.to.have.been
|
||||
.called
|
||||
expect(ctx.AnalyticsManager.setUserPropertyForUser).not.to.have.been
|
||||
.called
|
||||
})
|
||||
|
||||
it('sets user property if user has commons account affiliationd', async function (ctx) {
|
||||
ctx.InstitutionsAPI.promises.getUserAffiliations.resolves([
|
||||
{},
|
||||
{
|
||||
institution: {
|
||||
commonsAccount: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
institution: {
|
||||
commonsAccount: false,
|
||||
},
|
||||
},
|
||||
])
|
||||
await ctx.UserPostRegistrationAnalyticsManager.postRegistrationAnalytics(
|
||||
ctx.fakeUserId
|
||||
)
|
||||
expect(
|
||||
ctx.AnalyticsManager.setUserPropertyForUser
|
||||
).to.have.been.calledWith(
|
||||
ctx.fakeUserId,
|
||||
'registered-from-commons-account',
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
it('does not set user property if user has no commons account affiliation', async function (ctx) {
|
||||
ctx.InstitutionsAPI.promises.getUserAffiliations.resolves([
|
||||
{
|
||||
institution: {
|
||||
commonsAccount: false,
|
||||
},
|
||||
},
|
||||
])
|
||||
await ctx.UserPostRegistrationAnalyticsManager.postRegistrationAnalytics(
|
||||
ctx.fakeUserId
|
||||
)
|
||||
expect(ctx.AnalyticsManager.setUserPropertyForUser).not.to.have.been
|
||||
.called
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,114 +0,0 @@
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const path = require('path')
|
||||
const sinon = require('sinon')
|
||||
const { expect } = require('chai')
|
||||
|
||||
const MODULE_PATH = path.join(
|
||||
__dirname,
|
||||
'../../../../app/src/Features/User/UserPostRegistrationAnalyticsManager'
|
||||
)
|
||||
|
||||
describe('UserPostRegistrationAnalyticsManager', function () {
|
||||
beforeEach(function () {
|
||||
this.fakeUserId = '123abc'
|
||||
this.Queues = {
|
||||
createScheduledJob: sinon.stub().resolves(),
|
||||
}
|
||||
this.UserGetter = {
|
||||
promises: {
|
||||
getUser: sinon.stub().resolves(),
|
||||
},
|
||||
}
|
||||
this.UserGetter.promises.getUser
|
||||
.withArgs({ _id: this.fakeUserId })
|
||||
.resolves({ _id: this.fakeUserId })
|
||||
this.InstitutionsAPI = {
|
||||
promises: {
|
||||
getUserAffiliations: sinon.stub().resolves([]),
|
||||
},
|
||||
}
|
||||
this.AnalyticsManager = {
|
||||
setUserPropertyForUser: sinon.stub().resolves(),
|
||||
}
|
||||
this.UserPostRegistrationAnalyticsManager = SandboxedModule.require(
|
||||
MODULE_PATH,
|
||||
{
|
||||
requires: {
|
||||
'../../infrastructure/Queues': this.Queues,
|
||||
'./UserGetter': this.UserGetter,
|
||||
'../Institutions/InstitutionsAPI': this.InstitutionsAPI,
|
||||
'../Analytics/AnalyticsManager': this.AnalyticsManager,
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
describe('schedulePostRegistrationAnalytics', function () {
|
||||
it('should schedule delayed job on queue', async function () {
|
||||
await this.UserPostRegistrationAnalyticsManager.schedulePostRegistrationAnalytics(
|
||||
{
|
||||
_id: this.fakeUserId,
|
||||
}
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
this.Queues.createScheduledJob,
|
||||
'post-registration-analytics',
|
||||
{ data: { userId: this.fakeUserId } },
|
||||
24 * 60 * 60 * 1000
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('postRegistrationAnalytics', function () {
|
||||
it('stops without errors if user is not found', async function () {
|
||||
await this.UserPostRegistrationAnalyticsManager.postRegistrationAnalytics(
|
||||
'not-a-user'
|
||||
)
|
||||
expect(this.InstitutionsAPI.promises.getUserAffiliations).not.to.have.been
|
||||
.called
|
||||
expect(this.AnalyticsManager.setUserPropertyForUser).not.to.have.been
|
||||
.called
|
||||
})
|
||||
|
||||
it('sets user property if user has commons account affiliationd', async function () {
|
||||
this.InstitutionsAPI.promises.getUserAffiliations.resolves([
|
||||
{},
|
||||
{
|
||||
institution: {
|
||||
commonsAccount: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
institution: {
|
||||
commonsAccount: false,
|
||||
},
|
||||
},
|
||||
])
|
||||
await this.UserPostRegistrationAnalyticsManager.postRegistrationAnalytics(
|
||||
this.fakeUserId
|
||||
)
|
||||
expect(
|
||||
this.AnalyticsManager.setUserPropertyForUser
|
||||
).to.have.been.calledWith(
|
||||
this.fakeUserId,
|
||||
'registered-from-commons-account',
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
it('does not set user property if user has no commons account affiliation', async function () {
|
||||
this.InstitutionsAPI.promises.getUserAffiliations.resolves([
|
||||
{
|
||||
institution: {
|
||||
commonsAccount: false,
|
||||
},
|
||||
},
|
||||
])
|
||||
await this.UserPostRegistrationAnalyticsManager.postRegistrationAnalytics(
|
||||
this.fakeUserId
|
||||
)
|
||||
expect(this.AnalyticsManager.setUserPropertyForUser).not.to.have.been
|
||||
.called
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user