mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-01 21:31:36 +02:00
278 lines
7.3 KiB
JavaScript
278 lines
7.3 KiB
JavaScript
import { expect, vi } from 'vitest'
|
|
import sinon from 'sinon'
|
|
|
|
const modulePath =
|
|
'../../../../app/src/Features/Subscription/TeamInvitesController'
|
|
|
|
describe('TeamInvitesController', function () {
|
|
beforeEach(async function (ctx) {
|
|
ctx.user = { _id: '!@312431', email: 'user@email.com' }
|
|
ctx.adminUserId = '123jlkj'
|
|
ctx.subscriptionId = '123434325412'
|
|
ctx.user_email = 'bob@gmail.com'
|
|
ctx.req = {
|
|
session: {
|
|
user: {
|
|
_id: ctx.adminUserId,
|
|
email: ctx.user_email,
|
|
},
|
|
},
|
|
params: {},
|
|
query: {},
|
|
ip: '0.0.0.0',
|
|
}
|
|
|
|
ctx.subscription = {
|
|
_id: ctx.subscriptionId,
|
|
}
|
|
|
|
ctx.TeamInvitesHandler = {
|
|
promises: {
|
|
acceptInvite: sinon.stub().resolves(ctx.subscription),
|
|
getInvite: sinon.stub().resolves({
|
|
invite: {
|
|
email: ctx.user.email,
|
|
token: 'token123',
|
|
inviterName: ctx.user_email,
|
|
},
|
|
subscription: ctx.subscription,
|
|
}),
|
|
},
|
|
}
|
|
|
|
ctx.SubscriptionLocator = {
|
|
promises: {
|
|
hasSSOEnabled: sinon.stub().resolves(true),
|
|
getUsersSubscription: sinon.stub().resolves(),
|
|
},
|
|
}
|
|
ctx.ErrorController = { notFound: sinon.stub() }
|
|
|
|
ctx.SessionManager = {
|
|
getLoggedInUserId(session) {
|
|
return session.user?._id
|
|
},
|
|
getSessionUser(session) {
|
|
return session.user
|
|
},
|
|
}
|
|
|
|
ctx.UserAuditLogHandler = {
|
|
promises: {
|
|
addEntry: sinon.stub().resolves(),
|
|
},
|
|
}
|
|
ctx.UserGetter = {
|
|
promises: {
|
|
getUser: sinon.stub().resolves(ctx.user),
|
|
getUserByMainEmail: sinon.stub().resolves(ctx.user),
|
|
getUserByAnyEmail: sinon.stub().resolves(ctx.user),
|
|
},
|
|
}
|
|
ctx.EmailHandler = {
|
|
sendDeferredEmail: sinon.stub().resolves(),
|
|
}
|
|
|
|
ctx.RateLimiter = {
|
|
RateLimiter: class {},
|
|
}
|
|
|
|
vi.doMock(
|
|
'../../../../app/src/Features/Subscription/TeamInvitesHandler',
|
|
() => ({
|
|
default: ctx.TeamInvitesHandler,
|
|
})
|
|
)
|
|
|
|
vi.doMock(
|
|
'../../../../app/src/Features/Authentication/SessionManager',
|
|
() => ({
|
|
default: ctx.SessionManager,
|
|
})
|
|
)
|
|
|
|
vi.doMock(
|
|
'../../../../app/src/Features/Subscription/SubscriptionLocator',
|
|
() => ({
|
|
default: ctx.SubscriptionLocator,
|
|
})
|
|
)
|
|
|
|
vi.doMock('../../../../app/src/Features/User/UserAuditLogHandler', () => ({
|
|
default: ctx.UserAuditLogHandler,
|
|
}))
|
|
|
|
vi.doMock('../../../../app/src/Features/Errors/ErrorController', () => ({
|
|
default: ctx.ErrorController,
|
|
}))
|
|
|
|
vi.doMock('../../../../app/src/Features/User/UserGetter', () => ({
|
|
default: ctx.UserGetter,
|
|
}))
|
|
|
|
vi.doMock('../../../../app/src/Features/Email/EmailHandler', () => ({
|
|
default: ctx.EmailHandler,
|
|
}))
|
|
|
|
vi.doMock(
|
|
'../../../../app/src/infrastructure/RateLimiter',
|
|
() => ctx.RateLimiter
|
|
)
|
|
|
|
vi.doMock('../../../../app/src/infrastructure/Modules', () => ({
|
|
default: (ctx.Modules = {
|
|
promises: {
|
|
hooks: {
|
|
fire: sinon.stub().resolves([]),
|
|
},
|
|
},
|
|
}),
|
|
}))
|
|
|
|
vi.doMock(
|
|
'../../../../app/src/Features/SplitTests/SplitTestHandler',
|
|
() => ({
|
|
default: (ctx.SplitTestHandler = {
|
|
promises: {
|
|
getAssignment: sinon.stub().resolves({}),
|
|
},
|
|
}),
|
|
})
|
|
)
|
|
|
|
ctx.Controller = (await import(modulePath)).default
|
|
})
|
|
|
|
describe('acceptInvite', function () {
|
|
it('should add an audit log entry', async function (ctx) {
|
|
await new Promise(resolve => {
|
|
ctx.req.params.token = 'foo'
|
|
ctx.req.session.user = ctx.user
|
|
const res = {
|
|
json: () => {
|
|
sinon.assert.calledWith(
|
|
ctx.UserAuditLogHandler.promises.addEntry,
|
|
ctx.user._id,
|
|
'accept-group-invitation',
|
|
ctx.user._id,
|
|
ctx.req.ip,
|
|
{ subscriptionId: ctx.subscriptionId }
|
|
)
|
|
resolve()
|
|
},
|
|
}
|
|
ctx.Controller.acceptInvite(ctx.req, res)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('viewInvite', function () {
|
|
const req = {
|
|
params: { token: 'token123' },
|
|
query: {},
|
|
session: {
|
|
user: { _id: 'user123' },
|
|
},
|
|
}
|
|
|
|
describe('hasIndividualPaidSubscription', function () {
|
|
it('is true for personal subscription', async function (ctx) {
|
|
await new Promise(resolve => {
|
|
ctx.SubscriptionLocator.promises.getUsersSubscription.resolves({
|
|
recurlySubscription_id: 'subscription123',
|
|
groupPlan: false,
|
|
})
|
|
const res = {
|
|
render: (template, data) => {
|
|
expect(data.hasIndividualPaidSubscription).to.be.true
|
|
resolve()
|
|
},
|
|
}
|
|
ctx.Controller.viewInvite(req, res)
|
|
})
|
|
})
|
|
|
|
it('is true for group subscriptions', async function (ctx) {
|
|
await new Promise(resolve => {
|
|
ctx.SubscriptionLocator.promises.getUsersSubscription.resolves({
|
|
recurlySubscription_id: 'subscription123',
|
|
groupPlan: true,
|
|
})
|
|
const res = {
|
|
render: (template, data) => {
|
|
expect(data.hasIndividualPaidSubscription).to.be.false
|
|
resolve()
|
|
},
|
|
}
|
|
ctx.Controller.viewInvite(req, res)
|
|
})
|
|
})
|
|
|
|
it('is false for canceled subscriptions', async function (ctx) {
|
|
await new Promise(resolve => {
|
|
ctx.SubscriptionLocator.promises.getUsersSubscription.resolves({
|
|
recurlySubscription_id: 'subscription123',
|
|
groupPlan: false,
|
|
recurlyStatus: {
|
|
state: 'canceled',
|
|
},
|
|
})
|
|
const res = {
|
|
render: (template, data) => {
|
|
expect(data.hasIndividualPaidSubscription).to.be.false
|
|
resolve()
|
|
},
|
|
}
|
|
ctx.Controller.viewInvite(req, res)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('when user is logged out', function () {
|
|
it('renders logged out invite page', async function (ctx) {
|
|
await new Promise(resolve => {
|
|
const res = {
|
|
render: (template, data) => {
|
|
expect(template).to.equal('subscriptions/team/invite_logged_out')
|
|
expect(data.groupSSOActive).to.be.undefined
|
|
resolve()
|
|
},
|
|
}
|
|
ctx.Controller.viewInvite(
|
|
{ params: { token: 'token123' }, session: {} },
|
|
res
|
|
)
|
|
})
|
|
})
|
|
|
|
it('includes groupSSOActive flag when the group has SSO enabled', async function (ctx) {
|
|
await new Promise(resolve => {
|
|
ctx.Modules.promises.hooks.fire = sinon.stub().resolves([true])
|
|
const res = {
|
|
render: (template, data) => {
|
|
expect(data.groupSSOActive).to.be.true
|
|
resolve()
|
|
},
|
|
}
|
|
ctx.Controller.viewInvite(
|
|
{ params: { token: 'token123' }, session: {} },
|
|
res
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
it('renders the view', async function (ctx) {
|
|
await new Promise(resolve => {
|
|
const res = {
|
|
render: template => {
|
|
expect(template).to.equal('subscriptions/team/invite')
|
|
resolve()
|
|
},
|
|
}
|
|
ctx.Controller.viewInvite(req, res)
|
|
})
|
|
})
|
|
})
|
|
})
|