mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-24 19:33:02 +03:00
Added tests for click events in the activity feed
fixes https://github.com/TryGhost/Team/issues/2018 - Includes new test fixtures for redirects and click events - Tests if post, and links are returned in the click events
This commit is contained in:
parent
08da18e324
commit
d4540012dc
@ -358,13 +358,17 @@ const PostEmailSerializer = {
|
||||
// Now replace the links in the HTML version
|
||||
if (!options.isBrowserPreview && !options.isTestEmail && settingsCache.get('email_track_clicks')) {
|
||||
result.html = await linkReplacer.replace(result.html, async (url) => {
|
||||
// Add newsletter source attribution
|
||||
url = memberAttribution.service.addEmailSourceAttributionTracking(url, newsletter);
|
||||
const isSite = urlUtils.isSiteUrl(url);
|
||||
|
||||
if (isSite) {
|
||||
url = memberAttribution.service.addEmailSourceAttributionTracking(url, newsletter);
|
||||
|
||||
// Only add post attribution to our own site (because external sites could/should not process this information)
|
||||
url = memberAttribution.service.addPostAttributionTracking(url, post);
|
||||
} else {
|
||||
// For external sites, add ref to the site URL instead of newsletter
|
||||
const siteUrl = new URL(urlUtils.urlFor('home', true));
|
||||
url.searchParams.append('ref', siteUrl.hostname);
|
||||
}
|
||||
|
||||
// Add link click tracking
|
||||
|
@ -4042,6 +4042,209 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Returns click events in activity feed 1: [body] 1`] = `
|
||||
Object {
|
||||
"events": Array [
|
||||
Object {
|
||||
"data": Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
|
||||
"link": Object {
|
||||
"from": "/r/0",
|
||||
"to": "https:://ghost.org",
|
||||
},
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"email": "member1@test.com",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Mr Egg",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"post": Object {
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "HTML Ipsum",
|
||||
"url": Any<String>,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
},
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
|
||||
"link": Object {
|
||||
"from": "/r/1",
|
||||
"to": "https:://ghost.org",
|
||||
},
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"email": "member2@test.com",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": null,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"post": Object {
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Ghostly Kitchen Sink",
|
||||
"url": Any<String>,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
},
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
|
||||
"link": Object {
|
||||
"from": "/r/2",
|
||||
"to": "https:://ghost.org",
|
||||
},
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"email": "paid@test.com",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Egon Spengler",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"post": Object {
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Short and Sweet",
|
||||
"url": Any<String>,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
},
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
|
||||
"link": Object {
|
||||
"from": "/r/3",
|
||||
"to": "https:://ghost.org",
|
||||
},
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"email": "trialing@test.com",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Ray Stantz",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"post": Object {
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Not finished yet",
|
||||
"url": Any<String>,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
},
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
|
||||
"link": Object {
|
||||
"from": "/r/4",
|
||||
"to": "https:://ghost.org",
|
||||
},
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"email": "comped@test.com",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Vinz Clortho",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"post": Object {
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Not so short, bit complex",
|
||||
"url": Any<String>,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
},
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
|
||||
"link": Object {
|
||||
"from": "/r/5",
|
||||
"to": "https:://ghost.org",
|
||||
},
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"email": "vip@test.com",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Winston Zeddemore",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"post": Object {
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "This is a static page",
|
||||
"url": Any<String>,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
},
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
|
||||
"link": Object {
|
||||
"from": "/r/6",
|
||||
"to": "https:://ghost.org",
|
||||
},
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"email": "vip-paid@test.com",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Peter Venkman",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"post": Object {
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "This is a draft static page",
|
||||
"url": Any<String>,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
},
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}/,
|
||||
"link": Object {
|
||||
"from": "/r/7",
|
||||
"to": "https:://ghost.org",
|
||||
},
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"email": "with-product@test.com",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Dana Barrett",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"post": Object {
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "This is a scheduled post!!",
|
||||
"url": Any<String>,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
},
|
||||
"type": Any<String>,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Returns click events in activity feed 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "3631",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Version, Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Returns comments in activity feed 1: [body] 1`] = `
|
||||
Object {
|
||||
"events": Array [
|
||||
|
@ -416,7 +416,7 @@ describe('Members API', function () {
|
||||
|
||||
before(async function () {
|
||||
agent = await agentProvider.getAdminAPIAgent();
|
||||
await fixtureManager.init('posts', 'newsletters', 'members:newsletters', 'comments');
|
||||
await fixtureManager.init('posts', 'newsletters', 'members:newsletters', 'comments', 'redirects', 'clicks');
|
||||
await agent.loginAsOwner();
|
||||
|
||||
newsletters = await getNewsletters();
|
||||
@ -451,6 +451,36 @@ describe('Members API', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Returns click events in activity feed', async function () {
|
||||
// Check activity feed
|
||||
await agent
|
||||
.get(`/members/events?filter=type:click_event`)
|
||||
.expectStatus(200)
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
})
|
||||
.matchBodySnapshot({
|
||||
events: new Array(8).fill({
|
||||
type: anyString,
|
||||
data: {
|
||||
created_at: anyISODate,
|
||||
member: {
|
||||
id: anyObjectId,
|
||||
uuid: anyUuid
|
||||
},
|
||||
post: {
|
||||
id: anyObjectId,
|
||||
uuid: anyUuid,
|
||||
url: anyString
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.expect(({body}) => {
|
||||
should(body.events.find(e => e.type === 'click_event')).not.be.undefined();
|
||||
});
|
||||
});
|
||||
|
||||
// List Members
|
||||
|
||||
it('Can browse', async function () {
|
||||
|
@ -643,6 +643,18 @@ const fixtures = {
|
||||
}));
|
||||
},
|
||||
|
||||
insertRedirects: async function insertClicks() {
|
||||
await Promise.all(DataGenerator.forKnex.redirects.map((click) => {
|
||||
return models.Redirect.add(click, context.internal);
|
||||
}));
|
||||
},
|
||||
|
||||
insertClicks: async function insertClicks() {
|
||||
await Promise.all(DataGenerator.forKnex.members_click_events.map((click) => {
|
||||
return models.MemberClickEvent.add(click, context.internal);
|
||||
}));
|
||||
},
|
||||
|
||||
insertSnippets: function insertSnippets() {
|
||||
return Promise.map(DataGenerator.forKnex.snippets, function (snippet) {
|
||||
return models.Snippet.add(snippet, context.internal);
|
||||
@ -776,6 +788,12 @@ const toDoList = {
|
||||
},
|
||||
comments: function insertComments() {
|
||||
return fixtures.insertComments();
|
||||
},
|
||||
redirects: function insertRedirects() {
|
||||
return fixtures.insertRedirects();
|
||||
},
|
||||
clicks: function insertClicks() {
|
||||
return fixtures.insertClicks();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1656,6 +1656,26 @@ DataGenerator.forKnex = (function () {
|
||||
createBasic(DataGenerator.Content.members_paid_subscription_events[2])
|
||||
];
|
||||
|
||||
const redirects = posts.map((post, index) => {
|
||||
return {
|
||||
id: ObjectId().toHexString(),
|
||||
from: '/r/' + index,
|
||||
to: 'https:://ghost.org',
|
||||
post_id: post.id,
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
};
|
||||
});
|
||||
|
||||
const members_click_events = redirects.map((redirect, index) => {
|
||||
return {
|
||||
id: ObjectId().toHexString(),
|
||||
member_id: members[index].id,
|
||||
redirect_id: redirect.id,
|
||||
created_at: new Date()
|
||||
};
|
||||
});
|
||||
|
||||
const snippets = [
|
||||
createBasic(DataGenerator.Content.snippets[0])
|
||||
];
|
||||
@ -1730,10 +1750,12 @@ DataGenerator.forKnex = (function () {
|
||||
snippets,
|
||||
custom_theme_settings,
|
||||
comments,
|
||||
redirects,
|
||||
|
||||
members_paid_subscription_events,
|
||||
members_created_events,
|
||||
members_subscription_created_events
|
||||
members_subscription_created_events,
|
||||
members_click_events
|
||||
};
|
||||
}());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user