Revert "Added member attributions to activity feed (#15283)"
This reverts commit e986b78458
.
The tests were not passing for the PR and it was erroneously
merged into main
This commit is contained in:
parent
fce4b26601
commit
3c431bd8da
@ -102,8 +102,9 @@
|
||||
<span class="gh-dashboard-list-subtext">
|
||||
{{capitalize-first-letter parsedEvent.action}}
|
||||
{{#if parsedEvent.url}}
|
||||
{{parsedEvent.join}}
|
||||
<a class="ghost-members-activity-object-link {{if (feature "memberAttribution") 'hidden'}}" href="{{parsedEvent.url}}" target="_blank" rel="noopener noreferrer">{{parsedEvent.object}}</a>
|
||||
{{else}}
|
||||
{{parsedEvent.object}}
|
||||
{{/if}}
|
||||
{{#if parsedEvent.info}}
|
||||
<span class="highlight">{{parsedEvent.info}}</span>
|
||||
|
@ -27,8 +27,9 @@
|
||||
<span class="gh-members-activity-description">
|
||||
{{capitalize-first-letter event.action}}
|
||||
{{#if event.url}}
|
||||
{{event.join}}
|
||||
<a class="ghost-members-activity-object-link" href="{{event.url}}" target="_blank" rel="noopener noreferrer">{{event.object}}</a>
|
||||
{{else}}
|
||||
{{event.object}}
|
||||
{{/if}}
|
||||
{{#if event.email}}
|
||||
<GhEmailPreviewLink @data={{event.email}} />
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="flex items-center">
|
||||
<GhMemberAvatar @member={{event.member}} @containerClass="w9 h9 mr3 flex-shrink-0" />
|
||||
<div class="w-80">
|
||||
<h3 class="ma0 pa0 gh-members-list-name {{unless event.member.name "gh-members-name-noname"}}">{{event.subject}}</h3>
|
||||
<h3 class="ma0 pa0 gh-members-list-name {{unless event.member.name "gh-members-name-noname"}}">{{or event.member.name event.member.email}}</h3>
|
||||
{{#if event.member.name}}
|
||||
<p class="ma0 pa0 middarkgrey f8 gh-members-list-email">{{event.member.email}}</p>
|
||||
{{/if}}
|
||||
@ -21,9 +21,10 @@
|
||||
<div class="gh-members-activity-event">
|
||||
<span class="gh-members-activity-description">
|
||||
{{capitalize-first-letter event.action}}
|
||||
{{#if (and event.url (not (feature "memberAttribution")))}}
|
||||
{{event.join}}
|
||||
<a class="ghost-members-activity-object-link" href="{{event.url}}" target="_blank" rel="noopener noreferrer">{{event.object}}</a>
|
||||
{{#if event.url}}
|
||||
<a class="ghost-members-activity-object-link {{if (feature "memberAttribution") 'hidden'}}" href="{{event.url}}" target="_blank" rel="noopener noreferrer">{{event.object}}</a>
|
||||
{{else}}
|
||||
{{event.object}}
|
||||
{{/if}}
|
||||
{{#if event.email}}
|
||||
<span class="{{if (feature "memberAttribution") 'hidden'}}"><GhEmailPreviewLink @data={{event.email}} /></span>
|
||||
|
@ -2,15 +2,13 @@ import moment from 'moment';
|
||||
import {getNonDecimal, getSymbol} from 'ghost-admin/utils/currency';
|
||||
|
||||
export default function parseMemberEvent(event, hasMultipleNewsletters) {
|
||||
const subject = event.data.member.name || event.data.member.email;
|
||||
const icon = getIcon(event);
|
||||
const action = getAction(event, hasMultipleNewsletters);
|
||||
const info = getInfo(event);
|
||||
|
||||
const join = getJoin(event);
|
||||
const object = getObject(event);
|
||||
let subject = event.data.member.name || event.data.member.email;
|
||||
let icon = getIcon(event);
|
||||
let action = getAction(event);
|
||||
let object = getObject(event, hasMultipleNewsletters);
|
||||
let info = getInfo(event);
|
||||
const url = getURL(event);
|
||||
const timestamp = moment(event.data.created_at);
|
||||
let timestamp = moment(event.data.created_at);
|
||||
|
||||
return {
|
||||
memberId: event.data.member_id ?? event.data.member?.id,
|
||||
@ -20,7 +18,6 @@ export default function parseMemberEvent(event, hasMultipleNewsletters) {
|
||||
icon,
|
||||
subject,
|
||||
action,
|
||||
join,
|
||||
object,
|
||||
info,
|
||||
url,
|
||||
@ -80,7 +77,7 @@ function getIcon(event) {
|
||||
return 'event-' + icon;
|
||||
}
|
||||
|
||||
function getAction(event, hasMultipleNewsletters) {
|
||||
function getAction(event) {
|
||||
if (event.type === 'signup_event') {
|
||||
return 'signed up';
|
||||
}
|
||||
@ -94,98 +91,78 @@ function getAction(event, hasMultipleNewsletters) {
|
||||
}
|
||||
|
||||
if (event.type === 'newsletter_event') {
|
||||
let newsletter = 'newsletter';
|
||||
if (hasMultipleNewsletters && event.data.newsletter && event.data.newsletter.name) {
|
||||
newsletter = 'newsletter – ' + event.data.newsletter.name;
|
||||
}
|
||||
|
||||
if (event.data.subscribed) {
|
||||
return 'subscribed to ' + newsletter;
|
||||
return 'subscribed to';
|
||||
} else {
|
||||
return 'unsubscribed from ' + newsletter;
|
||||
return 'unsubscribed from';
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type === 'subscription_event') {
|
||||
if (event.data.type === 'created') {
|
||||
return 'started their subscription';
|
||||
return 'started';
|
||||
}
|
||||
if (event.data.type === 'updated') {
|
||||
return 'changed their subscription';
|
||||
return 'changed';
|
||||
}
|
||||
if (event.data.type === 'canceled') {
|
||||
return 'canceled their subscription';
|
||||
return 'canceled';
|
||||
}
|
||||
if (event.data.type === 'reactivated') {
|
||||
return 'reactivated their subscription';
|
||||
return 'reactivated';
|
||||
}
|
||||
if (event.data.type === 'expired') {
|
||||
return 'ended their subscription';
|
||||
return 'ended';
|
||||
}
|
||||
|
||||
return 'changed their subscription';
|
||||
return 'changed';
|
||||
}
|
||||
|
||||
if (event.type === 'email_opened_event') {
|
||||
return 'opened an email';
|
||||
return 'opened';
|
||||
}
|
||||
|
||||
if (event.type === 'email_delivered_event') {
|
||||
return 'received an email';
|
||||
return 'received';
|
||||
}
|
||||
|
||||
if (event.type === 'email_failed_event') {
|
||||
return 'failed to receive an email';
|
||||
return 'failed to receive';
|
||||
}
|
||||
|
||||
if (event.type === 'comment_event') {
|
||||
if (event.data.parent) {
|
||||
return 'replied to a comment';
|
||||
return 'replied to a comment on';
|
||||
}
|
||||
return 'commented';
|
||||
return 'commented on';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When we need to append the action and object in one sentence, you can add extra words here.
|
||||
* E.g.,
|
||||
* action: 'Signed up'.
|
||||
* object: 'My blog post'
|
||||
* When both words need to get appended, we'll add 'on'
|
||||
* -> do this by returning 'on' in getJoin()
|
||||
* This string is not added when action and object are in a separete table column, or when the getObject/getURL is empty
|
||||
*/
|
||||
function getJoin(event) {
|
||||
if (event.type === 'signup_event' || event.type === 'subscription_event') {
|
||||
if (event.data.attribution?.title) {
|
||||
// Add 'Attributed to ' for now, until this is incorporated in the design
|
||||
return 'on';
|
||||
function getObject(event, hasMultipleNewsletters) {
|
||||
if (event.type === 'newsletter_event') {
|
||||
if (hasMultipleNewsletters && event.data.newsletter && event.data.newsletter.name) {
|
||||
return 'newsletter – ' + event.data.newsletter.name;
|
||||
}
|
||||
return 'newsletter';
|
||||
}
|
||||
|
||||
if (event.type === 'subscription_event') {
|
||||
return 'their subscription';
|
||||
}
|
||||
|
||||
if (event.type.match?.(/^email_/)) {
|
||||
return 'an email';
|
||||
}
|
||||
|
||||
if (event.type === 'subscription_event') {
|
||||
return 'their subscription';
|
||||
}
|
||||
|
||||
if (event.type === 'comment_event') {
|
||||
if (event.data.post) {
|
||||
return 'on';
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Clickable object, shown between action and info, or in a separate column in some views
|
||||
*/
|
||||
function getObject(event) {
|
||||
if (event.type === 'signup_event' || event.type === 'subscription_event') {
|
||||
if (event.data.attribution?.title) {
|
||||
// Add 'Attributed to ' for now, until this is incorporated in the design
|
||||
return event.data.attribution.title;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type === 'comment_event') {
|
||||
if (event.data.post) {
|
||||
return event.data.post.title;
|
||||
if (event.type === 'comment_event') {
|
||||
if (event.data.post) {
|
||||
return event.data.post.title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,6 +179,13 @@ function getInfo(event) {
|
||||
let symbol = getSymbol(event.data.currency);
|
||||
return `(MRR ${sign}${symbol}${Math.abs(mrrDelta)})`;
|
||||
}
|
||||
|
||||
// TODO: we can include the post title
|
||||
/*if (event.type === 'comment_event') {
|
||||
if (event.data.post) {
|
||||
return event.data.post.title;
|
||||
}
|
||||
}*/
|
||||
return;
|
||||
}
|
||||
|
||||
@ -214,11 +198,5 @@ function getURL(event) {
|
||||
return event.data.post.url;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type === 'signup_event' || event.type === 'subscription_event') {
|
||||
if (event.data.attribution && event.data.attribution.url) {
|
||||
return event.data.attribution.url;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -8,16 +8,8 @@ const MemberCreatedEvent = ghostBookshelf.Model.extend({
|
||||
return this.belongsTo('Member', 'member_id', 'id');
|
||||
},
|
||||
|
||||
postAttribution() {
|
||||
return this.belongsTo('Post', 'attribution_id', 'id');
|
||||
},
|
||||
|
||||
userAttribution() {
|
||||
return this.belongsTo('User', 'attribution_id', 'id');
|
||||
},
|
||||
|
||||
tagAttribution() {
|
||||
return this.belongsTo('Tag', 'attribution_id', 'id');
|
||||
attribution() {
|
||||
return this.belongsTo('Post', 'attribution_id', 'id');
|
||||
}
|
||||
}, {
|
||||
async edit() {
|
||||
|
@ -8,10 +8,6 @@ const MemberPaidSubscriptionEvent = ghostBookshelf.Model.extend({
|
||||
return this.belongsTo('Member', 'member_id', 'id');
|
||||
},
|
||||
|
||||
subscriptionCreatedEvent() {
|
||||
return this.belongsTo('SubscriptionCreatedEvent', 'subscription_id', 'subscription_id');
|
||||
},
|
||||
|
||||
customQuery(qb, options) {
|
||||
if (options.aggregateMRRDeltas) {
|
||||
if (options.limit || options.filter) {
|
||||
|
@ -12,16 +12,8 @@ const SubscriptionCreatedEvent = ghostBookshelf.Model.extend({
|
||||
return this.belongsTo('StripeCustomerSubscription', 'subscription_id', 'id');
|
||||
},
|
||||
|
||||
postAttribution() {
|
||||
return this.belongsTo('Post', 'attribution_id', 'id');
|
||||
},
|
||||
|
||||
userAttribution() {
|
||||
return this.belongsTo('User', 'attribution_id', 'id');
|
||||
},
|
||||
|
||||
tagAttribution() {
|
||||
return this.belongsTo('Tag', 'attribution_id', 'id');
|
||||
attribution() {
|
||||
return this.belongsTo('Post', 'attribution_id', 'id');
|
||||
}
|
||||
}, {
|
||||
async edit() {
|
||||
|
@ -24,7 +24,7 @@ class MemberAttributionServiceWrapper {
|
||||
}
|
||||
});
|
||||
|
||||
this.attributionBuilder = new AttributionBuilder({urlTranslator});
|
||||
const attributionBuilder = new AttributionBuilder({urlTranslator});
|
||||
|
||||
// Expose the service
|
||||
this.service = new MemberAttributionService({
|
||||
@ -32,7 +32,7 @@ class MemberAttributionServiceWrapper {
|
||||
MemberCreatedEvent: models.MemberCreatedEvent,
|
||||
SubscriptionCreatedEvent: models.SubscriptionCreatedEvent
|
||||
},
|
||||
attributionBuilder: this.attributionBuilder,
|
||||
attributionBuilder,
|
||||
labsService
|
||||
});
|
||||
|
||||
|
@ -185,8 +185,6 @@ function createApiInstance(config) {
|
||||
MemberStatusEvent: models.MemberStatusEvent,
|
||||
MemberProductEvent: models.MemberProductEvent,
|
||||
MemberAnalyticEvent: models.MemberAnalyticEvent,
|
||||
MemberCreatedEvent: models.MemberCreatedEvent,
|
||||
SubscriptionCreatedEvent: models.SubscriptionCreatedEvent,
|
||||
OfferRedemption: models.OfferRedemption,
|
||||
Offer: models.Offer,
|
||||
StripeProduct: models.StripeProduct,
|
||||
|
@ -1,279 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to a page 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1ffbe2896088840a6e9",
|
||||
"title": "This is a static page",
|
||||
"type": "page",
|
||||
"url": "http://127.0.0.1:2369/static-page-test/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-page@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to a page 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": "1955",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to a post 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1ffbe2896088840a6df",
|
||||
"title": "HTML Ipsum",
|
||||
"type": "post",
|
||||
"url": "http://127.0.0.1:2369/html-ipsum/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-post@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to a post 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": "1938",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to a tag 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1febe2896088840a6db",
|
||||
"title": "kitchen sink",
|
||||
"type": "tag",
|
||||
"url": "http://127.0.0.1:2369/tag/kitchen-sink/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-tag@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to a tag 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": "1944",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to an author 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "1",
|
||||
"title": "Joe Bloggs",
|
||||
"type": "author",
|
||||
"url": "http://127.0.0.1:2369/author/joe-bloggs/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-author@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to an author 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": "1926",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to an url 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": null,
|
||||
"title": "/a-static-page/",
|
||||
"type": "url",
|
||||
"url": "http://127.0.0.1:2369/a-static-page/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-url@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Can read member attributed to an url 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": "1922",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Returns sign up attributions in activity feed 1: [body] 1`] = `
|
||||
Object {
|
||||
"events": Array [
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API - member attribution Returns sign up attributions 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": "8381",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Add should fail when passing incorrect email_type query parameter 1: [body] 1`] = `
|
||||
Object {
|
||||
"errors": Array [
|
||||
@ -4022,280 +3748,3 @@ Object {
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": null,
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member1@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": "Mr Egg",
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read 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": "1321",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to a page 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1ffbe2896088840a6e9",
|
||||
"title": "This is a static page",
|
||||
"type": "page",
|
||||
"url": "http://127.0.0.1:2369/static-page-test/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-page@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to a page 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": "1955",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to a post 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1ffbe2896088840a6df",
|
||||
"title": "HTML Ipsum",
|
||||
"type": "post",
|
||||
"url": "http://127.0.0.1:2369/html-ipsum/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-post@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to a post 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": "1938",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to a tag 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1febe2896088840a6db",
|
||||
"title": "kitchen sink",
|
||||
"type": "tag",
|
||||
"url": "http://127.0.0.1:2369/tag/kitchen-sink/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-tag@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to a tag 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": "1944",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to an author 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "1",
|
||||
"title": "Joe Bloggs",
|
||||
"type": "author",
|
||||
"url": "http://127.0.0.1:2369/author/joe-bloggs/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-author@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to an author 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": "1926",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to an url 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": null,
|
||||
"title": "/a-static-page/",
|
||||
"type": "url",
|
||||
"url": "http://127.0.0.1:2369/a-static-page/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": "member-attributed-to-url@test.com",
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "free",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Array [],
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members APi - member attribution Can read member attributed to an url 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": "1922",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
@ -10,10 +10,6 @@ const testUtils = require('../../utils');
|
||||
const Papa = require('papaparse');
|
||||
|
||||
const models = require('../../../core/server/models');
|
||||
const membersService = require('../../../core/server/services/members');
|
||||
const memberAttributionService = require('../../../core/server/services/member-attribution');
|
||||
const urlService = require('../../../core/server/services/url');
|
||||
const urlUtils = require('../../../core/shared/url-utils');
|
||||
|
||||
async function assertMemberEvents({eventType, memberId, asserts}) {
|
||||
const events = await models[eventType].where('member_id', memberId).fetchAll();
|
||||
@ -157,227 +153,6 @@ describe('Members API without Stripe', function () {
|
||||
});
|
||||
});
|
||||
|
||||
// Tests specific for member attribution
|
||||
describe('Members API - member attribution', function () {
|
||||
const signupAttributions = [];
|
||||
|
||||
before(async function () {
|
||||
agent = await agentProvider.getAdminAPIAgent();
|
||||
await fixtureManager.init('posts', 'newsletters', 'members:newsletters', 'comments');
|
||||
await agent.loginAsOwner();
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
mockManager.mockStripe();
|
||||
mockManager.mockMail();
|
||||
|
||||
// For some reason it is enabled by default?
|
||||
mockManager.mockLabsEnabled('memberAttribution');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
mockManager.restore();
|
||||
});
|
||||
|
||||
it('Can read member attributed to a post', async function () {
|
||||
const id = fixtureManager.get('posts', 0).id;
|
||||
const post = await models.Post.where('id', id).fetch({require: true});
|
||||
|
||||
// Set the attribution for this member manually
|
||||
const member = await membersService.api.members.create({
|
||||
email: 'member-attributed-to-post@test.com',
|
||||
attribution: memberAttributionService.attributionBuilder.build({
|
||||
id,
|
||||
url: '/out-of-date/',
|
||||
type: 'post'
|
||||
})
|
||||
});
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(post.id, {absolute: true});
|
||||
|
||||
await agent
|
||||
.get(`/members/${member.id}/`)
|
||||
.expectStatus(200)
|
||||
.matchBodySnapshot({
|
||||
members: new Array(1).fill(memberMatcherShallowIncludes)
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
})
|
||||
.expect(({body}) => {
|
||||
should(body.members[0].attribution).eql({
|
||||
id: post.id,
|
||||
url: absoluteUrl,
|
||||
type: 'post',
|
||||
title: post.get('title')
|
||||
});
|
||||
signupAttributions.push(body.members[0].attribution);
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read member attributed to a page', async function () {
|
||||
const id = fixtureManager.get('posts', 5).id;
|
||||
const post = await models.Post.where('id', id).fetch({require: true});
|
||||
|
||||
// Set the attribution for this member manually
|
||||
const member = await membersService.api.members.create({
|
||||
email: 'member-attributed-to-page@test.com',
|
||||
attribution: memberAttributionService.attributionBuilder.build({
|
||||
id,
|
||||
url: '/out-of-date/',
|
||||
type: 'page'
|
||||
})
|
||||
});
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(post.id, {absolute: true});
|
||||
|
||||
await agent
|
||||
.get(`/members/${member.id}/`)
|
||||
.expectStatus(200)
|
||||
.matchBodySnapshot({
|
||||
members: new Array(1).fill(memberMatcherShallowIncludes)
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
})
|
||||
.expect(({body}) => {
|
||||
should(body.members[0].attribution).eql({
|
||||
id: post.id,
|
||||
url: absoluteUrl,
|
||||
type: 'page',
|
||||
title: post.get('title')
|
||||
});
|
||||
signupAttributions.push(body.members[0].attribution);
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read member attributed to a tag', async function () {
|
||||
const id = fixtureManager.get('tags', 0).id;
|
||||
const tag = await models.Tag.where('id', id).fetch({require: true});
|
||||
|
||||
// Set the attribution for this member manually
|
||||
const member = await membersService.api.members.create({
|
||||
email: 'member-attributed-to-tag@test.com',
|
||||
attribution: memberAttributionService.attributionBuilder.build({
|
||||
id,
|
||||
url: '/out-of-date/',
|
||||
type: 'tag'
|
||||
})
|
||||
});
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(tag.id, {absolute: true});
|
||||
|
||||
await agent
|
||||
.get(`/members/${member.id}/`)
|
||||
.expectStatus(200)
|
||||
.matchBodySnapshot({
|
||||
members: new Array(1).fill(memberMatcherShallowIncludes)
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
})
|
||||
.expect(({body}) => {
|
||||
should(body.members[0].attribution).eql({
|
||||
id: tag.id,
|
||||
url: absoluteUrl,
|
||||
type: 'tag',
|
||||
title: tag.get('name')
|
||||
});
|
||||
signupAttributions.push(body.members[0].attribution);
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read member attributed to an author', async function () {
|
||||
const id = fixtureManager.get('users', 0).id;
|
||||
const author = await models.User.where('id', id).fetch({require: true});
|
||||
|
||||
// Set the attribution for this member manually
|
||||
const member = await membersService.api.members.create({
|
||||
email: 'member-attributed-to-author@test.com',
|
||||
attribution: memberAttributionService.attributionBuilder.build({
|
||||
id,
|
||||
url: '/out-of-date/',
|
||||
type: 'author'
|
||||
})
|
||||
});
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(author.id, {absolute: true});
|
||||
|
||||
await agent
|
||||
.get(`/members/${member.id}/`)
|
||||
.expectStatus(200)
|
||||
.matchBodySnapshot({
|
||||
members: new Array(1).fill(memberMatcherShallowIncludes)
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
})
|
||||
.expect(({body}) => {
|
||||
should(body.members[0].attribution).eql({
|
||||
id: author.id,
|
||||
url: absoluteUrl,
|
||||
type: 'author',
|
||||
title: author.get('name')
|
||||
});
|
||||
signupAttributions.push(body.members[0].attribution);
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read member attributed to an url', async function () {
|
||||
// Set the attribution for this member manually
|
||||
const member = await membersService.api.members.create({
|
||||
email: 'member-attributed-to-url@test.com',
|
||||
attribution: memberAttributionService.attributionBuilder.build({
|
||||
id: null,
|
||||
url: '/a-static-page/',
|
||||
type: 'url'
|
||||
})
|
||||
});
|
||||
|
||||
const absoluteUrl = urlUtils.createUrl('/a-static-page/', true);
|
||||
|
||||
await agent
|
||||
.get(`/members/${member.id}/`)
|
||||
.expectStatus(200)
|
||||
.matchBodySnapshot({
|
||||
members: new Array(1).fill(memberMatcherShallowIncludes)
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
})
|
||||
.expect(({body}) => {
|
||||
should(body.members[0].attribution).eql({
|
||||
id: null,
|
||||
url: absoluteUrl,
|
||||
type: 'url',
|
||||
title: '/a-static-page/'
|
||||
});
|
||||
signupAttributions.push(body.members[0].attribution);
|
||||
});
|
||||
});
|
||||
|
||||
// Activity feed
|
||||
it('Returns sign up attributions in activity feed', async function () {
|
||||
// Check activity feed
|
||||
await agent
|
||||
.get(`/members/events/?filter=type:signup_event`)
|
||||
.expectStatus(200)
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
})
|
||||
.matchBodySnapshot({
|
||||
events: new Array(signupAttributions.length).fill({
|
||||
type: anyString,
|
||||
data: anyObject
|
||||
})
|
||||
})
|
||||
.expect(({body}) => {
|
||||
should(body.events.find(e => e.type !== 'signup_event')).be.undefined();
|
||||
should(body.events.map(e => e.data.attribution)).containDeep(signupAttributions);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Members API', function () {
|
||||
let newsletters;
|
||||
|
||||
|
@ -1,448 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with author attribution 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "1",
|
||||
"title": "Joe Bloggs",
|
||||
"type": "author",
|
||||
"url": "http://127.0.0.1:2369/author/joe-bloggs/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": Any<String>,
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "paid",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Any<Array>,
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with author attribution 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": "2795",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with deleted post attribution 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": null,
|
||||
"title": "/removed-blog-post/",
|
||||
"type": "url",
|
||||
"url": "http://127.0.0.1:2369/removed-blog-post/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": Any<String>,
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "paid",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Any<Array>,
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with deleted post attribution 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": "2809",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with empty attribution object 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": null,
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": Any<String>,
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "paid",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Any<Array>,
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with empty attribution object 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": "2611",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with page attribution 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1ffbe2896088840a6e9",
|
||||
"title": "This is a static page",
|
||||
"type": "page",
|
||||
"url": "http://127.0.0.1:2369/static-page-test/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": Any<String>,
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "paid",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Any<Array>,
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with page attribution 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": "2857",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with post attribution 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1ffbe2896088840a6df",
|
||||
"title": "HTML Ipsum",
|
||||
"type": "post",
|
||||
"url": "http://127.0.0.1:2369/html-ipsum/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": Any<String>,
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "paid",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Any<Array>,
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with post attribution 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": "2823",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with tag attribution 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": "618ba1febe2896088840a6db",
|
||||
"title": "kitchen sink",
|
||||
"type": "tag",
|
||||
"url": "http://127.0.0.1:2369/tag/kitchen-sink/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": Any<String>,
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "paid",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Any<Array>,
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with tag attribution 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": "2837",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with url attribution 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": Object {
|
||||
"id": null,
|
||||
"title": "/",
|
||||
"type": "url",
|
||||
"url": "http://127.0.0.1:2369/",
|
||||
},
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": Any<String>,
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "paid",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Any<Array>,
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent with url attribution 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": "2737",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent without attribution 1: [body] 1`] = `
|
||||
Object {
|
||||
"members": Array [
|
||||
Object {
|
||||
"attribution": null,
|
||||
"avatar_image": null,
|
||||
"comped": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"email": Any<String>,
|
||||
"email_count": 0,
|
||||
"email_open_rate": null,
|
||||
"email_opened_count": 0,
|
||||
"geolocation": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"labels": Any<Array>,
|
||||
"last_seen_at": null,
|
||||
"name": null,
|
||||
"newsletters": Any<Array>,
|
||||
"note": null,
|
||||
"status": "paid",
|
||||
"subscribed": true,
|
||||
"subscriptions": Any<Array>,
|
||||
"tiers": Any<Array>,
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Creates a SubscriptionCreatedEvent without attribution 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": "2611",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Returns subscription created attributions in activity feed 1: [body] 1`] = `
|
||||
Object {
|
||||
"events": Array [
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"data": Any<Object>,
|
||||
"type": Any<String>,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Returns subscription created attributions in activity feed 1: [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": "7784",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution Returns subscription created attributions 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": "13390",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution empty initial activity feed 1: [body] 1`] = `
|
||||
Object {
|
||||
"events": Array [],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Members API Member attribution empty initial 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": "13",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
File diff suppressed because it is too large
Load Diff
@ -33,7 +33,7 @@ describe('Member Attribution Service', function () {
|
||||
type: 'url'
|
||||
}));
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: null,
|
||||
url: absoluteUrl,
|
||||
type: 'url',
|
||||
@ -60,7 +60,7 @@ describe('Member Attribution Service', function () {
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(post.id, {absolute: true, withSubdirectory: true});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: post.id,
|
||||
url: absoluteUrl,
|
||||
type: 'post',
|
||||
@ -92,7 +92,7 @@ describe('Member Attribution Service', function () {
|
||||
// Unpublish this post
|
||||
await models.Post.edit({status: 'draft'}, {id});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: null,
|
||||
url: absoluteUrl,
|
||||
type: 'url',
|
||||
@ -123,7 +123,7 @@ describe('Member Attribution Service', function () {
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(post.id, {absolute: true, withSubdirectory: true});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: post.id,
|
||||
url: absoluteUrl,
|
||||
type: 'page',
|
||||
@ -150,7 +150,7 @@ describe('Member Attribution Service', function () {
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(tag.id, {absolute: true, withSubdirectory: true});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: tag.id,
|
||||
url: absoluteUrl,
|
||||
type: 'tag',
|
||||
@ -177,7 +177,7 @@ describe('Member Attribution Service', function () {
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(author.id, {absolute: true, withSubdirectory: true});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: author.id,
|
||||
url: absoluteUrl,
|
||||
type: 'author',
|
||||
@ -212,7 +212,7 @@ describe('Member Attribution Service', function () {
|
||||
type: 'url'
|
||||
}));
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: null,
|
||||
url: absoluteUrl,
|
||||
type: 'url',
|
||||
@ -245,7 +245,7 @@ describe('Member Attribution Service', function () {
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(post.id, {absolute: true, withSubdirectory: true});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: post.id,
|
||||
url: absoluteUrl,
|
||||
type: 'post',
|
||||
@ -280,7 +280,7 @@ describe('Member Attribution Service', function () {
|
||||
// Unpublish this post
|
||||
await models.Post.edit({status: 'draft'}, {id});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: null,
|
||||
url: absoluteUrl,
|
||||
type: 'url',
|
||||
@ -310,7 +310,7 @@ describe('Member Attribution Service', function () {
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(post.id, {absolute: true, withSubdirectory: true});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: post.id,
|
||||
url: absoluteUrl,
|
||||
type: 'page',
|
||||
@ -338,7 +338,7 @@ describe('Member Attribution Service', function () {
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(tag.id, {absolute: true, withSubdirectory: true});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: tag.id,
|
||||
url: absoluteUrl,
|
||||
type: 'tag',
|
||||
@ -366,7 +366,7 @@ describe('Member Attribution Service', function () {
|
||||
|
||||
const absoluteUrl = urlService.getUrlByResourceId(author.id, {absolute: true, withSubdirectory: true});
|
||||
|
||||
(await attribution.fetchResource()).should.match(({
|
||||
(await attribution.getResource()).should.match(({
|
||||
id: author.id,
|
||||
url: absoluteUrl,
|
||||
type: 'author',
|
||||
|
@ -478,27 +478,6 @@ const fixtures = {
|
||||
return models.Product.add(archivedProduct, context.internal);
|
||||
},
|
||||
|
||||
insertProducts: async function insertProducts() {
|
||||
let coreProductFixtures = fixtureManager.findModelFixtures('Product').entries;
|
||||
await Promise.map(coreProductFixtures, async (product) => {
|
||||
const found = await models.Product.findOne(product, context.internal);
|
||||
if (!found) {
|
||||
await models.Product.add(product, context.internal);
|
||||
}
|
||||
});
|
||||
|
||||
const product = await models.Product.findOne({type: 'paid'}, context.internal);
|
||||
|
||||
await Promise.each(_.cloneDeep(DataGenerator.forKnex.stripe_products), function (stripeProduct) {
|
||||
stripeProduct.product_id = product.id;
|
||||
return models.StripeProduct.add(stripeProduct, context.internal);
|
||||
});
|
||||
|
||||
await Promise.each(_.cloneDeep(DataGenerator.forKnex.stripe_prices), function (stripePrice) {
|
||||
return models.StripePrice.add(stripePrice, context.internal);
|
||||
});
|
||||
},
|
||||
|
||||
insertMembersAndLabelsAndProducts: function insertMembersAndLabelsAndProducts(newsletters = false) {
|
||||
return Promise.map(DataGenerator.forKnex.labels, function (label) {
|
||||
return models.Label.add(label, context.internal);
|
||||
@ -705,9 +684,6 @@ const toDoList = {
|
||||
members: function insertMembersAndLabelsAndProducts() {
|
||||
return fixtures.insertMembersAndLabelsAndProducts(false);
|
||||
},
|
||||
products: function insertProducts() {
|
||||
return fixtures.insertProducts();
|
||||
},
|
||||
newsletters: function insertNewsletters() {
|
||||
return fixtures.insertNewsletters();
|
||||
},
|
||||
|
@ -27,16 +27,15 @@ class Attribution {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the instance to a parsed instance with more information about the resource included.
|
||||
* Convert the instance to a parsed instance with more information about the resource included.
|
||||
* It does:
|
||||
* - Uses the passed model and adds a title to the attribution
|
||||
* - If the resource exists and has a new url, it updates the url if possible
|
||||
* - Fetch the resource and add some information about it to the attribution
|
||||
* - If the resource exists and have a new url, it updates the url if possible
|
||||
* - Returns an absolute URL instead of a relative one
|
||||
* @param {Object|null} [model] The Post/User/Tag model of the resource associated with this attribution
|
||||
* @returns {AttributionResource}
|
||||
* @returns {Promise<AttributionResource>}
|
||||
*/
|
||||
getResource(model) {
|
||||
if (!this.id || this.type === 'url' || !this.type || !model) {
|
||||
async getResource() {
|
||||
if (!this.id || this.type === 'url' || !this.type) {
|
||||
return {
|
||||
id: null,
|
||||
type: 'url',
|
||||
@ -45,28 +44,18 @@ class Attribution {
|
||||
};
|
||||
}
|
||||
|
||||
const updatedUrl = this.#urlTranslator.getUrlByResourceId(this.id, {absolute: true});
|
||||
const resource = await this.#urlTranslator.getResourceById(this.id, this.type, {absolute: true});
|
||||
|
||||
return {
|
||||
id: model.id,
|
||||
type: this.type,
|
||||
url: updatedUrl,
|
||||
title: model.get('title') ?? model.get('name') ?? this.url
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as getResource, but fetches the model by ID instead of passing it as a parameter
|
||||
*/
|
||||
async fetchResource() {
|
||||
if (!this.id || this.type === 'url' || !this.type) {
|
||||
// No fetch required
|
||||
return this.getResource();
|
||||
if (resource) {
|
||||
return resource;
|
||||
}
|
||||
|
||||
// Fetch model
|
||||
const model = await this.#urlTranslator.getResourceById(this.id, this.type, {absolute: true});
|
||||
return this.getResource(model);
|
||||
return {
|
||||
id: null,
|
||||
type: 'url',
|
||||
url: this.#urlTranslator.relativeToAbsolute(this.url),
|
||||
title: this.url
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,47 +24,13 @@ class MemberAttributionService {
|
||||
return this.attributionBuilder.getAttribution(history);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribution resource for a given event model (MemberCreatedEvent / SubscriptionCreatedEvent), where the model has the required relations already loaded
|
||||
* You need to already load the 'postAttribution', 'userAttribution', and 'tagAttribution' relations
|
||||
* @param {Object} eventModel MemberCreatedEvent or SubscriptionCreatedEvent
|
||||
* @returns {import('./attribution').AttributionResource|null}
|
||||
*/
|
||||
getEventAttribution(eventModel) {
|
||||
if (eventModel.get('attribution_type') === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const _attribution = this.attributionBuilder.build({
|
||||
id: eventModel.get('attribution_id'),
|
||||
url: eventModel.get('attribution_url'),
|
||||
type: eventModel.get('attribution_type')
|
||||
});
|
||||
|
||||
if (_attribution.type !== 'url') {
|
||||
// Find the right relation to use to fetch the resource
|
||||
const tryRelations = [
|
||||
eventModel.related('postAttribution'),
|
||||
eventModel.related('userAttribution'),
|
||||
eventModel.related('tagAttribution')
|
||||
];
|
||||
for (const relation of tryRelations) {
|
||||
if (relation && relation.id) {
|
||||
// We need to check the ID, because .related() always returs a model when eager loaded, even when the relation didn't exist
|
||||
return _attribution.getResource(relation);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _attribution.getResource(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parsed attribution for a member creation event
|
||||
* @param {string} memberId
|
||||
* @returns {Promise<import('./attribution').AttributionResource|null>}
|
||||
*/
|
||||
async getMemberCreatedAttribution(memberId) {
|
||||
const memberCreatedEvent = await this.models.MemberCreatedEvent.findOne({member_id: memberId}, {require: false, withRelated: []});
|
||||
const memberCreatedEvent = await this.models.MemberCreatedEvent.findOne({member_id: memberId}, {require: false});
|
||||
if (!memberCreatedEvent || !memberCreatedEvent.get('attribution_type')) {
|
||||
return null;
|
||||
}
|
||||
@ -73,7 +39,7 @@ class MemberAttributionService {
|
||||
url: memberCreatedEvent.get('attribution_url'),
|
||||
type: memberCreatedEvent.get('attribution_type')
|
||||
});
|
||||
return await attribution.fetchResource();
|
||||
return await attribution.getResource();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,7 +48,7 @@ class MemberAttributionService {
|
||||
* @returns {Promise<import('./attribution').AttributionResource|null>}
|
||||
*/
|
||||
async getSubscriptionCreatedAttribution(subscriptionId) {
|
||||
const subscriptionCreatedEvent = await this.models.SubscriptionCreatedEvent.findOne({subscription_id: subscriptionId}, {require: false, withRelated: []});
|
||||
const subscriptionCreatedEvent = await this.models.SubscriptionCreatedEvent.findOne({subscription_id: subscriptionId}, {require: false});
|
||||
if (!subscriptionCreatedEvent || !subscriptionCreatedEvent.get('attribution_type')) {
|
||||
return null;
|
||||
}
|
||||
@ -91,7 +57,7 @@ class MemberAttributionService {
|
||||
url: subscriptionCreatedEvent.get('attribution_url'),
|
||||
type: subscriptionCreatedEvent.get('attribution_type')
|
||||
});
|
||||
return await attribution.fetchResource();
|
||||
return await attribution.getResource();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Translate a url into, (id+type), or a resource, and vice versa
|
||||
* Translate a url into a type and id
|
||||
* And also in reverse
|
||||
*/
|
||||
class UrlTranslator {
|
||||
/**
|
||||
@ -80,11 +81,9 @@ class UrlTranslator {
|
||||
}
|
||||
}
|
||||
|
||||
getUrlByResourceId(id, options = {absolute: true}) {
|
||||
return this.urlService.getUrlByResourceId(id, options);
|
||||
}
|
||||
async getResourceById(id, type, options = {absolute: true}) {
|
||||
const url = this.urlService.getUrlByResourceId(id, options);
|
||||
|
||||
async getResourceById(id, type) {
|
||||
switch (type) {
|
||||
case 'post':
|
||||
case 'page': {
|
||||
@ -93,7 +92,12 @@ class UrlTranslator {
|
||||
return null;
|
||||
}
|
||||
|
||||
return post;
|
||||
return {
|
||||
id: post.id,
|
||||
type,
|
||||
url,
|
||||
title: post.get('title')
|
||||
};
|
||||
}
|
||||
case 'author': {
|
||||
const user = await this.models.User.findOne({id}, {require: false});
|
||||
@ -101,7 +105,12 @@ class UrlTranslator {
|
||||
return null;
|
||||
}
|
||||
|
||||
return user;
|
||||
return {
|
||||
id: user.id,
|
||||
type,
|
||||
url,
|
||||
title: user.get('name')
|
||||
};
|
||||
}
|
||||
case 'tag': {
|
||||
const tag = await this.models.Tag.findOne({id}, {require: false});
|
||||
@ -109,7 +118,12 @@ class UrlTranslator {
|
||||
return null;
|
||||
}
|
||||
|
||||
return tag;
|
||||
return {
|
||||
id: tag.id,
|
||||
type,
|
||||
url,
|
||||
title: tag.get('name')
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -25,20 +25,17 @@ describe('AttributionBuilder', function () {
|
||||
}
|
||||
return;
|
||||
},
|
||||
getResourceById(id) {
|
||||
getResourceById(id, type) {
|
||||
if (id === 'invalid') {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
id,
|
||||
get() {
|
||||
return 'Title';
|
||||
}
|
||||
type,
|
||||
url: 'https://absolute/dir/path',
|
||||
title: 'Title'
|
||||
};
|
||||
},
|
||||
getUrlByResourceId() {
|
||||
return 'https://absolute/dir/path';
|
||||
},
|
||||
relativeToAbsolute(path) {
|
||||
return 'https://absolute/dir' + path;
|
||||
},
|
||||
@ -108,7 +105,7 @@ describe('AttributionBuilder', function () {
|
||||
});
|
||||
|
||||
it('Returns post resource', async function () {
|
||||
should(await attributionBuilder.build({type: 'post', id: '123', url: '/post'}).fetchResource()).match({
|
||||
should(await attributionBuilder.build({type: 'post', id: '123', url: '/post'}).getResource()).match({
|
||||
type: 'post',
|
||||
id: '123',
|
||||
url: 'https://absolute/dir/path',
|
||||
@ -117,7 +114,7 @@ describe('AttributionBuilder', function () {
|
||||
});
|
||||
|
||||
it('Returns url resource', async function () {
|
||||
should(await attributionBuilder.build({type: 'url', id: null, url: '/url'}).fetchResource()).match({
|
||||
should(await attributionBuilder.build({type: 'url', id: null, url: '/url'}).getResource()).match({
|
||||
type: 'url',
|
||||
id: null,
|
||||
url: 'https://absolute/dir/url',
|
||||
@ -126,7 +123,7 @@ describe('AttributionBuilder', function () {
|
||||
});
|
||||
|
||||
it('Returns url resource if not found', async function () {
|
||||
should(await attributionBuilder.build({type: 'post', id: 'invalid', url: '/post'}).fetchResource()).match({
|
||||
should(await attributionBuilder.build({type: 'post', id: 'invalid', url: '/post'}).getResource()).match({
|
||||
type: 'url',
|
||||
id: null,
|
||||
url: 'https://absolute/dir/post',
|
||||
|
@ -9,97 +9,4 @@ describe('MemberAttributionService', function () {
|
||||
new MemberAttributionService({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEventAttribution', function () {
|
||||
it('returns null if attribution_type is null', function () {
|
||||
const service = new MemberAttributionService({});
|
||||
const model = {
|
||||
id: 'event_id',
|
||||
get() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
should(service.getEventAttribution(model)).eql(null);
|
||||
});
|
||||
|
||||
it('returns url attribution types', function () {
|
||||
const service = new MemberAttributionService({
|
||||
attributionBuilder: {
|
||||
build(attribution) {
|
||||
return {
|
||||
...attribution,
|
||||
getResource() {
|
||||
return {
|
||||
...attribution,
|
||||
title: 'added'
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
const model = {
|
||||
id: 'event_id',
|
||||
get(name) {
|
||||
if (name === 'attribution_type') {
|
||||
return 'url';
|
||||
}
|
||||
if (name === 'attribution_url') {
|
||||
return '/my/url/';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
should(service.getEventAttribution(model)).eql({
|
||||
id: null,
|
||||
type: 'url',
|
||||
url: '/my/url/',
|
||||
title: 'added'
|
||||
});
|
||||
});
|
||||
|
||||
it('returns first loaded relation', function () {
|
||||
const service = new MemberAttributionService({
|
||||
attributionBuilder: {
|
||||
build(attribution) {
|
||||
return {
|
||||
...attribution,
|
||||
getResource() {
|
||||
return {
|
||||
...attribution,
|
||||
title: 'added'
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
const model = {
|
||||
id: 'event_id',
|
||||
get(name) {
|
||||
if (name === 'attribution_type') {
|
||||
return 'user';
|
||||
}
|
||||
if (name === 'attribution_url') {
|
||||
return '/my/url/';
|
||||
}
|
||||
return 'test_user_id';
|
||||
},
|
||||
related(name) {
|
||||
if (name === 'userAttribution') {
|
||||
return {
|
||||
id: 'test_user_id'
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
should(service.getEventAttribution(model)).eql({
|
||||
id: 'test_user_id',
|
||||
type: 'user',
|
||||
url: '/my/url/',
|
||||
title: 'added'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -111,26 +111,38 @@ describe('UrlTranslator', function () {
|
||||
});
|
||||
|
||||
it('returns for post', async function () {
|
||||
should(await translator.getResourceById('id', 'post')).match({
|
||||
id: 'post_id'
|
||||
should(await translator.getResourceById('id', 'post')).eql({
|
||||
type: 'post',
|
||||
id: 'post_id',
|
||||
title: 'Title',
|
||||
url: '/path'
|
||||
});
|
||||
});
|
||||
|
||||
it('returns for page', async function () {
|
||||
should(await translator.getResourceById('id', 'page')).match({
|
||||
id: 'post_id'
|
||||
should(await translator.getResourceById('id', 'page')).eql({
|
||||
type: 'page',
|
||||
id: 'post_id',
|
||||
title: 'Title',
|
||||
url: '/path'
|
||||
});
|
||||
});
|
||||
|
||||
it('returns for tag', async function () {
|
||||
should(await translator.getResourceById('id', 'tag')).match({
|
||||
id: 'tag_id'
|
||||
should(await translator.getResourceById('id', 'tag')).eql({
|
||||
type: 'tag',
|
||||
id: 'tag_id',
|
||||
title: 'Title',
|
||||
url: '/path'
|
||||
});
|
||||
});
|
||||
|
||||
it('returns for user', async function () {
|
||||
should(await translator.getResourceById('id', 'author')).match({
|
||||
id: 'user_id'
|
||||
should(await translator.getResourceById('id', 'author')).eql({
|
||||
type: 'author',
|
||||
id: 'user_id',
|
||||
title: 'Title',
|
||||
url: '/path'
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -48,8 +48,6 @@ module.exports = function MembersAPI({
|
||||
MemberProductEvent,
|
||||
MemberEmailChangeEvent,
|
||||
MemberAnalyticEvent,
|
||||
MemberCreatedEvent,
|
||||
SubscriptionCreatedEvent,
|
||||
Offer,
|
||||
OfferRedemption,
|
||||
StripeProduct,
|
||||
@ -107,11 +105,8 @@ module.exports = function MembersAPI({
|
||||
MemberPaymentEvent,
|
||||
MemberStatusEvent,
|
||||
MemberLoginEvent,
|
||||
MemberCreatedEvent,
|
||||
SubscriptionCreatedEvent,
|
||||
Comment,
|
||||
labsService,
|
||||
memberAttributionService
|
||||
labsService
|
||||
});
|
||||
|
||||
const memberBREADService = new MemberBREADService({
|
||||
|
@ -8,12 +8,9 @@ module.exports = class EventRepository {
|
||||
MemberPaymentEvent,
|
||||
MemberStatusEvent,
|
||||
MemberLoginEvent,
|
||||
MemberCreatedEvent,
|
||||
SubscriptionCreatedEvent,
|
||||
MemberPaidSubscriptionEvent,
|
||||
Comment,
|
||||
labsService,
|
||||
memberAttributionService
|
||||
labsService
|
||||
}) {
|
||||
this._MemberSubscribeEvent = MemberSubscribeEvent;
|
||||
this._MemberPaidSubscriptionEvent = MemberPaidSubscriptionEvent;
|
||||
@ -23,9 +20,6 @@ module.exports = class EventRepository {
|
||||
this._EmailRecipient = EmailRecipient;
|
||||
this._Comment = Comment;
|
||||
this._labsService = labsService;
|
||||
this._MemberCreatedEvent = MemberCreatedEvent;
|
||||
this._SubscriptionCreatedEvent = SubscriptionCreatedEvent;
|
||||
this._memberAttributionService = memberAttributionService;
|
||||
}
|
||||
|
||||
async registerPayment(data) {
|
||||
@ -68,38 +62,9 @@ module.exports = class EventRepository {
|
||||
}
|
||||
|
||||
async getSubscriptionEvents(options = {}, filters = {}) {
|
||||
if (!this._labsService.isSet('memberAttribution')){
|
||||
options = {
|
||||
...options,
|
||||
withRelated: ['member'],
|
||||
filter: []
|
||||
};
|
||||
if (filters['data.created_at']) {
|
||||
options.filter.push(filters['data.created_at'].replace(/data.created_at:/g, 'created_at:'));
|
||||
}
|
||||
if (filters['data.member_id']) {
|
||||
options.filter.push(filters['data.member_id'].replace(/data.member_id:/g, 'member_id:'));
|
||||
}
|
||||
options.filter = options.filter.join('+');
|
||||
|
||||
const {data: models, meta} = await this._MemberPaidSubscriptionEvent.findPage(options);
|
||||
|
||||
const data = models.map((model) => {
|
||||
return {
|
||||
type: 'subscription_event',
|
||||
data: model.toJSON(options)
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
meta
|
||||
};
|
||||
}
|
||||
|
||||
options = {
|
||||
...options,
|
||||
withRelated: ['member', 'subscriptionCreatedEvent.postAttribution', 'subscriptionCreatedEvent.userAttribution', 'subscriptionCreatedEvent.tagAttribution'],
|
||||
withRelated: ['member'],
|
||||
filter: []
|
||||
};
|
||||
if (filters['data.created_at']) {
|
||||
@ -115,10 +80,7 @@ module.exports = class EventRepository {
|
||||
const data = models.map((model) => {
|
||||
return {
|
||||
type: 'subscription_event',
|
||||
data: {
|
||||
...model.toJSON(options),
|
||||
attribution: model.get('type') === 'created' && model.related('subscriptionCreatedEvent') && model.related('subscriptionCreatedEvent').id ? this._memberAttributionService.getEventAttribution(model.related('subscriptionCreatedEvent')) : null
|
||||
}
|
||||
data: model.toJSON(options)
|
||||
};
|
||||
});
|
||||
|
||||
@ -187,39 +149,10 @@ module.exports = class EventRepository {
|
||||
}
|
||||
|
||||
async getSignupEvents(options = {}, filters = {}) {
|
||||
if (!this._labsService.isSet('memberAttribution')){
|
||||
options = {
|
||||
...options,
|
||||
withRelated: ['member'],
|
||||
filter: ['from_status:null']
|
||||
};
|
||||
if (filters['data.created_at']) {
|
||||
options.filter.push(filters['data.created_at'].replace(/data.created_at:/g, 'created_at:'));
|
||||
}
|
||||
if (filters['data.member_id']) {
|
||||
options.filter.push(filters['data.member_id'].replace(/data.member_id:/g, 'member_id:'));
|
||||
}
|
||||
options.filter = options.filter.join('+');
|
||||
|
||||
const {data: models, meta} = await this._MemberStatusEvent.findPage(options);
|
||||
|
||||
const data = models.map((model) => {
|
||||
return {
|
||||
type: 'signup_event',
|
||||
data: model.toJSON(options)
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
meta
|
||||
};
|
||||
}
|
||||
|
||||
options = {
|
||||
...options,
|
||||
withRelated: ['member', 'postAttribution', 'userAttribution', 'tagAttribution'],
|
||||
filter: []
|
||||
withRelated: ['member'],
|
||||
filter: ['from_status:null']
|
||||
};
|
||||
if (filters['data.created_at']) {
|
||||
options.filter.push(filters['data.created_at'].replace(/data.created_at:/g, 'created_at:'));
|
||||
@ -229,15 +162,12 @@ module.exports = class EventRepository {
|
||||
}
|
||||
options.filter = options.filter.join('+');
|
||||
|
||||
const {data: models, meta} = await this._MemberCreatedEvent.findPage(options);
|
||||
const {data: models, meta} = await this._MemberStatusEvent.findPage(options);
|
||||
|
||||
const data = models.map((model) => {
|
||||
return {
|
||||
type: 'signup_event',
|
||||
data: {
|
||||
...model.toJSON(options),
|
||||
attribution: this._memberAttributionService.getEventAttribution(model)
|
||||
}
|
||||
data: model.toJSON(options)
|
||||
};
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user