mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-04-15 03:01:37 -05:00
Updated emails to use newsletter settings (#14588)
refs https://github.com/TryGhost/Team/issues/1550 - Updated email template and seder options to use the settings specified for the related newsletter - Falls back to the default newsletter, and uses the default newsletter settings for the publishing preview because we only assign a newsletter at the point a post is published Co-authored-by: Thibaut Patel <thibaut.patel@gmail.com> Co-authored-by: Matt Hanley <git@matthanley.co.uk>
This commit is contained in:
parent
810c3077e8
commit
f5bd647100
8 changed files with 577 additions and 97 deletions
|
@ -86,6 +86,25 @@ const Newsletter = ghostBookshelf.Model.extend({
|
|||
};
|
||||
},
|
||||
|
||||
getDefaultNewsletter: async function getDefaultNewsletter(unfilteredOptions = {}) {
|
||||
const options = {
|
||||
filter: 'status:active',
|
||||
order: this.orderDefaultRaw(),
|
||||
limit: 1
|
||||
};
|
||||
|
||||
if (unfilteredOptions.transacting) {
|
||||
options.transacting = unfilteredOptions.transacting;
|
||||
}
|
||||
|
||||
const newsletters = await this.findPage(options);
|
||||
|
||||
if (newsletters.data.length > 0) {
|
||||
return newsletters.data[0];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
getNextAvailableSortOrder: async function getNextAvailableSortOrder(unfilteredOptions = {}) {
|
||||
const options = {
|
||||
filter: 'status:active',
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const postEmailSerializer = require('./post-email-serializer');
|
||||
const models = require('../../models');
|
||||
|
||||
class EmailPreview {
|
||||
/**
|
||||
|
@ -16,7 +17,9 @@ class EmailPreview {
|
|||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async generateEmailContent(post, memberSegment) {
|
||||
let emailContent = await postEmailSerializer.serialize(post, {
|
||||
const newsletter = await models.Newsletter.getDefaultNewsletter();
|
||||
|
||||
let emailContent = await postEmailSerializer.serialize(post, newsletter, {
|
||||
isBrowserPreview: true,
|
||||
apiVersion: this.apiVersion
|
||||
});
|
||||
|
|
|
@ -31,24 +31,18 @@ const messages = {
|
|||
newsletterVisibilityError: 'Unexpected visibility value "{value}". Use one of the valid: "members", "paid".'
|
||||
};
|
||||
|
||||
const getFromAddress = () => {
|
||||
let fromAddress = membersService.config.getEmailFromAddress();
|
||||
|
||||
const getFromAddress = (senderName, fromAddress) => {
|
||||
if (/@localhost$/.test(fromAddress) || /@ghost.local$/.test(fromAddress)) {
|
||||
const localAddress = 'localhost@example.com';
|
||||
logging.warn(`Rewriting bulk email from address ${fromAddress} to ${localAddress}`);
|
||||
fromAddress = localAddress;
|
||||
}
|
||||
|
||||
const siteTitle = settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : '';
|
||||
|
||||
return siteTitle ? `"${siteTitle}"<${fromAddress}>` : fromAddress;
|
||||
return senderName ? `"${senderName}"<${fromAddress}>` : fromAddress;
|
||||
};
|
||||
|
||||
const getReplyToAddress = () => {
|
||||
const fromAddress = membersService.config.getEmailFromAddress();
|
||||
const getReplyToAddress = (fromAddress, replyAddressOption) => {
|
||||
const supportAddress = membersService.config.getEmailSupportAddress();
|
||||
const replyAddressOption = settingsCache.get('members_reply_address');
|
||||
|
||||
return (replyAddressOption === 'support') ? supportAddress : fromAddress;
|
||||
};
|
||||
|
@ -60,14 +54,28 @@ const getReplyToAddress = () => {
|
|||
* @param {ValidAPIVersion} options.apiVersion - api version to be used when serializing email data
|
||||
*/
|
||||
const getEmailData = async (postModel, options) => {
|
||||
const {subject, html, plaintext} = await postEmailSerializer.serialize(postModel, options);
|
||||
let newsletter = await postModel.related('newsletter').fetch();
|
||||
if (!newsletter) {
|
||||
newsletter = await models.Newsletter.getDefaultNewsletter();
|
||||
}
|
||||
const {subject, html, plaintext} = await postEmailSerializer.serialize(postModel, newsletter, options);
|
||||
|
||||
let senderName = settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : '';
|
||||
if (newsletter.get('sender_name')) {
|
||||
senderName = newsletter.get('sender_name');
|
||||
}
|
||||
|
||||
let fromAddress = membersService.config.getEmailFromAddress();
|
||||
if (newsletter.get('sender_email')) {
|
||||
fromAddress = newsletter.get('sender_email');
|
||||
}
|
||||
|
||||
return {
|
||||
subject,
|
||||
html,
|
||||
plaintext,
|
||||
from: getFromAddress(),
|
||||
replyTo: getReplyToAddress()
|
||||
from: getFromAddress(senderName, fromAddress),
|
||||
replyTo: getReplyToAddress(fromAddress, newsletter.get('sender_reply_to'))
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -601,7 +609,9 @@ module.exports = {
|
|||
// NOTE: below are only exposed for testing purposes
|
||||
_transformEmailRecipientFilter: transformEmailRecipientFilter,
|
||||
_partitionMembersBySegment: partitionMembersBySegment,
|
||||
_getEmailMemberRows: getEmailMemberRows
|
||||
_getEmailMemberRows: getEmailMemberRows,
|
||||
_getFromAddress: getFromAddress,
|
||||
_getReplyToAddress: getReplyToAddress
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,7 +10,6 @@ const htmlToText = require('html-to-text');
|
|||
const {isUnsplashImage, isLocalContentImage} = require('@tryghost/kg-default-cards/lib/utils');
|
||||
const {textColorForBackgroundColor, darkenToContrastThreshold} = require('@tryghost/color-utils');
|
||||
const logging = require('@tryghost/logging');
|
||||
const models = require('../../models');
|
||||
|
||||
const ALLOWED_REPLACEMENTS = ['first_name'];
|
||||
|
||||
|
@ -170,15 +169,7 @@ const parseReplacements = (email) => {
|
|||
return replacements;
|
||||
};
|
||||
|
||||
const getTemplateSettings = async (newsletterId = null) => {
|
||||
let newsletter;
|
||||
if (newsletterId) {
|
||||
newsletter = await models.Newsletter.findOne({id: newsletterId, filter: 'status:active'});
|
||||
} else {
|
||||
const newsletters = await models.Newsletter.findPage({filter: 'status:active', limit: 1});
|
||||
newsletter = newsletters.data[0];
|
||||
}
|
||||
|
||||
const getTemplateSettings = async (newsletter) => {
|
||||
const accentColor = settingsCache.get('accent_color');
|
||||
const adjustedAccentColor = accentColor && darkenToContrastThreshold(accentColor, '#ffffff', 2).hex();
|
||||
const adjustedAccentContrastColor = accentColor && textColorForBackgroundColor(adjustedAccentColor).hex();
|
||||
|
@ -231,7 +222,7 @@ const getTemplateSettings = async (newsletterId = null) => {
|
|||
return templateSettings;
|
||||
};
|
||||
|
||||
const serialize = async (postModel, options = {isBrowserPreview: false, apiVersion: 'v4'}) => {
|
||||
const serialize = async (postModel, newsletter, options = {isBrowserPreview: false, apiVersion: 'v4'}) => {
|
||||
const post = await serializePostModel(postModel, options.apiVersion);
|
||||
|
||||
const timezone = settingsCache.get('timezone');
|
||||
|
@ -300,11 +291,11 @@ const serialize = async (postModel, options = {isBrowserPreview: false, apiVersi
|
|||
}
|
||||
}
|
||||
|
||||
const templateSettings = await getTemplateSettings(post.newsletter_id);
|
||||
const templateSettings = await getTemplateSettings(newsletter);
|
||||
|
||||
const render = template;
|
||||
|
||||
let htmlTemplate = render({post, site: getSite(), templateSettings});
|
||||
let htmlTemplate = render({post, site: getSite(), templateSettings, newsletter: newsletter.toJSON()});
|
||||
|
||||
if (options.isBrowserPreview) {
|
||||
const previewUnsubscribeUrl = createUnsubscribeUrl(null);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint indent: warn, no-irregular-whitespace: warn */
|
||||
const iff = (cond, yes, no) => (cond ? yes : no);
|
||||
module.exports = ({post, site, templateSettings}) => {
|
||||
module.exports = ({post, site, newsletter, templateSettings}) => {
|
||||
const date = new Date();
|
||||
const hasFeatureImageCaption = templateSettings.showFeatureImage && post.feature_image && post.feature_image_caption;
|
||||
return `<!doctype html>
|
||||
|
@ -322,6 +322,9 @@ figure blockquote p {
|
|||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.site-url-bottom-padding {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
|
@ -329,6 +332,13 @@ figure blockquote p {
|
|||
color: #15212A;
|
||||
}
|
||||
|
||||
.site-subtitle {
|
||||
color: #8695a4;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
padding-bottom: 10px;
|
||||
font-size: 42px;
|
||||
|
@ -1158,7 +1168,7 @@ ${ templateSettings.showBadge ? `
|
|||
` : ''}
|
||||
|
||||
|
||||
${ templateSettings.showHeaderIcon || templateSettings.showHeaderTitle ? `
|
||||
${ templateSettings.showHeaderIcon || templateSettings.showHeaderTitle || templateSettings.showHeaderName ? `
|
||||
<tr>
|
||||
<td class="${templateSettings.showHeaderTitle ? `site-info-bordered` : `site-info`}" width="100%" align="center">
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
|
@ -1169,9 +1179,20 @@ ${ templateSettings.showBadge ? `
|
|||
` : ``}
|
||||
${ templateSettings.showHeaderTitle ? `
|
||||
<tr>
|
||||
<td class="site-url"><div style="width: 100% !important;"><a href="${site.url}" class="site-title">${site.title}</a></div></td>
|
||||
<td class="site-url ${!templateSettings.showHeaderName ? 'site-url-bottom-padding' : ''}"><div style="width: 100% !important;"><a href="${site.url}" class="site-title">${site.title}</a></div></td>
|
||||
</tr>
|
||||
` : ``}
|
||||
${ templateSettings.showHeaderName && templateSettings.showHeaderTitle ? `
|
||||
<tr>
|
||||
<td class="site-url site-url-bottom-padding"><div style="width: 100% !important;"><a href="${site.url}" class="site-subtitle">${newsletter.name}</a></div></td>
|
||||
</tr>
|
||||
` : ``}
|
||||
${ templateSettings.showHeaderName && !templateSettings.showHeaderTitle ? `
|
||||
<tr>
|
||||
<td class="site-url site-url-bottom-padding"><div style="width: 100% !important;"><a href="${site.url}" class="site-title">${newsletter.name}</a></div></td>
|
||||
</tr>
|
||||
` : ``}
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -3,7 +3,7 @@ const sinon = require('sinon');
|
|||
const errors = require('@tryghost/errors');
|
||||
const labs = require('../../../../../core/shared/labs');
|
||||
|
||||
const {addEmail, _partitionMembersBySegment, _getEmailMemberRows, _transformEmailRecipientFilter, handleUnsubscribeRequest} = require('../../../../../core/server/services/mega/mega');
|
||||
const {addEmail, _partitionMembersBySegment, _getEmailMemberRows, _transformEmailRecipientFilter, handleUnsubscribeRequest, _getFromAddress, _getReplyToAddress} = require('../../../../../core/server/services/mega/mega');
|
||||
const membersService = require('../../../../../core/server/services/members');
|
||||
|
||||
describe('MEGA', function () {
|
||||
|
@ -240,4 +240,38 @@ describe('MEGA', function () {
|
|||
}, errors.ValidationError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFromAddress', function () {
|
||||
it('Returns only the email when only fromAddress is specified', function () {
|
||||
should(_getFromAddress('', 'test@example.com')).eql('test@example.com');
|
||||
});
|
||||
|
||||
it('Adds a sender name when it\'s specified', function () {
|
||||
should(_getFromAddress(' Unnamed sender!! ', 'test@example.com')).eql('" Unnamed sender!! "<test@example.com>');
|
||||
});
|
||||
|
||||
it('Overwrites the fromAddress when the domain is localhost', function () {
|
||||
should(_getFromAddress('Test', 'test@localhost')).eql('"Test"<localhost@example.com>');
|
||||
});
|
||||
it('Overwrites the fromAddress when the domain is ghost.local', function () {
|
||||
should(_getFromAddress('123', '456@ghost.local')).eql('"123"<localhost@example.com>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getReplyToAddress', function () {
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('Returns the from address by default', function () {
|
||||
should(_getReplyToAddress('test@example.com')).eql('test@example.com');
|
||||
should(_getReplyToAddress('test2@example.com', 'invalid')).eql('test2@example.com');
|
||||
should(_getReplyToAddress('test3@example.com', 'newsletter')).eql('test3@example.com');
|
||||
});
|
||||
|
||||
it('Returns the support email when the option is set to "support"', function () {
|
||||
sinon.stub(membersService.config, 'getEmailSupportAddress').returns('support@example.com');
|
||||
should(_getReplyToAddress('test4@example.com', 'support')).eql('support@example.com');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -94,78 +94,30 @@ describe('Post Email Serializer', function () {
|
|||
sinon.restore();
|
||||
});
|
||||
|
||||
it('uses the default newsletter settings when no newsletter_id is defined', async function () {
|
||||
sinon.stub(settingsCache, 'get').callsFake(function (key) {
|
||||
return {
|
||||
icon: 'icon',
|
||||
accent_color: '#990000'
|
||||
}[key];
|
||||
});
|
||||
sinon.stub(models.Newsletter, 'findPage').returns(
|
||||
Promise.resolve({
|
||||
data: [{
|
||||
get: function (key) {
|
||||
return {
|
||||
header_image: 'image',
|
||||
show_header_icon: true,
|
||||
show_header_title: true,
|
||||
show_feature_image: true,
|
||||
title_font_category: 'sans_serif',
|
||||
title_alignment: 'center',
|
||||
body_font_category: 'serif',
|
||||
show_badge: true,
|
||||
footer_content: '',
|
||||
show_header_name: true
|
||||
}[key];
|
||||
}
|
||||
}]
|
||||
})
|
||||
);
|
||||
|
||||
const res = await _getTemplateSettings();
|
||||
should(res).eql({
|
||||
headerImage: 'image',
|
||||
showHeaderIcon: 'icon',
|
||||
showHeaderTitle: true,
|
||||
showHeaderName: true,
|
||||
showFeatureImage: true,
|
||||
titleFontCategory: 'sans_serif',
|
||||
titleAlignment: 'center',
|
||||
bodyFontCategory: 'serif',
|
||||
showBadge: true,
|
||||
footerContent: '',
|
||||
accentColor: '#990000',
|
||||
adjustedAccentColor: '#990000',
|
||||
adjustedAccentContrastColor: '#FFFFFF'
|
||||
});
|
||||
});
|
||||
|
||||
it('uses the newsletter settings when a newsletter_id is defined', async function () {
|
||||
it('uses the newsletter settings', async function () {
|
||||
sinon.stub(settingsCache, 'get').callsFake(function (key) {
|
||||
return {
|
||||
icon: 'icon2',
|
||||
accent_color: '#000099'
|
||||
}[key];
|
||||
});
|
||||
sinon.stub(models.Newsletter, 'findOne').returns(
|
||||
Promise.resolve({
|
||||
get: function (key) {
|
||||
return {
|
||||
header_image: 'image',
|
||||
show_header_icon: true,
|
||||
show_header_title: true,
|
||||
show_feature_image: true,
|
||||
title_font_category: 'sans-serif',
|
||||
title_alignment: 'center',
|
||||
body_font_category: 'serif',
|
||||
show_badge: true,
|
||||
footer_content: 'footer',
|
||||
show_header_name: true
|
||||
}[key];
|
||||
}
|
||||
})
|
||||
);
|
||||
const res = await _getTemplateSettings('123');
|
||||
const newsletterMock = {
|
||||
get: function (key) {
|
||||
return {
|
||||
header_image: 'image',
|
||||
show_header_icon: true,
|
||||
show_header_title: true,
|
||||
show_feature_image: true,
|
||||
title_font_category: 'sans-serif',
|
||||
title_alignment: 'center',
|
||||
body_font_category: 'serif',
|
||||
show_badge: true,
|
||||
footer_content: 'footer',
|
||||
show_header_name: true
|
||||
}[key];
|
||||
}
|
||||
};
|
||||
const res = await _getTemplateSettings(newsletterMock);
|
||||
should(res).eql({
|
||||
headerImage: 'image',
|
||||
showHeaderIcon: 'icon2',
|
||||
|
|
450
test/unit/server/services/mega/template.test.js
Normal file
450
test/unit/server/services/mega/template.test.js
Normal file
|
@ -0,0 +1,450 @@
|
|||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const render = require('../../../../../core/server/services/mega/template');
|
||||
|
||||
describe('Mega template', function () {
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('Renders html correctly', function () {
|
||||
const post = {
|
||||
title: 'My post title',
|
||||
excerpt: 'My post excerpt',
|
||||
url: 'post url',
|
||||
authors: 'post authors',
|
||||
published_at: 'post published_at',
|
||||
feature_image: 'post feature image',
|
||||
feature_image_caption: 'post feature image caption',
|
||||
feature_image_width: 'post feature image width',
|
||||
feature_image_alt: 'post feature image alt',
|
||||
html: '<div class="post-content-html"></div>'
|
||||
};
|
||||
const site = {
|
||||
iconUrl: 'site icon url',
|
||||
url: 'site url',
|
||||
title: 'site title'
|
||||
};
|
||||
const templateSettings = {
|
||||
headerImage: 'header image',
|
||||
headerImageWidth: '600',
|
||||
showHeaderIcon: true,
|
||||
showHeaderTitle: true,
|
||||
showHeaderName: true,
|
||||
titleAlignment: 'left',
|
||||
titleFontCategory: 'serif',
|
||||
showFeatureImage: true,
|
||||
bodyFontCategory: 'sans_serif',
|
||||
footerContent: 'footer content',
|
||||
showBadge: true
|
||||
};
|
||||
const newsletter = {
|
||||
name: 'newsletter name'
|
||||
};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
should($('title').text()).eql(post.title);
|
||||
should($('.preheader').text()).eql(post.excerpt);
|
||||
should($('.header-image').length).eql(1);
|
||||
|
||||
const headerImage = $('.header-image img');
|
||||
should(headerImage.length).eql(1);
|
||||
should(headerImage.attr('src')).eql(templateSettings.headerImage);
|
||||
should(headerImage.attr('width')).eql(templateSettings.headerImageWidth);
|
||||
should($('td.site-info-bordered').length).eql(1);
|
||||
should($('.site-info').length).eql(0);
|
||||
should($('.site-url').length).eql(2);
|
||||
should($('.site-icon').length).eql(1);
|
||||
should($('.site-icon a').attr('href')).eql(site.url);
|
||||
should($('.site-icon a img').attr('src')).eql(site.iconUrl);
|
||||
should($('.site-icon a img').attr('alt')).eql(site.title);
|
||||
should($('.site-title').length).eql(1);
|
||||
|
||||
const headerTitle = $($('.site-url').first());
|
||||
should(headerTitle.length).eql(1);
|
||||
should(headerTitle.hasClass('site-url-bottom-padding')).eql(false);
|
||||
should(headerTitle.find('.site-title').attr('href')).eql(site.url);
|
||||
should(headerTitle.find('.site-title').text()).eql(site.title);
|
||||
|
||||
const headerSubtitle = $($('.site-url').get()[1]);
|
||||
should(headerSubtitle.length).eql(1);
|
||||
should(headerSubtitle.hasClass('site-url-bottom-padding')).eql(true);
|
||||
should(headerSubtitle.find('.site-subtitle').attr('href')).eql(site.url);
|
||||
should(headerSubtitle.find('.site-subtitle').text()).eql(newsletter.name);
|
||||
|
||||
const postTitle = $('.post-title');
|
||||
should(postTitle.length).eql(1);
|
||||
should(postTitle.hasClass('post-title-serif')).eql(true);
|
||||
should(postTitle.hasClass('post-title-left')).eql(true);
|
||||
should($('.post-title a').attr('href')).eql(post.url);
|
||||
should($('.post-title a').hasClass('post-title-link-left')).eql(true);
|
||||
should($('.post-title a').text()).eql(post.title);
|
||||
|
||||
const postMeta = $('.post-meta');
|
||||
should(postMeta.length).eql(1);
|
||||
should(postMeta.hasClass('post-meta-left')).eql(true);
|
||||
should(postMeta.text().trim().replace(/ *\n */g, '\n')).eql(`By ${post.authors} –\n${post.published_at} –\nView online →`);
|
||||
should(postMeta.find('a').attr('href')).eql(post.url);
|
||||
|
||||
const featureImage = $('.feature-image');
|
||||
should(featureImage.length).eql(1);
|
||||
should(featureImage.hasClass('feature-image-with-caption')).eql(true);
|
||||
should(featureImage.find('img').attr('src')).eql(post.feature_image);
|
||||
should(featureImage.find('img').attr('width')).eql(post.feature_image_width);
|
||||
should(featureImage.find('img').attr('alt')).eql(post.feature_image_alt);
|
||||
|
||||
const imageCaption = $('.feature-image-caption');
|
||||
should(imageCaption.length).eql(1);
|
||||
|
||||
should(imageCaption.text()).eql(post.feature_image_caption);
|
||||
|
||||
should($('.post-content-sans-serif').length).eql(1);
|
||||
should($('.post-content').length).eql(0);
|
||||
|
||||
should($('.post-content-html').length).eql(1);
|
||||
|
||||
const footers = $('.footer').get();
|
||||
should(footers.length).eql(2);
|
||||
should($(footers[0]).text()).eql(templateSettings.footerContent);
|
||||
should($(footers[1]).text()).eql(`${site.title} © ${(new Date()).getFullYear()} – Unsubscribe`);
|
||||
should($(footers[1]).find('a').attr('href')).eql('%recipient.unsubscribe_url%');
|
||||
|
||||
const footerPowered = $('.footer-powered');
|
||||
should(footerPowered.length).eql(1);
|
||||
should(footerPowered.find('a img').attr('alt')).eql('Powered by Ghost');
|
||||
});
|
||||
|
||||
it('Uses the post title as a fallback for the excerpt', function () {
|
||||
const post = {
|
||||
title: 'My post title'
|
||||
};
|
||||
const site = {};
|
||||
const templateSettings = {};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.preheader').text()).eql(post.title + ' – ');
|
||||
});
|
||||
|
||||
it('Hides the header image if it isn\'t set', function () {
|
||||
const post = {};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
headerImage: ''
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
should($('.header-image').length).eql(0);
|
||||
});
|
||||
|
||||
it('Shows no width in the header if headerImageWidth isn\'t defined', function () {
|
||||
const post = {
|
||||
title: 'My post title'
|
||||
};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
headerImage: 'header image'
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.header-image').length).eql(1);
|
||||
should($('.header-image img').length).eql(1);
|
||||
should(typeof $('.header-image img').attr('width')).eql('undefined');
|
||||
});
|
||||
|
||||
it('Shows no header when all header features are disabled', function () {
|
||||
const post = {
|
||||
title: 'My post title'
|
||||
};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
showHeaderIcon: false,
|
||||
showHeaderTitle: false,
|
||||
showHeaderName: false
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.site-info-bordered').length).eql(0);
|
||||
should($('.site-info').length).eql(0);
|
||||
should($('.site-url').length).eql(0);
|
||||
should($('.site-icon').length).eql(0);
|
||||
should($('.site-title').length).eql(0);
|
||||
should($('.site-subtitle').length).eql(0);
|
||||
should($('.site-url-bottom-padding').length).eql(0);
|
||||
});
|
||||
|
||||
it('Shows the right header for showHeaderIcon:true, showHeaderTitle:false, showHeaderName:false', function () {
|
||||
/**
|
||||
* The edge case where the iconUrl is falsy in the current configuration wasn't tested.
|
||||
* The reason is that the Ghost admin is guarding against the edge case.
|
||||
*/
|
||||
const post = {};
|
||||
const site = {
|
||||
iconUrl: 'site icon url'
|
||||
};
|
||||
const templateSettings = {
|
||||
showHeaderIcon: true,
|
||||
showHeaderTitle: false,
|
||||
showHeaderName: false
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.site-info-bordered').length).eql(0);
|
||||
should($('.site-info').length).eql(1);
|
||||
should($('.site-icon').length).eql(1);
|
||||
should($('.site-url').length).eql(0);
|
||||
should($('.site-title').length).eql(0);
|
||||
should($('.site-subtitle').length).eql(0);
|
||||
});
|
||||
|
||||
it('Shows the right header for showHeaderIcon:false, showHeaderTitle:true, showHeaderName:false', function () {
|
||||
const post = {};
|
||||
const site = {
|
||||
title: 'site title'
|
||||
};
|
||||
const templateSettings = {
|
||||
showHeaderIcon: false,
|
||||
showHeaderTitle: true,
|
||||
showHeaderName: false
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.site-info-bordered').length).eql(1);
|
||||
should($('.site-info').length).eql(0);
|
||||
should($('.site-icon').length).eql(0);
|
||||
should($('.site-url').length).eql(1);
|
||||
should($('.site-url').hasClass('site-url-bottom-padding')).eql(true);
|
||||
should($('.site-url').text()).eql(site.title);
|
||||
should($('.site-title').length).eql(1);
|
||||
should($('.site-subtitle').length).eql(0);
|
||||
});
|
||||
|
||||
it('Shows the right header for showHeaderIcon:false, showHeaderTitle:false, showHeaderName:true', function () {
|
||||
const post = {};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
showHeaderIcon: false,
|
||||
showHeaderTitle: false,
|
||||
showHeaderName: true
|
||||
};
|
||||
const newsletter = {
|
||||
name: 'newsletter name'
|
||||
};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.site-info-bordered').length).eql(0);
|
||||
should($('.site-info').length).eql(1);
|
||||
should($('.site-icon').length).eql(0);
|
||||
should($('.site-url').length).eql(1);
|
||||
should($('.site-url').hasClass('site-url-bottom-padding')).eql(true);
|
||||
should($('.site-url').text()).eql(newsletter.name);
|
||||
should($('.site-title').length).eql(1);
|
||||
should($('.site-subtitle').length).eql(0);
|
||||
});
|
||||
|
||||
it('Shows the right header for showHeaderIcon:true, showHeaderTitle:true, showHeaderName:false', function () {
|
||||
const post = {};
|
||||
const site = {
|
||||
iconUrl: 'site icon url',
|
||||
title: 'site title'
|
||||
};
|
||||
const templateSettings = {
|
||||
showHeaderIcon: true,
|
||||
showHeaderTitle: true,
|
||||
showHeaderName: false
|
||||
};
|
||||
const newsletter = {
|
||||
};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.site-info-bordered').length).eql(1);
|
||||
should($('.site-info').length).eql(0);
|
||||
should($('.site-icon').length).eql(1);
|
||||
should($('.site-url').length).eql(1);
|
||||
should($('.site-url').hasClass('site-url-bottom-padding')).eql(true);
|
||||
should($('.site-url').text()).eql(site.title);
|
||||
should($('.site-title').length).eql(1);
|
||||
should($('.site-subtitle').length).eql(0);
|
||||
});
|
||||
|
||||
it('Shows the right header for showHeaderIcon:true, showHeaderTitle:false, showHeaderName:true', function () {
|
||||
const post = {};
|
||||
const site = {
|
||||
iconUrl: 'site icon url'
|
||||
};
|
||||
const templateSettings = {
|
||||
showHeaderIcon: true,
|
||||
showHeaderTitle: false,
|
||||
showHeaderName: true
|
||||
};
|
||||
const newsletter = {
|
||||
name: 'newsletter name'
|
||||
};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.site-info-bordered').length).eql(0);
|
||||
should($('.site-info').length).eql(1);
|
||||
should($('.site-icon').length).eql(1);
|
||||
should($('.site-url').length).eql(1);
|
||||
should($('.site-url').hasClass('site-url-bottom-padding')).eql(true);
|
||||
should($('.site-url').text()).eql(newsletter.name);
|
||||
should($('.site-title').length).eql(1);
|
||||
should($('.site-subtitle').length).eql(0);
|
||||
});
|
||||
|
||||
it('Shows the right html titleFontCategory isn\'t set to `serif` and when titleAlignment is set to `center`', function () {
|
||||
const post = {};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
titleFontCategory: 'sans_serif',
|
||||
titleAlignment: 'center'
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
const postTitle = $('.post-title');
|
||||
should(postTitle.hasClass('post-title-serif')).eql(false);
|
||||
should(postTitle.hasClass('post-title-left')).eql(false);
|
||||
should($('.post-title a').hasClass('post-title-link-left')).eql(false);
|
||||
should($('.post-meta').hasClass('post-meta-left')).eql(false);
|
||||
});
|
||||
|
||||
it('Renders correctly without a feature image (showFeatureImage set to `false`)', function () {
|
||||
const post = {
|
||||
feature_image: 'post feature image'
|
||||
};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
showFeatureImage: false
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
should($('.feature-image').length).eql(0);
|
||||
should($('.feature-image-caption').length).eql(0);
|
||||
});
|
||||
|
||||
it('Renders correctly without a feature image (post doesn\'t have a feature image)', function () {
|
||||
const post = {};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
showFeatureImage: true
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
should($('.feature-image').length).eql(0);
|
||||
should($('.feature-image-caption').length).eql(0);
|
||||
});
|
||||
|
||||
it('Renders correctly a feature image without width nor alt', function () {
|
||||
const post = {
|
||||
feature_image: 'post feature image'
|
||||
};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
showFeatureImage: true
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
const featureImage = $('.feature-image');
|
||||
should(featureImage.length).eql(1);
|
||||
should(featureImage.hasClass('feature-image-with-caption')).eql(false);
|
||||
should(featureImage.find('img').attr('src')).eql(post.feature_image);
|
||||
should(typeof featureImage.find('img').attr('width')).eql('undefined');
|
||||
should(typeof featureImage.find('img').attr('alt')).eql('undefined');
|
||||
});
|
||||
|
||||
it('Renders correctly without a feature image caption', function () {
|
||||
const post = {
|
||||
feature_image: 'post feature image'
|
||||
};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
showFeatureImage: true
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
const featureImage = $('.feature-image');
|
||||
should(featureImage.length).eql(1);
|
||||
should(featureImage.hasClass('feature-image-with-caption')).eql(false);
|
||||
|
||||
const imageCaption = $('.feature-image-caption');
|
||||
should(imageCaption.length).eql(0);
|
||||
});
|
||||
|
||||
it('Shows no footer when `footerContent` is falsy', function () {
|
||||
const post = {};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
footerContent: ''
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
const footer = $('.footer');
|
||||
should(footer.length).eql(1);
|
||||
should(footer.text()).eql(`${site.title} © ${(new Date()).getFullYear()} – Unsubscribe`);
|
||||
});
|
||||
|
||||
it('Shows no badge when `showBadge` is false', function () {
|
||||
const post = {};
|
||||
const site = {};
|
||||
const templateSettings = {
|
||||
showBadge: false
|
||||
};
|
||||
const newsletter = {};
|
||||
|
||||
const html = render({post, site, templateSettings, newsletter});
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
should($('.footer-powered').length).eql(0);
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue