diff --git a/services/web/app/src/Features/Email/Bodies/UpdatedNoCTAEmailBody.mjs b/services/web/app/src/Features/Email/Bodies/UpdatedNoCTAEmailBody.mjs
new file mode 100644
index 0000000000..6a314c2926
--- /dev/null
+++ b/services/web/app/src/Features/Email/Bodies/UpdatedNoCTAEmailBody.mjs
@@ -0,0 +1,28 @@
+import _ from 'lodash'
+import { fontFamily, colors } from '../emailStyles.mjs'
+
+export default _.template(`\
+<% if (title) { %>
+
+ <%= title %>
+
+<% } %>
+
+<% if (greeting) { %>
+
+ <%= greeting %>
+
+<% } %>
+
+<% (message).forEach(function(paragraph) { %>
+
+ <%= paragraph %>
+
+<% }) %>
+
+<% if (highlightedText) { %>
+
+ <%= highlightedText %>
+
+<% } %>\
+`)
diff --git a/services/web/app/src/Features/Email/Bodies/updated-cta-email.mjs b/services/web/app/src/Features/Email/Bodies/updated-cta-email.mjs
new file mode 100644
index 0000000000..8987b62251
--- /dev/null
+++ b/services/web/app/src/Features/Email/Bodies/updated-cta-email.mjs
@@ -0,0 +1,65 @@
+import _ from 'lodash'
+import { fontFamily, colors } from '../emailStyles.mjs'
+
+export default _.template(`\
+<% if (title) { %>
+
+ <%= title %>
+
+<% } %>
+
+<% if (greeting) { %>
+
+ <%= greeting %>
+
+<% } %>
+
+<% (message).forEach(function(paragraph) { %>
+
+ <%= paragraph %>
+
+<% }) %>
+
+
+
+<% if (secondaryMessage && secondaryMessage.length > 0) { %>
+ <% (secondaryMessage).forEach(function(paragraph) { %>
+
+ <%= paragraph %>
+
+ <% }) %>
+<% } %>
+
+
+ If the button above does not appear, please copy and paste this link into your browser's address bar:
+
+
+ <%= ctaURL %>
+
+
+<% if (gmailGoToAction) { %>
+
+<% } %>\
+`)
diff --git a/services/web/app/src/Features/Email/EmailBuilder.mjs b/services/web/app/src/Features/Email/EmailBuilder.mjs
index 2635ebf52b..21a1314b08 100644
--- a/services/web/app/src/Features/Email/EmailBuilder.mjs
+++ b/services/web/app/src/Features/Email/EmailBuilder.mjs
@@ -4,9 +4,12 @@ import moment from 'moment'
import EmailMessageHelper from './EmailMessageHelper.mjs'
import StringHelper from '../Helpers/StringHelper.mjs'
import BaseEmailLayout from './Layouts/BaseEmailLayout.mjs'
+import UpdatedBaseEmailLayout from './Layouts/UpdatedBaseEmailLayout.mjs'
import SpamSafe from './SpamSafe.mjs'
import ctaEmailBody from './Bodies/cta-email.mjs'
+import updatedCtaEmailBody from './Bodies/updated-cta-email.mjs'
import NoCTAEmailBody from './Bodies/NoCTAEmailBody.mjs'
+import UpdatedNoCTAEmailBody from './Bodies/UpdatedNoCTAEmailBody.mjs'
function _emailBodyPlainText(content, opts, ctaEmail) {
let emailBody = `${content.greeting(opts, true)}`
@@ -75,7 +78,12 @@ function ctaTemplate(content) {
subject(opts) {
return content.subject(opts)
},
- layout: BaseEmailLayout,
+ layout(opts) {
+ const layoutFn = opts.useNewEmailDesign
+ ? UpdatedBaseEmailLayout
+ : BaseEmailLayout
+ return layoutFn(opts)
+ },
footerMessage(opts) {
return content.footerMessage(opts)
},
@@ -83,7 +91,8 @@ function ctaTemplate(content) {
return _emailBodyPlainText(content, opts, true)
},
compiledTemplate(opts) {
- return ctaEmailBody({
+ const bodyFn = opts.useNewEmailDesign ? updatedCtaEmailBody : ctaEmailBody
+ return bodyFn({
title: content.title(opts),
greeting: content.greeting(opts),
message: content.message(opts),
@@ -108,7 +117,12 @@ function NoCTAEmailTemplate(content) {
subject(opts) {
return content.subject(opts)
},
- layout: BaseEmailLayout,
+ layout(opts) {
+ const layoutFn = opts.useNewEmailDesign
+ ? UpdatedBaseEmailLayout
+ : BaseEmailLayout
+ return layoutFn(opts)
+ },
plainTextTemplate(opts) {
return `\
${content.greeting(opts)}
@@ -120,7 +134,10 @@ The ${settings.appName} Team - ${settings.siteUrl}\
`
},
compiledTemplate(opts) {
- return NoCTAEmailBody({
+ const bodyFn = opts.useNewEmailDesign
+ ? UpdatedNoCTAEmailBody
+ : NoCTAEmailBody
+ return bodyFn({
title:
typeof content.title === 'function' ? content.title(opts) : undefined,
greeting: content.greeting(opts),
@@ -137,7 +154,6 @@ The ${settings.appName} Team - ${settings.siteUrl}\
function buildEmail(templateName, opts) {
const template = templates[templateName]
- opts.siteUrl = settings.siteUrl
opts.body = template.compiledTemplate(opts)
opts.footerMessage = template.footerMessage
? template.footerMessage(opts)
@@ -189,7 +205,7 @@ templates.canceledSubscription = ctaTemplate({
return ['Thank you in advance!']
},
ctaText() {
- return 'Leave Feedback'
+ return 'Leave feedback'
},
ctaURL(opts) {
return 'https://docs.google.com/forms/d/e/1FAIpQLSfa7z_s-cucRRXm70N4jEcSbFsZeb0yuKThHGQL8ySEaQzF0Q/viewform?usp=sf_link'
@@ -394,7 +410,7 @@ templates.reconfirmEmail = ctaTemplate({
]
},
ctaText() {
- return 'Reconfirm Email'
+ return 'Reconfirm email'
},
ctaURL(opts) {
return opts.confirmEmailUrl
@@ -894,7 +910,7 @@ templates.SAMLDataCleared = ctaTemplate({
]
},
ctaText(opts) {
- return 'Update my Emails and affiliations'
+ return 'Update my emails and affiliations'
},
ctaURL(opts) {
return `${settings.siteUrl}/user/settings`
diff --git a/services/web/app/src/Features/Email/EmailHandler.mjs b/services/web/app/src/Features/Email/EmailHandler.mjs
index 85a94d5439..0c0b769688 100644
--- a/services/web/app/src/Features/Email/EmailHandler.mjs
+++ b/services/web/app/src/Features/Email/EmailHandler.mjs
@@ -4,14 +4,37 @@ import logger from '@overleaf/logger'
import EmailBuilder from './EmailBuilder.mjs'
import EmailSender from './EmailSender.mjs'
import Queues from '../../infrastructure/Queues.mjs'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.mjs'
+import UserGetter from '../User/UserGetter.mjs'
const EMAIL_SETTINGS = Settings.email || {}
/**
* @param {string} emailType
- * @param {opts} any
+ * @param {object} opts
*/
async function sendEmail(emailType, opts) {
+ if (opts.to) {
+ try {
+ const user = await UserGetter.promises.getUserByAnyEmail(opts.to, {
+ _id: 1,
+ })
+ if (user) {
+ const { variant } =
+ await SplitTestHandler.promises.getAssignmentForUser(
+ user._id.toString(),
+ 'new-email-design'
+ )
+ opts.useNewEmailDesign = variant === 'enabled'
+ }
+ } catch (err) {
+ logger.warn(
+ { err },
+ 'failed to get new-email-design split test assignment'
+ )
+ }
+ }
+
const email = EmailBuilder.buildEmail(emailType, opts)
if (email.type === 'lifecycle' && !EMAIL_SETTINGS.lifecycle) {
return
diff --git a/services/web/app/src/Features/Email/Layouts/UpdatedBaseEmailLayout.mjs b/services/web/app/src/Features/Email/Layouts/UpdatedBaseEmailLayout.mjs
new file mode 100644
index 0000000000..174bd6d8d1
--- /dev/null
+++ b/services/web/app/src/Features/Email/Layouts/UpdatedBaseEmailLayout.mjs
@@ -0,0 +1,169 @@
+import _ from 'lodash'
+import settings from '@overleaf/settings'
+import { fontFamily, colors } from '../emailStyles.mjs'
+
+const _isSaas = settings.env === 'saas'
+const _imageBase = settings.cdn?.web?.host || settings.siteUrl || null
+
+let _logoHtml = `${settings.appName}`
+let _taglineHtml = ''
+if (_isSaas && _imageBase) {
+ _logoHtml = `
+
+
+
+ `
+
+ _taglineHtml = `
+
+
+
+
+ `
+}
+
+const _customFooter = settings.email?.template?.customFooter || ''
+
+export default _.template(`\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+ |
+
+
+
+
+ | |
+
+
+
+
+ |
+ ${_taglineHtml}
+ |
+
+
+
+ ${
+ _customFooter
+ ? `
+ |
+ ${_customFooter}
+ |
+ `
+ : ''
+ }
+
+ <% if (footerMessage) { %>
+
+ |
+ <%= footerMessage %>
+ |
+
+ <% } %>
+
+
+
+
+ |
+
+
+
+
+\
+`)
diff --git a/services/web/app/src/Features/Email/emailStyles.mjs b/services/web/app/src/Features/Email/emailStyles.mjs
new file mode 100644
index 0000000000..5ad855e6c2
--- /dev/null
+++ b/services/web/app/src/Features/Email/emailStyles.mjs
@@ -0,0 +1,12 @@
+export const fontFamily = 'Arial, Helvetica, sans-serif'
+
+export const colors = {
+ textDark: '#1b222c',
+ textMuted: '#495365',
+ background: '#f4f5f6',
+ ctaGreen: '#098842',
+ ctaText: '#ffffff',
+ linkGreen: '#1e6b41',
+ linkHover: '#155a30',
+ logoGreen: '#04652f',
+}
diff --git a/services/web/public/img/ol-brand/email-footer-tagline@2x.png b/services/web/public/img/ol-brand/email-footer-tagline@2x.png
new file mode 100644
index 0000000000..de4d7a2b1e
Binary files /dev/null and b/services/web/public/img/ol-brand/email-footer-tagline@2x.png differ
diff --git a/services/web/public/img/ol-brand/email-logo@2x.png b/services/web/public/img/ol-brand/email-logo@2x.png
new file mode 100644
index 0000000000..900c7a113b
Binary files /dev/null and b/services/web/public/img/ol-brand/email-logo@2x.png differ
diff --git a/services/web/test/unit/src/Email/EmailBuilder.test.mjs b/services/web/test/unit/src/Email/EmailBuilder.test.mjs
index c12104f120..8b94fcab5d 100644
--- a/services/web/test/unit/src/Email/EmailBuilder.test.mjs
+++ b/services/web/test/unit/src/Email/EmailBuilder.test.mjs
@@ -275,13 +275,11 @@ describe('EmailBuilder', function () {
describe('HTML email', function () {
it('should include a CTA button and a fallback CTA link', function (ctx) {
const dom = cheerio.load(ctx.email.html)
- const buttonLink = dom('a:contains("Leave Feedback")')
+ const buttonLink = dom('a:contains("Leave feedback")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.expectedUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html()
- expect(fallbackLink).to.contain(ctx.expectedUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.expectedUrl)
})
})
@@ -317,10 +315,8 @@ describe('EmailBuilder', function () {
const buttonLink = dom('a:contains("Leave feedback")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.expectedUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html()
- expect(fallbackLink).to.contain(ctx.expectedUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.expectedUrl)
})
})
@@ -354,10 +350,8 @@ describe('EmailBuilder', function () {
const buttonLink = dom('a:contains("Confirm email")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.opts.confirmEmailUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html()
- expect(fallbackLink).to.contain(ctx.opts.confirmEmailUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.opts.confirmEmailUrl)
})
})
@@ -396,13 +390,11 @@ describe('EmailBuilder', function () {
describe('HTML email', function () {
it('should include a CTA button and a fallback CTA link', function (ctx) {
const dom = cheerio.load(ctx.email.html)
- const buttonLink = dom('td a')
- expect(buttonLink).to.exist
+ const buttonLink = dom('a:contains("View project")')
+ expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.expectedUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback).to.exist
- const fallbackLink = fallback.html().replace(/&/g, '&')
- expect(fallbackLink).to.contain(ctx.expectedUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.expectedUrl)
})
})
@@ -438,13 +430,11 @@ describe('EmailBuilder', function () {
describe('HTML email', function () {
it('should include a CTA button and a fallback CTA link', function (ctx) {
const dom = cheerio.load(ctx.email.html)
- const buttonLink = dom('td a')
- expect(buttonLink).to.exist
+ const buttonLink = dom('a:contains("Reset password")')
+ expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.opts.setNewPasswordUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback).to.exist
- const fallbackLink = fallback.html().replace(/&/g, '&')
- expect(fallbackLink).to.contain(ctx.opts.setNewPasswordUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.opts.setNewPasswordUrl)
})
})
@@ -475,13 +465,11 @@ describe('EmailBuilder', function () {
describe('HTML email', function () {
it('should include a CTA button and a fallback CTA link', function (ctx) {
const dom = cheerio.load(ctx.email.html)
- const buttonLink = dom('a:contains("Reconfirm Email")')
+ const buttonLink = dom('a:contains("Reconfirm email")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.opts.confirmEmailUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html()
- expect(fallbackLink).to.contain(ctx.opts.confirmEmailUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.opts.confirmEmailUrl)
})
})
@@ -521,10 +509,8 @@ describe('EmailBuilder', function () {
const buttonLink = dom('a:contains("Join now")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.opts.acceptInviteUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html()
- expect(fallbackLink).to.contain(ctx.opts.acceptInviteUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.opts.acceptInviteUrl)
})
})
@@ -559,10 +545,8 @@ describe('EmailBuilder', function () {
const buttonLink = dom('a:contains("View Subscription Dashboard")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.expectedUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html()
- expect(fallbackLink).to.contain(ctx.expectedUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.expectedUrl)
})
})
@@ -593,10 +577,8 @@ describe('EmailBuilder', function () {
const buttonLink = dom(`a:contains("Open ${ctx.settings.appName}")`)
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.settings.siteUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html()
- expect(fallbackLink).to.contain(ctx.settings.siteUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.settings.siteUrl)
})
})
@@ -630,10 +612,8 @@ describe('EmailBuilder', function () {
const buttonLink = dom('a:contains("Set password")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.opts.setNewPasswordUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html().replace(/&/, '&')
- expect(fallbackLink).to.contain(ctx.opts.setNewPasswordUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.opts.setNewPasswordUrl)
})
})
@@ -676,10 +656,8 @@ describe('EmailBuilder', function () {
const buttonLink = dom('a:contains("View project")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.opts.inviteUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- const fallbackLink = fallback.html().replace(/&/g, '&')
- expect(fallbackLink).to.contain(ctx.opts.inviteUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.opts.inviteUrl)
})
})
@@ -711,9 +689,8 @@ describe('EmailBuilder', function () {
const buttonLink = ctx.dom('a:contains("Confirm email")')
expect(buttonLink.length).to.equal(1)
expect(buttonLink.attr('href')).to.equal(ctx.opts.confirmEmailUrl)
- const fallback = ctx.dom('.force-overleaf-style').last()
- expect(fallback.length).to.equal(1)
- expect(fallback.html()).to.contain(ctx.opts.confirmEmailUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.opts.confirmEmailUrl)
})
it('should include help links', function (ctx) {
const helpGuidesLink = ctx.dom('a:contains("Help Guides")')
@@ -761,11 +738,12 @@ describe('EmailBuilder', function () {
expect(email.html).to.contain(
'You can still log in to Overleaf using one of our other'
)
- const links = dom('a')
- expect(links[0].attribs.href).to.equal(
+ const loginLink = dom('a:contains("login options")')
+ expect(loginLink.attr('href')).to.equal(
`${ctx.settings.siteUrl}/login`
)
- expect(links[1].attribs.href).to.equal(setNewPasswordUrl)
+ const passwordLink = dom('a:contains("Set your new password")')
+ expect(passwordLink.attr('href')).to.equal(setNewPasswordUrl)
expect(email.html).to.contain(
"If you don't have a password, you can set one now."
)
@@ -813,8 +791,8 @@ describe('EmailBuilder', function () {
expect(email.html).to.contain(
'You now need an email address and password to sign in to your Overleaf account.'
)
- const links = dom('a')
- expect(links[0].attribs.href).to.equal(
+ const ctaLink = dom('a:contains("Set your new password")')
+ expect(ctaLink.attr('href')).to.equal(
`${ctx.settings.siteUrl}/user/password/reset`
)
@@ -1067,13 +1045,11 @@ describe('EmailBuilder', function () {
expect(ctx.email.html).to.contain(
'Remove inactive users to free up licenses'
)
- const buttonLink = dom('td a')
+ const buttonLink = dom('a:contains("Add licenses")')
expect(buttonLink).to.exist
expect(buttonLink.attr('href')).to.equal(ctx.expectedUrl)
- const fallback = dom('.force-overleaf-style').last()
- expect(fallback).to.exist
- const fallbackLink = fallback.html().replace(/&/g, '&')
- expect(fallbackLink).to.contain(ctx.expectedUrl)
+ expect(ctx.email.html).to.contain('copy and paste this link')
+ expect(ctx.email.html).to.contain(ctx.expectedUrl)
})
})
diff --git a/services/web/test/unit/src/Email/EmailHandler.test.mjs b/services/web/test/unit/src/Email/EmailHandler.test.mjs
index 3d189efb3f..211ff146df 100644
--- a/services/web/test/unit/src/Email/EmailHandler.test.mjs
+++ b/services/web/test/unit/src/Email/EmailHandler.test.mjs
@@ -39,6 +39,27 @@ describe('EmailHandler', function () {
default: ctx.Queues,
}))
+ ctx.SplitTestHandler = {
+ promises: {
+ getAssignmentForUser: sinon.stub().resolves({ variant: 'default' }),
+ },
+ }
+ vi.doMock(
+ '../../../../app/src/Features/SplitTests/SplitTestHandler',
+ () => ({
+ default: ctx.SplitTestHandler,
+ })
+ )
+
+ ctx.UserGetter = {
+ promises: {
+ getUserByAnyEmail: sinon.stub().resolves(null),
+ },
+ }
+ vi.doMock('../../../../app/src/Features/User/UserGetter', () => ({
+ default: ctx.UserGetter,
+ }))
+
ctx.EmailHandler = (await import(MODULE_PATH)).default
})
diff --git a/services/web/test/unit/src/Email/UpdatedBaseEmailLayout.test.mjs b/services/web/test/unit/src/Email/UpdatedBaseEmailLayout.test.mjs
new file mode 100644
index 0000000000..cf2df55888
--- /dev/null
+++ b/services/web/test/unit/src/Email/UpdatedBaseEmailLayout.test.mjs
@@ -0,0 +1,75 @@
+import { vi, expect } from 'vitest'
+import { load } from 'cheerio'
+import path from 'node:path'
+
+const LAYOUT_PATH = path.join(
+ import.meta.dirname,
+ '../../../../app/src/Features/Email/Layouts/UpdatedBaseEmailLayout'
+)
+
+async function buildLayoutWithEnv(env) {
+ vi.resetModules()
+ vi.doMock('@overleaf/settings', () => ({
+ default: {
+ appName: 'TestApp',
+ siteUrl: 'https://www.example.com',
+ env,
+ },
+ }))
+ const { default: layout } = await import(LAYOUT_PATH)
+ return layout({ body: 'Test body', footerMessage: '' })
+}
+
+describe('UpdatedBaseEmailLayout branding', function () {
+ afterEach(function () {
+ vi.restoreAllMocks()
+ vi.resetModules()
+ })
+
+ describe('on SaaS', function () {
+ it('should show the logo image', async function () {
+ const html = await buildLayoutWithEnv('saas')
+ const dom = load(html)
+ const logoImg = dom('img[alt="TestApp"]')
+ expect(logoImg.length).to.equal(1)
+ expect(logoImg.attr('src')).to.contain('email-logo@2x.png')
+ })
+
+ it('should show the tagline image', async function () {
+ const html = await buildLayoutWithEnv('saas')
+ expect(html).to.contain('email-footer-tagline@2x.png')
+ })
+ })
+
+ describe('on server-ce', function () {
+ it('should show the app name as text instead of logo', async function () {
+ const html = await buildLayoutWithEnv('server-ce')
+ const dom = load(html)
+ const logoImg = dom('img[alt="TestApp"]')
+ expect(logoImg.length).to.equal(0)
+ expect(html).to.contain('TestApp')
+ expect(html).to.not.contain('email-logo@2x.png')
+ })
+
+ it('should not show the tagline image', async function () {
+ const html = await buildLayoutWithEnv('server-ce')
+ expect(html).to.not.contain('email-footer-tagline@2x.png')
+ })
+ })
+
+ describe('on server-pro', function () {
+ it('should show the app name as text instead of logo', async function () {
+ const html = await buildLayoutWithEnv('server-pro')
+ const dom = load(html)
+ const logoImg = dom('img[alt="TestApp"]')
+ expect(logoImg.length).to.equal(0)
+ expect(html).to.contain('TestApp')
+ expect(html).to.not.contain('email-logo@2x.png')
+ })
+
+ it('should not show the tagline image', async function () {
+ const html = await buildLayoutWithEnv('server-pro')
+ expect(html).to.not.contain('email-footer-tagline@2x.png')
+ })
+ })
+})