2022-11-21 12:29:53 +03:00
const { agentProvider , fixtureManager , matchers , mockManager } = require ( '../../utils/e2e-framework' ) ;
2023-03-07 18:08:40 +03:00
const { anyEtag , anyErrorId , anyContentVersion , anyString } = matchers ;
2023-06-21 11:56:59 +03:00
const assert = require ( 'assert/strict' ) ;
2023-03-03 20:58:19 +03:00
const sinon = require ( 'sinon' ) ;
2023-03-07 18:08:40 +03:00
const escapeRegExp = require ( 'lodash/escapeRegExp' ) ;
const should = require ( 'should' ) ;
2022-09-02 12:20:11 +03:00
// @TODO: factor out these requires
2022-10-12 10:54:35 +03:00
const ObjectId = require ( 'bson-objectid' ) . default ;
2019-11-08 07:37:53 +03:00
const testUtils = require ( '../../utils' ) ;
2020-04-20 14:47:12 +03:00
const models = require ( '../../../core/server/models/index' ) ;
2023-03-03 20:58:19 +03:00
const logging = require ( '@tryghost/logging' ) ;
2019-11-08 07:37:53 +03:00
2023-03-14 18:03:57 +03:00
function testCleanedSnapshot ( html , cleaned ) {
2023-03-07 18:08:40 +03:00
for ( const [ key , value ] of Object . entries ( cleaned ) ) {
html = html . replace ( new RegExp ( escapeRegExp ( key ) , 'g' ) , value ) ;
}
should ( { html } ) . matchSnapshot ( ) ;
}
const matchEmailPreviewBody = {
email _previews : [
{
html : anyString ,
plaintext : anyString
}
]
} ;
2019-11-05 07:32:53 +03:00
describe ( 'Email Preview API' , function ( ) {
2022-09-02 12:20:11 +03:00
let agent ;
2019-11-05 07:32:53 +03:00
2022-11-21 12:29:53 +03:00
afterEach ( function ( ) {
mockManager . restore ( ) ;
2023-03-03 20:58:19 +03:00
sinon . restore ( ) ;
2022-11-21 12:29:53 +03:00
} ) ;
2023-03-07 18:08:40 +03:00
beforeEach ( function ( ) {
mockManager . mockMailgun ( ) ;
} ) ;
2020-11-30 17:25:22 +03:00
before ( async function ( ) {
2022-09-02 12:20:11 +03:00
agent = await agentProvider . getAdminAPIAgent ( ) ;
await fixtureManager . init ( 'users' , 'newsletters' , 'posts' ) ;
await agent . loginAsOwner ( ) ;
2019-11-05 07:32:53 +03:00
} ) ;
describe ( 'Read' , function ( ) {
2020-11-30 17:25:22 +03:00
it ( 'can\'t retrieve for non existent post' , async function ( ) {
2022-09-02 12:20:11 +03:00
await agent . get ( 'email_previews/posts/abcd1234abcd1234abcd1234/' )
. expectStatus ( 404 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
. matchBodySnapshot ( {
errors : [ {
id : anyErrorId
} ]
} ) ;
2019-11-05 07:32:53 +03:00
} ) ;
2020-11-30 17:25:22 +03:00
it ( 'can read post email preview with fields' , async function ( ) {
2023-03-09 14:32:22 +03:00
const defaultNewsletter = await models . Newsletter . getDefaultNewsletter ( ) ;
2022-09-02 12:20:11 +03:00
await agent
. get ( ` email_previews/posts/ ${ fixtureManager . get ( 'posts' , 0 ) . id } / ` )
. expectStatus ( 200 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
2023-03-09 14:32:22 +03:00
. matchBodySnapshot ( matchEmailPreviewBody )
. expect ( ( { body } ) => {
testCleanedSnapshot ( body . email _previews [ 0 ] . html , {
[ defaultNewsletter . get ( 'uuid' ) ] : 'requested-newsletter-uuid'
} ) ;
testCleanedSnapshot ( body . email _previews [ 0 ] . plaintext , {
[ defaultNewsletter . get ( 'uuid' ) ] : 'requested-newsletter-uuid'
} ) ;
} ) ;
2019-11-05 07:32:53 +03:00
} ) ;
2020-04-20 14:47:12 +03:00
2020-11-30 17:25:22 +03:00
it ( 'can read post email preview with email card and replacements' , async function ( ) {
2023-03-09 14:32:22 +03:00
const defaultNewsletter = await models . Newsletter . getDefaultNewsletter ( ) ;
2020-04-20 14:47:12 +03:00
const post = testUtils . DataGenerator . forKnex . createPost ( {
2021-04-21 18:02:02 +03:00
id : ObjectId ( ) . toHexString ( ) ,
2020-04-20 14:47:12 +03:00
title : 'Post with email-only card' ,
slug : 'email-only-card' ,
2020-04-20 16:25:58 +03:00
mobiledoc : '{"version":"0.3.1","atoms":[],"cards":[["email",{"html":"<p>Hey {first_name \\"there\\"} {unknown}</p><p><strong>Welcome to your first Ghost email!</strong></p>"}],["email",{"html":"<p>Another email card with a similar replacement, {first_name, \\"see?\\"}</p>"}]],"markups":[],"sections":[[10,0],[1,"p",[[0,[],0,"This is the actual post content..."]]],[10,1],[1,"p",[]]]}' ,
2020-04-20 14:47:12 +03:00
html : '<p>This is the actual post content...</p>' ,
plaintext : 'This is the actual post content...' ,
status : 'draft' ,
2022-09-02 12:20:11 +03:00
uuid : 'd52c42ae-2755-455c-80ec-70b2ec55c904' ,
published _at : new Date ( 0 )
2020-04-20 14:47:12 +03:00
} ) ;
2020-11-30 17:25:22 +03:00
await models . Post . add ( post , { context : { internal : true } } ) ;
2022-09-02 12:20:11 +03:00
await agent
. get ( ` email_previews/posts/ ${ post . id } / ` )
. expectStatus ( 200 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
2023-03-09 14:32:22 +03:00
. matchBodySnapshot ( matchEmailPreviewBody )
. expect ( ( { body } ) => {
testCleanedSnapshot ( body . email _previews [ 0 ] . html , {
[ defaultNewsletter . get ( 'uuid' ) ] : 'requested-newsletter-uuid'
} ) ;
testCleanedSnapshot ( body . email _previews [ 0 ] . plaintext , {
[ defaultNewsletter . get ( 'uuid' ) ] : 'requested-newsletter-uuid'
} ) ;
} ) ;
2020-04-20 14:47:12 +03:00
} ) ;
2020-08-12 21:46:25 +03:00
2020-11-30 17:25:22 +03:00
it ( 'has custom content transformations for email compatibility' , async function ( ) {
2023-03-07 18:08:40 +03:00
const defaultNewsletter = await models . Newsletter . getDefaultNewsletter ( ) ;
2020-08-12 21:46:25 +03:00
const post = testUtils . DataGenerator . forKnex . createPost ( {
2021-04-21 18:02:02 +03:00
id : ObjectId ( ) . toHexString ( ) ,
2020-08-12 21:46:25 +03:00
title : 'Post with email-only card' ,
slug : 'email-only-card' ,
2020-08-12 22:14:06 +03:00
mobiledoc : '{"version":"0.3.1","atoms":[],"cards":[],"markups":[["a",["href","https://ghost.org"]]],"sections":[[1,"p",[[0,[],0,"Testing "],[0,[0],1,"links"],[0,[],0," in email excerpt and apostrophes \'"]]]]}' ,
2020-08-12 21:46:25 +03:00
html : '<p>This is the actual post content...</p>' ,
plaintext : 'This is the actual post content...' ,
status : 'draft' ,
2022-09-02 12:20:11 +03:00
uuid : 'd52c42ae-2755-455c-80ec-70b2ec55c904' ,
published _at : new Date ( 0 )
2020-08-12 21:46:25 +03:00
} ) ;
2020-11-30 17:25:22 +03:00
await models . Post . add ( post , { context : { internal : true } } ) ;
2022-09-02 12:20:11 +03:00
await agent
. get ( ` email_previews/posts/ ${ post . id } / ` )
. expectStatus ( 200 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
2023-03-07 18:08:40 +03:00
. matchBodySnapshot ( matchEmailPreviewBody )
2022-09-02 12:20:11 +03:00
. expect ( ( { body } ) => {
// Extra assert to ensure apostrophe is transformed
assert . doesNotMatch ( body . email _previews [ 0 ] . html , /Testing links in email excerpt and apostrophes '/ ) ;
assert . match ( body . email _previews [ 0 ] . html , /Testing links in email excerpt and apostrophes '/ ) ;
2023-03-07 18:08:40 +03:00
2023-03-09 14:32:22 +03:00
testCleanedSnapshot ( body . email _previews [ 0 ] . html , {
[ defaultNewsletter . get ( 'uuid' ) ] : 'requested-newsletter-uuid'
} ) ;
2023-03-07 18:08:40 +03:00
testCleanedSnapshot ( body . email _previews [ 0 ] . plaintext , {
[ defaultNewsletter . get ( 'uuid' ) ] : 'requested-newsletter-uuid'
} ) ;
2022-09-02 12:20:11 +03:00
} ) ;
2020-08-12 21:46:25 +03:00
} ) ;
2022-05-11 18:52:24 +03:00
2022-09-02 12:20:11 +03:00
it ( 'uses the posts newsletter by default' , async function ( ) {
2022-05-11 18:52:24 +03:00
const defaultNewsletter = await models . Newsletter . getDefaultNewsletter ( ) ;
2022-09-02 12:20:11 +03:00
const selectedNewsletter = fixtureManager . get ( 'newsletters' , 0 ) ;
defaultNewsletter . id . should . not . eql ( selectedNewsletter . id , 'Should use a non-default newsletter for this test' ) ;
2022-05-11 18:52:24 +03:00
const post = testUtils . DataGenerator . forKnex . createPost ( {
id : ObjectId ( ) . toHexString ( ) ,
title : 'Post with email-only card' ,
slug : 'email-only-card' ,
mobiledoc : '{"version":"0.3.1","atoms":[],"cards":[],"markups":[["a",["href","https://ghost.org"]]],"sections":[[1,"p",[[0,[],0,"Testing "],[0,[0],1,"links"],[0,[],0," in email excerpt and apostrophes \'"]]]]}' ,
html : '<p>This is the actual post content...</p>' ,
plaintext : 'This is the actual post content...' ,
status : 'scheduled' ,
uuid : 'd52c42ae-2755-455c-80ec-70b2ec55c904' ,
2022-09-02 12:20:11 +03:00
newsletter _id : selectedNewsletter . id ,
published _at : new Date ( 0 )
2022-05-11 18:52:24 +03:00
} ) ;
await models . Post . add ( post , { context : { internal : true } } ) ;
2022-09-02 12:20:11 +03:00
await agent
. get ( ` email_previews/posts/ ${ post . id } / ` )
. expectStatus ( 200 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
2023-03-07 18:08:40 +03:00
. matchBodySnapshot ( matchEmailPreviewBody )
2022-09-02 12:20:11 +03:00
. expect ( ( { body } ) => {
// Extra assert to ensure newsletter is correct
assert . doesNotMatch ( body . email _previews [ 0 ] . html , new RegExp ( defaultNewsletter . get ( 'name' ) ) ) ;
assert . match ( body . email _previews [ 0 ] . html , new RegExp ( selectedNewsletter . name ) ) ;
2023-03-07 18:08:40 +03:00
testCleanedSnapshot ( body . email _previews [ 0 ] . html , {
[ selectedNewsletter . uuid ] : 'requested-newsletter-uuid'
} ) ;
testCleanedSnapshot ( body . email _previews [ 0 ] . plaintext , {
[ selectedNewsletter . uuid ] : 'requested-newsletter-uuid'
} ) ;
2022-09-02 12:20:11 +03:00
} ) ;
2022-05-16 14:15:54 +03:00
} ) ;
it ( 'uses the newsletter provided through ?newsletter=slug' , async function ( ) {
const defaultNewsletter = await models . Newsletter . getDefaultNewsletter ( ) ;
2022-09-02 12:20:11 +03:00
const selectedNewsletter = fixtureManager . get ( 'newsletters' , 0 ) ;
2022-05-16 14:15:54 +03:00
selectedNewsletter . id . should . not . eql ( defaultNewsletter . id , 'Should use a non-default newsletter for this test' ) ;
const post = testUtils . DataGenerator . forKnex . createPost ( {
id : ObjectId ( ) . toHexString ( ) ,
title : 'Post with email-only card' ,
slug : 'email-only-card' ,
mobiledoc : '{"version":"0.3.1","atoms":[],"cards":[],"markups":[["a",["href","https://ghost.org"]]],"sections":[[1,"p",[[0,[],0,"Testing "],[0,[0],1,"links"],[0,[],0," in email excerpt and apostrophes \'"]]]]}' ,
html : '<p>This is the actual post content...</p>' ,
plaintext : 'This is the actual post content...' ,
status : 'draft' ,
2022-09-02 12:20:11 +03:00
uuid : 'd52c42ae-2755-455c-80ec-70b2ec55c904' ,
published _at : new Date ( 0 )
2022-05-16 14:15:54 +03:00
} ) ;
await models . Post . add ( post , { context : { internal : true } } ) ;
2022-09-02 12:20:11 +03:00
await agent
. get ( ` email_previews/posts/ ${ post . id } /?newsletter= ${ selectedNewsletter . slug } ` )
. expectStatus ( 200 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
2023-03-07 18:08:40 +03:00
. matchBodySnapshot ( matchEmailPreviewBody )
2022-09-02 12:20:11 +03:00
. expect ( ( { body } ) => {
// Extra assert to ensure newsletter is correct
assert . doesNotMatch ( body . email _previews [ 0 ] . html , new RegExp ( defaultNewsletter . get ( 'name' ) ) ) ;
assert . match ( body . email _previews [ 0 ] . html , new RegExp ( selectedNewsletter . name ) ) ;
2023-03-07 18:08:40 +03:00
testCleanedSnapshot ( body . email _previews [ 0 ] . html , {
[ selectedNewsletter . uuid ] : 'requested-newsletter-uuid'
} ) ;
testCleanedSnapshot ( body . email _previews [ 0 ] . plaintext , {
[ selectedNewsletter . uuid ] : 'requested-newsletter-uuid'
} ) ;
2022-09-02 12:20:11 +03:00
} ) ;
2022-05-11 18:52:24 +03:00
} ) ;
2019-11-05 07:32:53 +03:00
} ) ;
2020-05-28 11:56:53 +03:00
describe ( 'As Owner' , function ( ) {
2020-11-30 17:25:22 +03:00
it ( 'can send test email' , async function ( ) {
2022-09-02 12:20:11 +03:00
await agent
. post ( ` email_previews/posts/ ${ fixtureManager . get ( 'posts' , 0 ) . id } / ` )
. body ( {
2020-05-28 11:56:53 +03:00
emails : [ 'test@ghost.org' ]
} )
2022-09-02 12:20:11 +03:00
. expectStatus ( 204 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
. expectEmptyBody ( ) ;
2020-05-28 11:56:53 +03:00
} ) ;
} ) ;
2020-11-30 17:25:22 +03:00
2020-05-28 11:56:53 +03:00
describe ( 'As Admin' , function ( ) {
2020-11-30 17:25:22 +03:00
before ( async function ( ) {
2022-09-02 12:20:11 +03:00
await agent . loginAsAdmin ( ) ;
2020-05-28 11:56:53 +03:00
} ) ;
2020-11-30 17:25:22 +03:00
it ( 'can send test email' , async function ( ) {
2022-09-02 12:20:11 +03:00
await agent
. post ( ` email_previews/posts/ ${ fixtureManager . get ( 'posts' , 0 ) . id } / ` )
. body ( {
2020-05-28 11:56:53 +03:00
emails : [ 'test@ghost.org' ]
} )
2022-09-02 12:20:11 +03:00
. expectStatus ( 204 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
. expectEmptyBody ( ) ;
2020-05-28 11:56:53 +03:00
} ) ;
} ) ;
2020-11-30 17:25:22 +03:00
2020-05-28 11:56:53 +03:00
describe ( 'As Editor' , function ( ) {
2020-11-30 17:25:22 +03:00
before ( async function ( ) {
2022-09-02 12:20:11 +03:00
await agent . loginAsEditor ( ) ;
2020-05-28 11:56:53 +03:00
} ) ;
2020-11-30 17:25:22 +03:00
it ( 'can send test email' , async function ( ) {
2022-09-02 12:20:11 +03:00
await agent
. post ( ` email_previews/posts/ ${ fixtureManager . get ( 'posts' , 0 ) . id } / ` )
. body ( {
2020-05-28 11:56:53 +03:00
emails : [ 'test@ghost.org' ]
} )
2022-09-02 12:20:11 +03:00
. expectStatus ( 204 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
. expectEmptyBody ( ) ;
2020-05-28 11:56:53 +03:00
} ) ;
} ) ;
2020-11-30 17:25:22 +03:00
2020-05-28 11:56:53 +03:00
describe ( 'As Author' , function ( ) {
2020-11-30 17:25:22 +03:00
before ( async function ( ) {
2022-09-02 12:20:11 +03:00
await agent . loginAsAuthor ( ) ;
} ) ;
it ( 'cannot send test email' , async function ( ) {
2023-03-03 20:58:19 +03:00
const loggingStub = sinon . stub ( logging , 'error' ) ;
2022-09-02 12:20:11 +03:00
await agent
. post ( ` email_previews/posts/ ${ fixtureManager . get ( 'posts' , 0 ) . id } / ` )
. body ( {
emails : [ 'test@ghost.org' ]
} )
. expectStatus ( 403 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
. matchBodySnapshot ( {
errors : [ {
id : anyErrorId
} ]
} ) ;
2023-03-03 20:58:19 +03:00
sinon . assert . calledOnce ( loggingStub ) ;
2022-09-02 12:20:11 +03:00
} ) ;
} ) ;
2020-11-30 17:25:22 +03:00
2022-09-02 12:20:11 +03:00
describe ( 'As Contributor' , function ( ) {
before ( async function ( ) {
await agent . loginAsContributor ( ) ;
2020-05-28 11:56:53 +03:00
} ) ;
2020-11-30 17:25:22 +03:00
it ( 'cannot send test email' , async function ( ) {
2023-03-03 20:58:19 +03:00
const loggingStub = sinon . stub ( logging , 'error' ) ;
2022-09-02 12:20:11 +03:00
await agent
. post ( ` email_previews/posts/ ${ fixtureManager . get ( 'posts' , 0 ) . id } / ` )
. body ( {
2020-05-28 11:56:53 +03:00
emails : [ 'test@ghost.org' ]
} )
2022-09-02 12:20:11 +03:00
. expectStatus ( 403 )
. matchHeaderSnapshot ( {
2023-01-17 14:56:29 +03:00
'content-version' : anyContentVersion ,
2022-09-02 12:20:11 +03:00
etag : anyEtag
} )
. matchBodySnapshot ( {
errors : [ {
id : anyErrorId
} ]
2022-03-17 19:13:25 +03:00
} ) ;
2023-03-03 20:58:19 +03:00
sinon . assert . calledOnce ( loggingStub ) ;
2020-05-28 11:56:53 +03:00
} ) ;
} ) ;
2019-11-05 07:32:53 +03:00
} ) ;