mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 21:23:45 +01:00
Merge pull request #35936 from overleaf/ii-workspaces-subscription-admin-settings
Shared Workspace settings for subscription admins GitOrigin-RevId: 61cc45a48aaf1709905e98b3cccf09b50e2afa84
This commit is contained in:
@@ -1300,6 +1300,88 @@ templates.groupAiFeaturesEnabled = NoCTAEmailTemplate({
|
||||
},
|
||||
})
|
||||
|
||||
templates.groupSharedWorkspaceDisabledForOwner = ctaTemplate({
|
||||
subject() {
|
||||
return `Your shared workspace has been disabled`
|
||||
},
|
||||
title() {
|
||||
return `Your projects are back in your personal list.`
|
||||
},
|
||||
greeting(opts) {
|
||||
return opts.firstName ? `Hi ${opts.firstName},` : 'Hi there,'
|
||||
},
|
||||
message(opts) {
|
||||
const groupName = _.escape(opts.groupName)
|
||||
return [
|
||||
`Your group administrator has disabled the shared workspace for ${groupName}.`,
|
||||
`Projects you owned in the workspace have been returned to your personal projects list. They’re no longer visible to the whole group — only collaborators you’d actively shared them with still have access.`,
|
||||
`You don’t need to do anything. You can find your projects in your projects list as usual.`,
|
||||
]
|
||||
},
|
||||
ctaText() {
|
||||
return 'Open your projects'
|
||||
},
|
||||
ctaURL() {
|
||||
return `${settings.siteUrl}/project`
|
||||
},
|
||||
})
|
||||
|
||||
templates.groupSharedWorkspaceDisabledForMember = ctaTemplate({
|
||||
subject() {
|
||||
return `Your group's shared workspace has been disabled`
|
||||
},
|
||||
title() {
|
||||
return `Here's what's changed for your group.`
|
||||
},
|
||||
greeting(opts) {
|
||||
return opts.firstName ? `Hi ${opts.firstName},` : 'Hi there,'
|
||||
},
|
||||
message(opts) {
|
||||
const groupName = _.escape(opts.groupName)
|
||||
return [
|
||||
`Your group administrator has disabled the shared workspace for ${groupName}.`,
|
||||
`Projects that were in the shared workspace have been returned to their owners. You’ll still have access to any projects their owners have shared with you directly — but projects you could only see through the shared workspace may no longer be visible.`,
|
||||
`You don’t need to do anything. If you’re not sure whether you still have access to a project, check with the project owner or your group administrator.`,
|
||||
]
|
||||
},
|
||||
ctaText() {
|
||||
return 'Open your projects'
|
||||
},
|
||||
ctaURL() {
|
||||
return `${settings.siteUrl}/project`
|
||||
},
|
||||
})
|
||||
|
||||
templates.groupSharedWorkspaceDisabledForAdmin = ctaTemplate({
|
||||
subject(opts) {
|
||||
return `Shared workspace disabled for ${opts.groupName}`
|
||||
},
|
||||
title() {
|
||||
return `Here's a summary of what changed for your group.`
|
||||
},
|
||||
greeting(opts) {
|
||||
return opts.firstName ? `Hi ${opts.firstName},` : 'Hi there,'
|
||||
},
|
||||
message(opts) {
|
||||
const groupName = _.escape(opts.groupName)
|
||||
return [
|
||||
`You’ve disabled the shared workspace for ${groupName}. Here's a summary of what happened.`,
|
||||
'<ul>' +
|
||||
'<li>Projects in the workspace have been returned to their owners and are no longer visible to the whole group.</li>' +
|
||||
'<li>Each project is now shared only with the collaborators the owner had already added.</li>' +
|
||||
'<li>Group members have been notified of the change.</li>' +
|
||||
'</ul>',
|
||||
`No further action is needed on your part.`,
|
||||
]
|
||||
},
|
||||
ctaText() {
|
||||
return 'Open your projects'
|
||||
},
|
||||
ctaURL() {
|
||||
return `${settings.siteUrl}/project`
|
||||
},
|
||||
})
|
||||
|
||||
templates.groupDomainCapturedByGroupChanged = ctaTemplate({
|
||||
subject(opts) {
|
||||
return opts.domainCapturedByGroup
|
||||
|
||||
@@ -186,6 +186,7 @@ async function userSubscriptionPage(req, res) {
|
||||
'group-discount-10'
|
||||
)
|
||||
await SplitTestHandler.promises.getAssignment(req, res, 'ai-toggling')
|
||||
await SplitTestHandler.promises.getAssignment(req, res, 'shared-workspace')
|
||||
await SplitTestHandler.promises.getAssignment(
|
||||
req,
|
||||
res,
|
||||
|
||||
@@ -30,6 +30,9 @@ export const GroupPolicySchema = new Schema(
|
||||
|
||||
// User can't use the Dropbox feature
|
||||
userCannotUseDropbox: Boolean,
|
||||
|
||||
// User can't use the shared workspace feature
|
||||
userCannotUseSharedWorkspace: Boolean,
|
||||
},
|
||||
{ minimize: false }
|
||||
)
|
||||
|
||||
@@ -499,9 +499,13 @@
|
||||
"disable_equation_preview": "",
|
||||
"disable_equation_preview_confirm": "",
|
||||
"disable_equation_preview_enable_in_settings": "",
|
||||
"disable_shared_workspace": "",
|
||||
"disable_shared_workspace_modal_body": "",
|
||||
"disable_shared_workspace_modal_title": "",
|
||||
"disable_single_sign_on": "",
|
||||
"disable_sso": "",
|
||||
"disable_stop_on_first_error": "",
|
||||
"disable_workspace": "",
|
||||
"disabled": "",
|
||||
"disabling": "",
|
||||
"disagree": "",
|
||||
@@ -645,8 +649,12 @@
|
||||
"enable": "",
|
||||
"enable_ai_features": "",
|
||||
"enable_managed_users": "",
|
||||
"enable_shared_workspace": "",
|
||||
"enable_shared_workspace_modal_body": "",
|
||||
"enable_shared_workspace_modal_title": "",
|
||||
"enable_single_sign_on": "",
|
||||
"enable_sso": "",
|
||||
"enable_workspace": "",
|
||||
"enabled": "",
|
||||
"enables_real_time_syntax_checking_in_the_editor": "",
|
||||
"enabling": "",
|
||||
@@ -1896,6 +1904,12 @@
|
||||
"share_project": "",
|
||||
"share_project_name": "",
|
||||
"shared_with_you": "",
|
||||
"shared_workspace": "",
|
||||
"shared_workspace_failed_to_disable": "",
|
||||
"shared_workspace_failed_to_enable": "",
|
||||
"shared_workspace_is_enabled": "",
|
||||
"shared_workspace_managed_by_overleaf_support": "",
|
||||
"shared_workspace_section_subtext": "",
|
||||
"sharelatex_beta_program": "",
|
||||
"sharing_permissions": "",
|
||||
"shortcut_to_open_advanced_reference_search": "",
|
||||
|
||||
+12
-5
@@ -100,6 +100,7 @@ export default function ManagedGroupSubscriptions() {
|
||||
const isSharingPermissionsEnabled = useFeatureFlag(
|
||||
'sharing-updates-sharing-permissions'
|
||||
)
|
||||
const isSharedWorkspaceEnabled = useFeatureFlag('shared-workspace')
|
||||
const aiTogglingSplitTestEnabled = useFeatureFlag('ai-toggling')
|
||||
|
||||
if (!managedGroupSubscriptions) {
|
||||
@@ -115,12 +116,18 @@ export default function ManagedGroupSubscriptions() {
|
||||
{managedGroupSubscriptions.map(subscription => {
|
||||
const isAdmin = usersEmail === subscription.admin_id.email
|
||||
|
||||
// Feature controls are currently rendered only for managed groups, where the admin can
|
||||
// toggle AI Feature on/off. For non-managed groups, the section only displays notifications
|
||||
// for features that have been disabled by Overleaf Support. When the `ai-toggling` split
|
||||
// test is enabled, it's always displayed for non-managed groups that have the feature on.
|
||||
// This flag will be deleted once AI Features toggling is available to all groups.
|
||||
// Shared Workspace is available to both managed and non-managed groups, so while the
|
||||
// `shared-workspace` split test has the group opted in, the section is rendered whenever
|
||||
// Overleaf Support hasn't disabled the feature for them.
|
||||
// AI Features toggling is narrower: it's only interactive for managed groups, so for
|
||||
// non-managed groups the section falls back to displaying notifications for features that
|
||||
// have been disabled by Overleaf Support. When the `ai-toggling` split test is enabled,
|
||||
// it's also displayed for non-managed groups that have the feature on. Both flags will be
|
||||
// deleted once their features are available to all groups.
|
||||
const shouldDisplayFeatureControls =
|
||||
(isSharedWorkspaceEnabled &&
|
||||
subscription.planLevelName === 'Pro' &&
|
||||
subscription.features?.sharedWorkspace !== false) ||
|
||||
(subscription.features?.aiToggling && aiTogglingSplitTestEnabled) ||
|
||||
subscription.managedUsersEnabled ||
|
||||
subscription.groupPolicy?.userCannotUseAIFeatures ||
|
||||
|
||||
@@ -296,6 +296,7 @@ export interface Meta {
|
||||
'ol-script-logs': ScriptLogType[]
|
||||
'ol-settingsGroupSSO': { enabled: boolean } | undefined
|
||||
'ol-settingsPlans': Plan[]
|
||||
'ol-sharedWorkspaceEnabled': boolean
|
||||
'ol-sharingPermissions': SharingPermissions
|
||||
'ol-shouldAllowEditingDetails': boolean
|
||||
'ol-shouldLoadHotjar': boolean
|
||||
|
||||
@@ -642,9 +642,13 @@
|
||||
"disable_equation_preview": "Disable equation preview",
|
||||
"disable_equation_preview_confirm": "This will disable equation preview for you in all projects.",
|
||||
"disable_equation_preview_enable_in_settings": "You can enable it again in <b>Settings</b>.",
|
||||
"disable_shared_workspace": "Disable shared workspace",
|
||||
"disable_shared_workspace_modal_body": "Projects in the workspace will be transferred to their owners and shared only with their active collaborators. Group members will no longer have access to the shared workspace.",
|
||||
"disable_shared_workspace_modal_title": "Disable shared workspace?",
|
||||
"disable_single_sign_on": "Disable single sign-on",
|
||||
"disable_sso": "Disable SSO",
|
||||
"disable_stop_on_first_error": "Disable “Stop on first error”",
|
||||
"disable_workspace": "Disable workspace",
|
||||
"disabled": "Disabled",
|
||||
"disabling": "Disabling",
|
||||
"disagree": "Disagree",
|
||||
@@ -817,8 +821,12 @@
|
||||
"enable": "Enable",
|
||||
"enable_ai_features": "Enable AI features",
|
||||
"enable_managed_users": "Enable Managed Users",
|
||||
"enable_shared_workspace": "Enable shared workspace",
|
||||
"enable_shared_workspace_modal_body": "Projects added to the workspace will be visible to the whole group. Once enabled, shared workspace can’t be turned off without transferring projects back to their owners.",
|
||||
"enable_shared_workspace_modal_title": "Enable shared workspace?",
|
||||
"enable_single_sign_on": "Enable single sign-on",
|
||||
"enable_sso": "Enable SSO",
|
||||
"enable_workspace": "Enable workspace",
|
||||
"enabled": "Enabled",
|
||||
"enables_real_time_syntax_checking_in_the_editor": "Enables real-time syntax checking in the editor",
|
||||
"enabling": "Enabling",
|
||||
@@ -2429,6 +2437,12 @@
|
||||
"share_project": "Share Project",
|
||||
"share_project_name": "Share __projectName__",
|
||||
"shared_with_you": "Shared with you",
|
||||
"shared_workspace": "Shared workspace",
|
||||
"shared_workspace_failed_to_disable": "Shared workspace couldn’t be disabled. Try again or contact __appName__ support if the problem continues.",
|
||||
"shared_workspace_failed_to_enable": "Shared workspace couldn’t be enabled. Try again or contact __appName__ support if the problem continues.",
|
||||
"shared_workspace_is_enabled": "Shared workspace is enabled",
|
||||
"shared_workspace_managed_by_overleaf_support": "Shared workspace is managed by __appName__ support.",
|
||||
"shared_workspace_section_subtext": "All group members can see and access projects in the shared workspace.",
|
||||
"sharelatex_beta_program": "__appName__ beta program",
|
||||
"sharing_permissions": "Sharing permissions",
|
||||
"shortcut_to_open_advanced_reference_search": "(<strong>__ctrlSpace__</strong> or <strong>__altSpace__</strong>)",
|
||||
|
||||
+135
@@ -2,6 +2,7 @@ import { expect } from 'chai'
|
||||
import { screen } from '@testing-library/react'
|
||||
import ManagedGroupSubscriptions from '../../../../../../frontend/js/features/subscription/components/dashboard/managed-group-subscriptions'
|
||||
import { ManagedGroupSubscription } from '../../../../../../types/subscription/dashboard/subscription'
|
||||
import { MetaTag } from '@/utils/meta'
|
||||
import {
|
||||
cleanUpContext,
|
||||
renderWithSubscriptionDashContext,
|
||||
@@ -531,5 +532,139 @@ describe('<ManagedGroupSubscriptions />', function () {
|
||||
expect(screen.queryByText('Feature controls')).to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('Shared Workspace', function () {
|
||||
// metaAttributesCache isn't cleared between tests, so ol-splitTestVariants leaks from
|
||||
// earlier tests. Every test below sets it explicitly to stay independent of run order.
|
||||
function splitTestVariants(enabled: boolean): MetaTag {
|
||||
return {
|
||||
name: 'ol-splitTestVariants',
|
||||
value: enabled ? { 'shared-workspace': 'enabled' } : {},
|
||||
}
|
||||
}
|
||||
|
||||
it('renders the feature controls row for a non-managed group when the feature is enabled', async function () {
|
||||
renderWithSubscriptionDashContext(<ManagedGroupSubscriptions />, {
|
||||
metaTags: [
|
||||
{
|
||||
name: 'ol-managedGroupSubscriptions',
|
||||
value: makeSubscription({
|
||||
managedUsersEnabled: false,
|
||||
features: {
|
||||
groupSSO: false,
|
||||
managedUsers: false,
|
||||
sharedWorkspace: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{ name: 'ol-usersEmail', value: adminEmail },
|
||||
splitTestVariants(true),
|
||||
],
|
||||
})
|
||||
await screen.findByText('Feature controls')
|
||||
})
|
||||
|
||||
it('renders the feature controls row for a non-managed group when the feature is unset', async function () {
|
||||
renderWithSubscriptionDashContext(<ManagedGroupSubscriptions />, {
|
||||
metaTags: [
|
||||
{
|
||||
name: 'ol-managedGroupSubscriptions',
|
||||
value: makeSubscription({
|
||||
managedUsersEnabled: false,
|
||||
features: { groupSSO: false, managedUsers: false },
|
||||
}),
|
||||
},
|
||||
{ name: 'ol-usersEmail', value: adminEmail },
|
||||
splitTestVariants(true),
|
||||
],
|
||||
})
|
||||
await screen.findByText('Feature controls')
|
||||
})
|
||||
|
||||
it('does not render the feature controls row when the split test is not enabled', function () {
|
||||
renderWithSubscriptionDashContext(<ManagedGroupSubscriptions />, {
|
||||
metaTags: [
|
||||
{
|
||||
name: 'ol-managedGroupSubscriptions',
|
||||
value: makeSubscription({
|
||||
managedUsersEnabled: false,
|
||||
features: {
|
||||
groupSSO: false,
|
||||
managedUsers: false,
|
||||
sharedWorkspace: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{ name: 'ol-usersEmail', value: adminEmail },
|
||||
splitTestVariants(false),
|
||||
],
|
||||
})
|
||||
expect(screen.queryByText('Feature controls')).to.be.null
|
||||
})
|
||||
|
||||
it('does not render the feature controls row when Overleaf Support has disabled the feature', function () {
|
||||
renderWithSubscriptionDashContext(<ManagedGroupSubscriptions />, {
|
||||
metaTags: [
|
||||
{
|
||||
name: 'ol-managedGroupSubscriptions',
|
||||
value: makeSubscription({
|
||||
managedUsersEnabled: false,
|
||||
features: {
|
||||
groupSSO: false,
|
||||
managedUsers: false,
|
||||
sharedWorkspace: false,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{ name: 'ol-usersEmail', value: adminEmail },
|
||||
splitTestVariants(true),
|
||||
],
|
||||
})
|
||||
expect(screen.queryByText('Feature controls')).to.be.null
|
||||
})
|
||||
|
||||
it('does not render the feature controls row when the user is not the group admin', function () {
|
||||
renderWithSubscriptionDashContext(<ManagedGroupSubscriptions />, {
|
||||
metaTags: [
|
||||
{
|
||||
name: 'ol-managedGroupSubscriptions',
|
||||
value: makeSubscription({
|
||||
managedUsersEnabled: false,
|
||||
features: {
|
||||
groupSSO: false,
|
||||
managedUsers: false,
|
||||
sharedWorkspace: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{ name: 'ol-usersEmail', value: 'other@example.com' },
|
||||
splitTestVariants(true),
|
||||
],
|
||||
})
|
||||
expect(screen.queryByText('Feature controls')).to.be.null
|
||||
})
|
||||
|
||||
it('does not render the feature controls row when the group is not on a Pro plan', function () {
|
||||
renderWithSubscriptionDashContext(<ManagedGroupSubscriptions />, {
|
||||
metaTags: [
|
||||
{
|
||||
name: 'ol-managedGroupSubscriptions',
|
||||
value: makeSubscription({
|
||||
managedUsersEnabled: false,
|
||||
planLevelName: 'Standard',
|
||||
features: {
|
||||
groupSSO: false,
|
||||
managedUsers: false,
|
||||
sharedWorkspace: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{ name: 'ol-usersEmail', value: adminEmail },
|
||||
splitTestVariants(true),
|
||||
],
|
||||
})
|
||||
expect(screen.queryByText('Feature controls')).to.be.null
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1122,6 +1122,183 @@ describe('EmailBuilder', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('groupSharedWorkspaceDisabledForOwner', function () {
|
||||
beforeEach(function (ctx) {
|
||||
ctx.emailAddress = 'example@overleaf.com'
|
||||
ctx.opts = {
|
||||
to: ctx.emailAddress,
|
||||
groupName: 'Example Group',
|
||||
firstName: 'Joe',
|
||||
}
|
||||
ctx.email = ctx.EmailBuilder.buildEmail(
|
||||
'groupSharedWorkspaceDisabledForOwner',
|
||||
ctx.opts
|
||||
)
|
||||
ctx.expectedUrl = `${ctx.settings.siteUrl}/project`
|
||||
})
|
||||
|
||||
it('should build the email', function (ctx) {
|
||||
expect(ctx.email.html).to.exist
|
||||
expect(ctx.email.text).to.exist
|
||||
})
|
||||
|
||||
describe('HTML email', function () {
|
||||
it('should include a CTA button and a fallback CTA link', function (ctx) {
|
||||
const dom = cheerio.load(ctx.email.html)
|
||||
expect(ctx.email.subject).to.equal(
|
||||
'Your shared workspace has been disabled'
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
'Your projects are back in your personal list.'
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
`Your group administrator has disabled the shared workspace for ${ctx.opts.groupName}.`
|
||||
)
|
||||
const buttonLink = dom('a:contains("Open your projects")')
|
||||
expect(buttonLink.length).to.equal(1)
|
||||
expect(buttonLink.attr('href')).to.equal(ctx.expectedUrl)
|
||||
expect(ctx.email.html).to.contain('copy and paste this link')
|
||||
expect(ctx.email.html).to.contain(ctx.expectedUrl)
|
||||
})
|
||||
})
|
||||
|
||||
describe('plain text email', function () {
|
||||
it('should contain the CTA link', function (ctx) {
|
||||
expect(ctx.email.text).to.contain(ctx.expectedUrl)
|
||||
})
|
||||
})
|
||||
|
||||
it('escapes the group name in the HTML email', function (ctx) {
|
||||
const email = ctx.EmailBuilder.buildEmail(
|
||||
'groupSharedWorkspaceDisabledForOwner',
|
||||
{ ...ctx.opts, groupName: '<script>alert(1)</script>' }
|
||||
)
|
||||
expect(email.html).to.not.contain('<script>alert(1)</script>')
|
||||
expect(email.html).to.contain('<script>alert(1)</script>')
|
||||
})
|
||||
})
|
||||
|
||||
describe('groupSharedWorkspaceDisabledForMember', function () {
|
||||
beforeEach(function (ctx) {
|
||||
ctx.emailAddress = 'example@overleaf.com'
|
||||
ctx.opts = {
|
||||
to: ctx.emailAddress,
|
||||
groupName: 'Example Group',
|
||||
firstName: 'Joe',
|
||||
}
|
||||
ctx.email = ctx.EmailBuilder.buildEmail(
|
||||
'groupSharedWorkspaceDisabledForMember',
|
||||
ctx.opts
|
||||
)
|
||||
ctx.expectedUrl = `${ctx.settings.siteUrl}/project`
|
||||
})
|
||||
|
||||
it('should build the email', function (ctx) {
|
||||
expect(ctx.email.html).to.exist
|
||||
expect(ctx.email.text).to.exist
|
||||
})
|
||||
|
||||
describe('HTML email', function () {
|
||||
it('should include a CTA button and a fallback CTA link', function (ctx) {
|
||||
const dom = cheerio.load(ctx.email.html)
|
||||
expect(ctx.email.subject).to.equal(
|
||||
"Your group's shared workspace has been disabled"
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
"Here's what's changed for your group."
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
`Your group administrator has disabled the shared workspace for ${ctx.opts.groupName}.`
|
||||
)
|
||||
const buttonLink = dom('a:contains("Open your projects")')
|
||||
expect(buttonLink.length).to.equal(1)
|
||||
expect(buttonLink.attr('href')).to.equal(ctx.expectedUrl)
|
||||
expect(ctx.email.html).to.contain('copy and paste this link')
|
||||
expect(ctx.email.html).to.contain(ctx.expectedUrl)
|
||||
})
|
||||
})
|
||||
|
||||
describe('plain text email', function () {
|
||||
it('should contain the CTA link', function (ctx) {
|
||||
expect(ctx.email.text).to.contain(ctx.expectedUrl)
|
||||
})
|
||||
})
|
||||
|
||||
it('escapes the group name in the HTML email', function (ctx) {
|
||||
const email = ctx.EmailBuilder.buildEmail(
|
||||
'groupSharedWorkspaceDisabledForMember',
|
||||
{ ...ctx.opts, groupName: '<script>alert(1)</script>' }
|
||||
)
|
||||
expect(email.html).to.not.contain('<script>alert(1)</script>')
|
||||
expect(email.html).to.contain('<script>alert(1)</script>')
|
||||
})
|
||||
})
|
||||
|
||||
describe('groupSharedWorkspaceDisabledForAdmin', function () {
|
||||
beforeEach(function (ctx) {
|
||||
ctx.emailAddress = 'example@overleaf.com'
|
||||
ctx.opts = {
|
||||
to: ctx.emailAddress,
|
||||
groupName: 'Example Group',
|
||||
firstName: 'Joe',
|
||||
}
|
||||
ctx.email = ctx.EmailBuilder.buildEmail(
|
||||
'groupSharedWorkspaceDisabledForAdmin',
|
||||
ctx.opts
|
||||
)
|
||||
ctx.expectedUrl = `${ctx.settings.siteUrl}/project`
|
||||
})
|
||||
|
||||
it('should build the email', function (ctx) {
|
||||
expect(ctx.email.html).to.exist
|
||||
expect(ctx.email.text).to.exist
|
||||
})
|
||||
|
||||
describe('HTML email', function () {
|
||||
it('should include a CTA button and a fallback CTA link', function (ctx) {
|
||||
const dom = cheerio.load(ctx.email.html)
|
||||
expect(ctx.email.subject).to.equal(
|
||||
`Shared workspace disabled for ${ctx.opts.groupName}`
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
"Here's a summary of what changed for your group."
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
`You’ve disabled the shared workspace for ${ctx.opts.groupName}. Here's a summary of what happened.`
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
'Projects in the workspace have been returned to their owners and are no longer visible to the whole group.'
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
'Each project is now shared only with the collaborators the owner had already added.'
|
||||
)
|
||||
expect(ctx.email.html).to.contain(
|
||||
'Group members have been notified of the change.'
|
||||
)
|
||||
const buttonLink = dom('a:contains("Open your projects")')
|
||||
expect(buttonLink.length).to.equal(1)
|
||||
expect(buttonLink.attr('href')).to.equal(ctx.expectedUrl)
|
||||
expect(ctx.email.html).to.contain('copy and paste this link')
|
||||
expect(ctx.email.html).to.contain(ctx.expectedUrl)
|
||||
})
|
||||
})
|
||||
|
||||
describe('plain text email', function () {
|
||||
it('should contain the CTA link', function (ctx) {
|
||||
expect(ctx.email.text).to.contain(ctx.expectedUrl)
|
||||
})
|
||||
})
|
||||
|
||||
it('escapes the group name in the HTML email', function (ctx) {
|
||||
const email = ctx.EmailBuilder.buildEmail(
|
||||
'groupSharedWorkspaceDisabledForAdmin',
|
||||
{ ...ctx.opts, groupName: '<script>alert(1)</script>' }
|
||||
)
|
||||
expect(email.html).to.not.contain('<script>alert(1)</script>')
|
||||
expect(email.html).to.contain('<script>alert(1)</script>')
|
||||
})
|
||||
})
|
||||
|
||||
describe('groupDomainCapturedByGroupChanged', function () {
|
||||
it('should build active-domain-capture email', function (ctx) {
|
||||
const email = ctx.EmailBuilder.buildEmail(
|
||||
|
||||
@@ -102,6 +102,7 @@ export type ManagedGroupSubscription = {
|
||||
groupSSO: boolean | null
|
||||
managedUsers: boolean | null
|
||||
aiToggling?: boolean | null
|
||||
sharedWorkspace?: boolean | null
|
||||
}
|
||||
managedUsersEnabled: boolean
|
||||
groupPolicy?: GroupPolicy
|
||||
|
||||
Reference in New Issue
Block a user