Renamed reason to description in recommendations table (#18527)
fixes https://github.com/TryGhost/Product/issues/4005 We no longer use the 'reason' of a recommendation, but allow a flexible description instead. Because this is a breaking change in the API, we do this before making this feature GA. - Added new database utils for renaming a column - Added new migration to rename the column - Updated all references in code
This commit is contained in:
parent
a2dd0ea1ca
commit
9abd466397
@ -4,7 +4,7 @@ import {Meta, apiUrl, createInfiniteQuery, createMutation, useFetchApi} from '..
|
||||
export type Recommendation = {
|
||||
id: string
|
||||
title: string
|
||||
reason: string|null
|
||||
description: string|null
|
||||
excerpt: string|null // Fetched from the site meta data
|
||||
featured_image: string|null // Fetched from the site meta data
|
||||
favicon: string|null // Fetched from the site meta data
|
||||
|
@ -61,7 +61,7 @@ const AddRecommendationModal: React.FC<RoutingModalProps & AddRecommendationModa
|
||||
initialState: recommendation ?? {
|
||||
title: '',
|
||||
url: initialUrlCleaned,
|
||||
reason: '',
|
||||
description: '',
|
||||
excerpt: null,
|
||||
featured_image: null,
|
||||
favicon: null,
|
||||
@ -119,7 +119,7 @@ const AddRecommendationModal: React.FC<RoutingModalProps & AddRecommendationModa
|
||||
updatedRecommendation.favicon = oembed?.metadata?.icon ?? formState.favicon ?? null;
|
||||
updatedRecommendation.one_click_subscribe = false;
|
||||
}
|
||||
updatedRecommendation.reason = updatedRecommendation.excerpt || null;
|
||||
updatedRecommendation.description = updatedRecommendation.excerpt || null;
|
||||
|
||||
// Switch modal without changing the route (the second modal is not reachable by URL)
|
||||
modal.remove();
|
||||
|
@ -2,7 +2,7 @@ import AddRecommendationModal from './AddRecommendationModal';
|
||||
import Modal from '../../../../admin-x-ds/global/modal/Modal';
|
||||
import NiceModal, {useModal} from '@ebay/nice-modal-react';
|
||||
import React from 'react';
|
||||
import RecommendationReasonForm, {validateReasonForm} from './RecommendationReasonForm';
|
||||
import RecommendationDescriptionForm, {validateDescriptionForm} from './RecommendationDescriptionForm';
|
||||
import trackEvent from '../../../../utils/plausible';
|
||||
import useForm from '../../../../hooks/useForm';
|
||||
import useHandleError from '../../../../utils/api/handleError';
|
||||
@ -39,7 +39,7 @@ const AddRecommendationModalConfirm: React.FC<AddRecommendationModalProps> = ({r
|
||||
},
|
||||
onSaveError: handleError,
|
||||
onValidate: (state) => {
|
||||
const newErrors = validateReasonForm(state);
|
||||
const newErrors = validateDescriptionForm(state);
|
||||
|
||||
if (Object.keys(newErrors).length !== 0) {
|
||||
showToast({
|
||||
@ -127,7 +127,7 @@ const AddRecommendationModalConfirm: React.FC<AddRecommendationModalProps> = ({r
|
||||
}
|
||||
}}
|
||||
>
|
||||
<RecommendationReasonForm clearError={clearError} errors={errors} formState={formState} setErrors={setErrors} showURL={false} updateForm={updateForm}/>
|
||||
<RecommendationDescriptionForm clearError={clearError} errors={errors} formState={formState} setErrors={setErrors} showURL={false} updateForm={updateForm}/>
|
||||
</Modal>;
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@ import ConfirmationModal from '../../../../admin-x-ds/global/modal/ConfirmationM
|
||||
import Modal from '../../../../admin-x-ds/global/modal/Modal';
|
||||
import NiceModal, {useModal} from '@ebay/nice-modal-react';
|
||||
import React from 'react';
|
||||
import RecommendationReasonForm, {validateReasonForm} from './RecommendationReasonForm';
|
||||
import RecommendationDescriptionForm, {validateDescriptionForm} from './RecommendationDescriptionForm';
|
||||
import useForm from '../../../../hooks/useForm';
|
||||
import useHandleError from '../../../../utils/api/handleError';
|
||||
import useRouting from '../../../../hooks/useRouting';
|
||||
@ -33,7 +33,7 @@ const EditRecommendationModal: React.FC<RoutingModalProps & EditRecommendationMo
|
||||
},
|
||||
onSaveError: handleError,
|
||||
onValidate: (state) => {
|
||||
const newErrors = validateReasonForm(state);
|
||||
const newErrors = validateDescriptionForm(state);
|
||||
|
||||
if (Object.keys(newErrors).length !== 0) {
|
||||
showToast({
|
||||
@ -119,7 +119,7 @@ const EditRecommendationModal: React.FC<RoutingModalProps & EditRecommendationMo
|
||||
}
|
||||
}}
|
||||
>
|
||||
<RecommendationReasonForm clearError={clearError} errors={errors} formState={formState} setErrors={setErrors} showURL={true} updateForm={updateForm as any}/>
|
||||
<RecommendationDescriptionForm clearError={clearError} errors={errors} formState={formState} setErrors={setErrors} showURL={true} updateForm={updateForm as any}/>
|
||||
</Modal>;
|
||||
};
|
||||
|
||||
|
@ -18,7 +18,7 @@ interface Props<T extends EditOrAddRecommendation> {
|
||||
setErrors: (errors: ErrorMessages) => void
|
||||
}
|
||||
|
||||
export const validateReasonFormField = function (errors: ErrorMessages, field: 'title'|'reason', value: string|null) {
|
||||
export const validateDescriptionFormField = function (errors: ErrorMessages, field: 'title'|'description', value: string|null) {
|
||||
const cloned = {...errors};
|
||||
switch (field) {
|
||||
case 'title':
|
||||
@ -28,11 +28,11 @@ export const validateReasonFormField = function (errors: ErrorMessages, field: '
|
||||
delete cloned.title;
|
||||
}
|
||||
break;
|
||||
case 'reason':
|
||||
case 'description':
|
||||
if (value && value.length > 200) {
|
||||
cloned.reason = 'Description cannot be longer than 200 characters';
|
||||
cloned.description = 'Description cannot be longer than 200 characters';
|
||||
} else {
|
||||
delete cloned.reason;
|
||||
delete cloned.description;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -43,16 +43,16 @@ export const validateReasonFormField = function (errors: ErrorMessages, field: '
|
||||
return cloned;
|
||||
};
|
||||
|
||||
export const validateReasonForm = function (formState: EditOrAddRecommendation) {
|
||||
export const validateDescriptionForm = function (formState: EditOrAddRecommendation) {
|
||||
let newErrors: ErrorMessages = {};
|
||||
newErrors = validateReasonFormField(newErrors, 'title', formState.title);
|
||||
newErrors = validateReasonFormField(newErrors, 'reason', formState.reason);
|
||||
newErrors = validateDescriptionFormField(newErrors, 'title', formState.title);
|
||||
newErrors = validateDescriptionFormField(newErrors, 'description', formState.description);
|
||||
return newErrors;
|
||||
};
|
||||
|
||||
const RecommendationReasonForm: React.FC<Props<EditOrAddRecommendation | Recommendation>> = ({showURL, formState, updateForm, errors, clearError, setErrors}) => {
|
||||
const [reasonLength, setReasonLength] = React.useState(formState?.reason?.length || 0);
|
||||
const reasonLengthColor = reasonLength > 200 ? 'text-red' : 'text-green';
|
||||
const RecommendationDescriptionForm: React.FC<Props<EditOrAddRecommendation | Recommendation>> = ({showURL, formState, updateForm, errors, clearError, setErrors}) => {
|
||||
const [descriptionLength, setDescriptionLength] = React.useState(formState?.description?.length || 0);
|
||||
const descriptionLengthColor = descriptionLength > 200 ? 'text-red' : 'text-green';
|
||||
|
||||
// Do an intial validation on mounting
|
||||
const didValidate = React.useRef(false);
|
||||
@ -61,7 +61,7 @@ const RecommendationReasonForm: React.FC<Props<EditOrAddRecommendation | Recomme
|
||||
return;
|
||||
}
|
||||
didValidate.current = true;
|
||||
setErrors(validateReasonForm(formState));
|
||||
setErrors(validateDescriptionForm(formState));
|
||||
}, [formState, setErrors]);
|
||||
|
||||
return <Form
|
||||
@ -79,7 +79,7 @@ const RecommendationReasonForm: React.FC<Props<EditOrAddRecommendation | Recomme
|
||||
<RecommendationIcon {...formState} />
|
||||
<span className='text-[1.6rem] font-semibold text-grey-900'>{formState.title}</span>
|
||||
</div>
|
||||
{formState.reason && <span className='pl-[31px] text-[1.35rem] leading-snug text-grey-700'>{formState.reason}</span>}
|
||||
{formState.description && <span className='pl-[31px] text-[1.35rem] leading-snug text-grey-700'>{formState.description}</span>}
|
||||
</div>
|
||||
{formState.one_click_subscribe && <span className='flex whitespace-nowrap pl-6 text-md font-semibold text-green'>Subscribe</span>}
|
||||
</a>
|
||||
@ -108,7 +108,7 @@ const RecommendationReasonForm: React.FC<Props<EditOrAddRecommendation | Recomme
|
||||
title="Title"
|
||||
value={formState.title ?? ''}
|
||||
onBlur={() => setErrors(
|
||||
validateReasonFormField(errors, 'title', formState.title)
|
||||
validateDescriptionFormField(errors, 'title', formState.title)
|
||||
)}
|
||||
onChange={(e) => {
|
||||
clearError?.('title');
|
||||
@ -117,22 +117,22 @@ const RecommendationReasonForm: React.FC<Props<EditOrAddRecommendation | Recomme
|
||||
/>
|
||||
<TextArea
|
||||
clearBg={true}
|
||||
error={Boolean(errors.reason)}
|
||||
error={Boolean(errors.description)}
|
||||
// Note: we don't show the error text here, because errors are related to the character count
|
||||
hint={<>Max: <strong>200</strong> characters. You’ve used <strong className={reasonLengthColor}>{reasonLength}</strong></>}
|
||||
hint={<>Max: <strong>200</strong> characters. You’ve used <strong className={descriptionLengthColor}>{descriptionLength}</strong></>}
|
||||
rows={4}
|
||||
title="Short description"
|
||||
value={formState.reason ?? ''}
|
||||
value={formState.description ?? ''}
|
||||
onBlur={() => setErrors(
|
||||
validateReasonFormField(errors, 'reason', formState.reason)
|
||||
validateDescriptionFormField(errors, 'description', formState.description)
|
||||
)}
|
||||
onChange={(e) => {
|
||||
clearError?.('reason');
|
||||
setReasonLength(e.target.value.length);
|
||||
updateForm(state => ({...state, reason: e.target.value}));
|
||||
clearError?.('description');
|
||||
setDescriptionLength(e.target.value.length);
|
||||
updateForm(state => ({...state, description: e.target.value}));
|
||||
}}
|
||||
/>
|
||||
</Form>;
|
||||
};
|
||||
|
||||
export default RecommendationReasonForm;
|
||||
export default RecommendationDescriptionForm;
|
@ -15,7 +15,7 @@ test.describe('Recommendations', async () => {
|
||||
favicon: null,
|
||||
featured_image: null,
|
||||
one_click_subscribe: false,
|
||||
reason: 'This is a cool website',
|
||||
description: 'This is a cool website',
|
||||
title: 'example.com',
|
||||
url: 'https://example.com/a-cool-website'}
|
||||
]}}
|
||||
@ -38,7 +38,7 @@ test.describe('Recommendations', async () => {
|
||||
favicon: null,
|
||||
featured_image: null,
|
||||
one_click_subscribe: false,
|
||||
reason: 'This is a cool website',
|
||||
description: 'This is a cool website',
|
||||
title: 'example.com',
|
||||
url: 'https://example.com/a-cool-website'}
|
||||
]
|
||||
|
@ -2,7 +2,7 @@
|
||||
"recommendations": {
|
||||
"id": "21452552",
|
||||
"title": "Some Recommendation",
|
||||
"reason": "i like this website",
|
||||
"description": "i like this website",
|
||||
"excerpt": "this is a great website",
|
||||
"feature_image": null,
|
||||
"favicon": null,
|
||||
|
@ -104,11 +104,11 @@ export const RecommendationsPageStyles = `
|
||||
animation: 0.5s ease-in-out fadeIn;
|
||||
}
|
||||
|
||||
.gh-portal-recommendation-subscribed.with-reason {
|
||||
.gh-portal-recommendation-subscribed.with-description {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.gh-portal-recommendation-subscribed.without-reason {
|
||||
.gh-portal-recommendation-subscribed.without-description {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ const openTab = (url) => {
|
||||
|
||||
const RecommendationItem = (recommendation) => {
|
||||
const {t, onAction, member, site} = useContext(AppContext);
|
||||
const {title, url, reason, favicon, one_click_subscribe: oneClickSubscribe, featured_image: featuredImage} = recommendation;
|
||||
const {title, url, description, favicon, one_click_subscribe: oneClickSubscribe, featured_image: featuredImage} = recommendation;
|
||||
const allowOneClickSubscribe = member && oneClickSubscribe;
|
||||
const [subscribed, setSubscribed] = useState(false);
|
||||
const [clicked, setClicked] = useState(false);
|
||||
@ -263,8 +263,8 @@ const RecommendationItem = (recommendation) => {
|
||||
<ArrowIcon className="gh-portal-recommendation-arrow-icon" />
|
||||
</div>
|
||||
<div className="gh-portal-recommendation-description-container">
|
||||
{subscribed && <div className={'gh-portal-recommendation-subscribed ' + (reason ? 'with-reason' : 'without-reason')}><span>{t('Verification link sent, check your inbox')}</span><CheckmarkIcon className="gh-portal-recommendation-checkmark-icon" alt=''/></div>}
|
||||
{reason && <p className={subscribed ? 'gh-portal-recommendation-description-hidden' : ''}>{reason}</p>}
|
||||
{subscribed && <div className={'gh-portal-recommendation-subscribed ' + (description ? 'with-description' : 'without-description')}><span>{t('Verification link sent, check your inbox')}</span><CheckmarkIcon className="gh-portal-recommendation-checkmark-icon" alt=''/></div>}
|
||||
{description && <p className={subscribed ? 'gh-portal-recommendation-description-hidden' : ''}>{description}</p>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="gh-portal-recommendation-item-action">
|
||||
|
@ -5,7 +5,7 @@
|
||||
<a href="{{rec.url}}" data-recommendation="{{rec.id}}" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="{{rec.favicon}}" alt="{{rec.title}}">
|
||||
<h5 class="recommendation-title">{{rec.title}}</h5>
|
||||
<p class="recommendation-reason">{{rec.reason}}</p>
|
||||
<p class="recommendation-description">{{rec.description}}</p>
|
||||
</a>
|
||||
</li>
|
||||
{{/each}}
|
||||
|
@ -91,7 +91,35 @@ function createSetNullableMigration(table, column, options = {}) {
|
||||
if (options.disableForeignKeyChecks) {
|
||||
await knex.raw('SET FOREIGN_KEY_CHECKS=1;').transacting(knex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} table
|
||||
* @param {string} from
|
||||
* @param {string} to
|
||||
*
|
||||
* @returns {Migration}
|
||||
*/
|
||||
function createRenameColumnMigration(table, from, to) {
|
||||
return createNonTransactionalMigration(
|
||||
async function up(knex) {
|
||||
const hasColumn = await knex.schema.hasColumn(table, to);
|
||||
if (hasColumn) {
|
||||
logging.warn(`Renaming ${table}.${from} to ${table}.${to} column - skipping as column ${table}.${to} already exists`);
|
||||
} else {
|
||||
await commands.renameColumn(table, from, to, knex);
|
||||
}
|
||||
},
|
||||
async function down(knex) {
|
||||
const hasColumn = await knex.schema.hasColumn(table, from);
|
||||
if (hasColumn) {
|
||||
logging.warn(`Renaming ${table}.${to} to ${table}.${from} column - skipping as column ${table}.${from} already exists`);
|
||||
} else {
|
||||
await commands.renameColumn(table, to, from, knex);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -134,7 +162,8 @@ module.exports = {
|
||||
createAddColumnMigration,
|
||||
createDropColumnMigration,
|
||||
createSetNullableMigration,
|
||||
createDropNullableMigration
|
||||
createDropNullableMigration,
|
||||
createRenameColumnMigration
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,3 @@
|
||||
const {createRenameColumnMigration} = require('../../utils');
|
||||
|
||||
module.exports = createRenameColumnMigration('recommendations', 'reason', 'description');
|
@ -156,6 +156,25 @@ async function dropColumn(tableName, column, transaction = db.knex, columnSpec =
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} tableName
|
||||
* @param {string} from
|
||||
* @param {string} to
|
||||
* @param {import('knex').Knex.Transaction} [transaction]
|
||||
*/
|
||||
async function renameColumn(tableName, from, to, transaction = db.knex) {
|
||||
logging.info(`Renaming column '${from}' to '${to}' in table '${tableName}'`);
|
||||
|
||||
if (DatabaseInfo.isMySQL(transaction)) {
|
||||
// The knex helper does a lot of interesting things with foreign keys that are slow on bigger MySQL clusters
|
||||
return await transaction.raw(`ALTER TABLE \`${tableName}\` RENAME COLUMN \`${from}\` TO \`${to}\`;`);
|
||||
}
|
||||
|
||||
return await transaction.schema.table(tableName, function (table) {
|
||||
table.renameColumn(from, to);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an unique index to a table over the given columns.
|
||||
*
|
||||
@ -520,6 +539,7 @@ module.exports = {
|
||||
addForeign,
|
||||
dropForeign,
|
||||
addColumn,
|
||||
renameColumn,
|
||||
dropColumn,
|
||||
setNullable,
|
||||
dropNullable,
|
||||
|
@ -1076,7 +1076,7 @@ module.exports = {
|
||||
excerpt: {type: 'string', maxlength: 2000, nullable: true},
|
||||
featured_image: {type: 'string', maxlength: 2000, nullable: true},
|
||||
favicon: {type: 'string', maxlength: 2000, nullable: true},
|
||||
reason: {type: 'string', maxlength: 2000, nullable: true},
|
||||
description: {type: 'string', maxlength: 2000, nullable: true},
|
||||
one_click_subscribe: {type: 'boolean', nullable: false, defaultTo: false},
|
||||
created_at: {type: 'dateTime', nullable: false},
|
||||
updated_at: {type: 'dateTime', nullable: true}
|
||||
|
@ -1150,12 +1150,12 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Because dogs are cute",
|
||||
"excerpt": "Dogs are cute",
|
||||
"favicon": "https://dogpictures.com/favicon.ico",
|
||||
"featured_image": "https://dogpictures.com/dog.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Because dogs are cute",
|
||||
"title": "Dog Pictures",
|
||||
"updated_at": null,
|
||||
"url": "https://dogpictures.com/",
|
||||
@ -1168,7 +1168,7 @@ exports[`Recommendations Admin API add Can add a full recommendation 2: [headers
|
||||
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": "354",
|
||||
"content-length": "359",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1184,12 +1184,12 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": null,
|
||||
"title": "Dog Pictures",
|
||||
"updated_at": null,
|
||||
"url": "https://dogpictures.com/",
|
||||
@ -1202,7 +1202,7 @@ exports[`Recommendations Admin API add Can add a minimal recommendation 2: [head
|
||||
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": "263",
|
||||
"content-length": "268",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1218,12 +1218,12 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": null,
|
||||
"title": "Recommendation 3 with a different path",
|
||||
"updated_at": null,
|
||||
"url": "https://recommendation3.com/path-1",
|
||||
@ -1236,7 +1236,7 @@ exports[`Recommendations Admin API add Can add a recommendation with the same ho
|
||||
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": "299",
|
||||
"content-length": "304",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1335,12 +1335,12 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation0.com/favicon.ico",
|
||||
"featured_image": "https://recommendation0.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 0",
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -1353,7 +1353,7 @@ exports[`Recommendations Admin API browse Can browse 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": "470",
|
||||
"content-length": "480",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1410,12 +1410,12 @@ Object {
|
||||
"subscribers": 3,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 4",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation4.com/favicon.ico",
|
||||
"featured_image": "https://recommendation4.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 4",
|
||||
"title": "Recommendation 4",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation4.com/",
|
||||
@ -1426,12 +1426,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 3",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation3.com/favicon.ico",
|
||||
"featured_image": "https://recommendation3.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 3",
|
||||
"title": "Recommendation 3",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation3.com/",
|
||||
@ -1442,12 +1442,12 @@ Object {
|
||||
"subscribers": 2,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 2",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation2.com/favicon.ico",
|
||||
"featured_image": "https://recommendation2.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 2",
|
||||
"title": "Recommendation 2",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation2.com/",
|
||||
@ -1458,12 +1458,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 1",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation1.com/favicon.ico",
|
||||
"featured_image": "https://recommendation1.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 1",
|
||||
"title": "Recommendation 1",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation1.com/",
|
||||
@ -1474,12 +1474,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation0.com/favicon.ico",
|
||||
"featured_image": "https://recommendation0.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 0",
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -1492,7 +1492,7 @@ exports[`Recommendations Admin API browse Can include click and subscribe counts
|
||||
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": "2103",
|
||||
"content-length": "2153",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1520,12 +1520,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 3",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation3.com/favicon.ico",
|
||||
"featured_image": "https://recommendation3.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 3",
|
||||
"title": "Recommendation 3",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation3.com/",
|
||||
@ -1536,12 +1536,12 @@ Object {
|
||||
"subscribers": 3,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 4",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation4.com/favicon.ico",
|
||||
"featured_image": "https://recommendation4.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 4",
|
||||
"title": "Recommendation 4",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation4.com/",
|
||||
@ -1552,12 +1552,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation0.com/favicon.ico",
|
||||
"featured_image": "https://recommendation0.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 0",
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -1568,12 +1568,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 1",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation1.com/favicon.ico",
|
||||
"featured_image": "https://recommendation1.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 1",
|
||||
"title": "Recommendation 1",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation1.com/",
|
||||
@ -1584,12 +1584,12 @@ Object {
|
||||
"subscribers": 2,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 2",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation2.com/favicon.ico",
|
||||
"featured_image": "https://recommendation2.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 2",
|
||||
"title": "Recommendation 2",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation2.com/",
|
||||
@ -1602,7 +1602,7 @@ exports[`Recommendations Admin API browse Can include click and subscribe counts
|
||||
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": "2103",
|
||||
"content-length": "2153",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1629,12 +1629,12 @@ Object {
|
||||
"clicks": 2,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 4",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation4.com/favicon.ico",
|
||||
"featured_image": "https://recommendation4.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 4",
|
||||
"title": "Recommendation 4",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation4.com/",
|
||||
@ -1644,12 +1644,12 @@ Object {
|
||||
"clicks": 3,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 3",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation3.com/favicon.ico",
|
||||
"featured_image": "https://recommendation3.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 3",
|
||||
"title": "Recommendation 3",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation3.com/",
|
||||
@ -1659,12 +1659,12 @@ Object {
|
||||
"clicks": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 2",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation2.com/favicon.ico",
|
||||
"featured_image": "https://recommendation2.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 2",
|
||||
"title": "Recommendation 2",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation2.com/",
|
||||
@ -1674,12 +1674,12 @@ Object {
|
||||
"clicks": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 1",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation1.com/favicon.ico",
|
||||
"featured_image": "https://recommendation1.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 1",
|
||||
"title": "Recommendation 1",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation1.com/",
|
||||
@ -1689,12 +1689,12 @@ Object {
|
||||
"clicks": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation0.com/favicon.ico",
|
||||
"featured_image": "https://recommendation0.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 0",
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -1707,7 +1707,7 @@ exports[`Recommendations Admin API browse Can include only clicks 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": "2023",
|
||||
"content-length": "2073",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1734,12 +1734,12 @@ Object {
|
||||
"subscribers": 3,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 4",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation4.com/favicon.ico",
|
||||
"featured_image": "https://recommendation4.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 4",
|
||||
"title": "Recommendation 4",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation4.com/",
|
||||
@ -1749,12 +1749,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 3",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation3.com/favicon.ico",
|
||||
"featured_image": "https://recommendation3.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 3",
|
||||
"title": "Recommendation 3",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation3.com/",
|
||||
@ -1764,12 +1764,12 @@ Object {
|
||||
"subscribers": 2,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 2",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation2.com/favicon.ico",
|
||||
"featured_image": "https://recommendation2.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 2",
|
||||
"title": "Recommendation 2",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation2.com/",
|
||||
@ -1779,12 +1779,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 1",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation1.com/favicon.ico",
|
||||
"featured_image": "https://recommendation1.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 1",
|
||||
"title": "Recommendation 1",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation1.com/",
|
||||
@ -1794,12 +1794,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation0.com/favicon.ico",
|
||||
"featured_image": "https://recommendation0.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 0",
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -1812,7 +1812,7 @@ exports[`Recommendations Admin API browse Can include only subscribers 2: [heade
|
||||
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": "2048",
|
||||
"content-length": "2098",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1840,12 +1840,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 3",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation3.com/favicon.ico",
|
||||
"featured_image": "https://recommendation3.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 3",
|
||||
"title": "Recommendation 3",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation3.com/",
|
||||
@ -1856,12 +1856,12 @@ Object {
|
||||
"subscribers": 3,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 4",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation4.com/favicon.ico",
|
||||
"featured_image": "https://recommendation4.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 4",
|
||||
"title": "Recommendation 4",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation4.com/",
|
||||
@ -1872,12 +1872,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation0.com/favicon.ico",
|
||||
"featured_image": "https://recommendation0.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 0",
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -1888,12 +1888,12 @@ Object {
|
||||
"subscribers": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 1",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation1.com/favicon.ico",
|
||||
"featured_image": "https://recommendation1.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 1",
|
||||
"title": "Recommendation 1",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation1.com/",
|
||||
@ -1904,12 +1904,12 @@ Object {
|
||||
"subscribers": 2,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 2",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation2.com/favicon.ico",
|
||||
"featured_image": "https://recommendation2.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 2",
|
||||
"title": "Recommendation 2",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation2.com/",
|
||||
@ -1922,7 +1922,7 @@ exports[`Recommendations Admin API browse Can order by click and subscribe count
|
||||
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": "2103",
|
||||
"content-length": "2153",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -1946,120 +1946,120 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 14",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation14.com/favicon.ico",
|
||||
"featured_image": "https://recommendation14.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 14",
|
||||
"title": "Recommendation 14",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation14.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 13",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation13.com/favicon.ico",
|
||||
"featured_image": "https://recommendation13.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 13",
|
||||
"title": "Recommendation 13",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation13.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 12",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation12.com/favicon.ico",
|
||||
"featured_image": "https://recommendation12.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 12",
|
||||
"title": "Recommendation 12",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation12.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 11",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation11.com/favicon.ico",
|
||||
"featured_image": "https://recommendation11.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 11",
|
||||
"title": "Recommendation 11",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation11.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 10",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation10.com/favicon.ico",
|
||||
"featured_image": "https://recommendation10.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 10",
|
||||
"title": "Recommendation 10",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation10.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 9",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation9.com/favicon.ico",
|
||||
"featured_image": "https://recommendation9.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 9",
|
||||
"title": "Recommendation 9",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation9.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 8",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation8.com/favicon.ico",
|
||||
"featured_image": "https://recommendation8.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 8",
|
||||
"title": "Recommendation 8",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation8.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 7",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation7.com/favicon.ico",
|
||||
"featured_image": "https://recommendation7.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 7",
|
||||
"title": "Recommendation 7",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation7.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 6",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation6.com/favicon.ico",
|
||||
"featured_image": "https://recommendation6.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 6",
|
||||
"title": "Recommendation 6",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation6.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 5",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation5.com/favicon.ico",
|
||||
"featured_image": "https://recommendation5.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 5",
|
||||
"title": "Recommendation 5",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation5.com/",
|
||||
@ -2072,7 +2072,7 @@ exports[`Recommendations Admin API browse Can request pages 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": "3752",
|
||||
"content-length": "3852",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -2096,60 +2096,60 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 4",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation4.com/favicon.ico",
|
||||
"featured_image": "https://recommendation4.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 4",
|
||||
"title": "Recommendation 4",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation4.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 3",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation3.com/favicon.ico",
|
||||
"featured_image": "https://recommendation3.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 3",
|
||||
"title": "Recommendation 3",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation3.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 2",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation2.com/favicon.ico",
|
||||
"featured_image": "https://recommendation2.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 2",
|
||||
"title": "Recommendation 2",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation2.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 1",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation1.com/favicon.ico",
|
||||
"featured_image": "https://recommendation1.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 1",
|
||||
"title": "Recommendation 1",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation1.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation0.com/favicon.ico",
|
||||
"featured_image": "https://recommendation0.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 0",
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -2162,7 +2162,7 @@ exports[`Recommendations Admin API browse Can request pages 4: [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": "1917",
|
||||
"content-length": "1967",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -2175,7 +2175,7 @@ exports[`Recommendations Admin API browse Uses default limit of 5 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": "1915",
|
||||
"content-length": "1965",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -2203,12 +2203,12 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Because cats are cute",
|
||||
"excerpt": "Cats are cute",
|
||||
"favicon": "https://catpictures.com/favicon.ico",
|
||||
"featured_image": "https://catpictures.com/cat.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Because cats are cute",
|
||||
"title": "Cat Pictures",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://dogpictures.com/",
|
||||
@ -2221,7 +2221,7 @@ exports[`Recommendations Admin API edit Can edit recommendation 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": "377",
|
||||
"content-length": "382",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -2236,12 +2236,12 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": null,
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -2254,7 +2254,7 @@ exports[`Recommendations Admin API edit Can edit recommendation and set nullable
|
||||
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": "292",
|
||||
"content-length": "297",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -2269,12 +2269,12 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation0.com/favicon.ico",
|
||||
"featured_image": "https://recommendation0.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 0",
|
||||
"title": "Changed",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -2287,7 +2287,7 @@ exports[`Recommendations Admin API edit Can edit some fields of a recommendation
|
||||
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": "374",
|
||||
"content-length": "384",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -2333,12 +2333,12 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 1",
|
||||
"excerpt": "Test excerpt",
|
||||
"favicon": "https://recommendation1.com/favicon.ico",
|
||||
"featured_image": "https://recommendation1.com/featured.jpg",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": true,
|
||||
"reason": "Reason 1",
|
||||
"title": "Recommendation 1",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation1.com/",
|
||||
@ -2351,7 +2351,7 @@ exports[`Recommendations Admin API read can get a recommendation by ID 2: [heade
|
||||
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": "383",
|
||||
"content-length": "393",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
@ -7,7 +7,7 @@ const {Recommendation, ClickEvent, SubscribeEvent} = require('@tryghost/recommen
|
||||
async function addDummyRecommendation(i = 0) {
|
||||
const recommendation = Recommendation.create({
|
||||
title: `Recommendation ${i}`,
|
||||
reason: `Reason ${i}`,
|
||||
description: `Description ${i}`,
|
||||
url: new URL(`https://recommendation${i}.com`),
|
||||
favicon: new URL(`https://recommendation${i}.com/favicon.ico`),
|
||||
featuredImage: new URL(`https://recommendation${i}.com/featured.jpg`),
|
||||
@ -357,7 +357,7 @@ describe('Recommendations Admin API', function () {
|
||||
assert.equal(body.recommendations[0].id, id);
|
||||
assert.equal(body.recommendations[0].title, 'Recommendation 1');
|
||||
assert.equal(body.recommendations[0].url, 'https://recommendation1.com/');
|
||||
assert.equal(body.recommendations[0].reason, 'Reason 1');
|
||||
assert.equal(body.recommendations[0].description, 'Description 1');
|
||||
assert.equal(body.recommendations[0].excerpt, 'Test excerpt');
|
||||
assert.equal(body.recommendations[0].featured_image, 'https://recommendation1.com/featured.jpg');
|
||||
assert.equal(body.recommendations[0].favicon, 'https://recommendation1.com/favicon.ico');
|
||||
@ -393,7 +393,7 @@ describe('Recommendations Admin API', function () {
|
||||
recommendations: [{
|
||||
title: 'Cat Pictures',
|
||||
url: 'https://dogpictures.com',
|
||||
reason: 'Because cats are cute',
|
||||
description: 'Because cats are cute',
|
||||
excerpt: 'Cats are cute',
|
||||
featured_image: 'https://catpictures.com/cat.jpg',
|
||||
favicon: 'https://catpictures.com/favicon.ico',
|
||||
@ -419,7 +419,7 @@ describe('Recommendations Admin API', function () {
|
||||
assert.equal(body.recommendations[0].id, id);
|
||||
assert.equal(body.recommendations[0].title, 'Cat Pictures');
|
||||
assert.equal(body.recommendations[0].url, 'https://dogpictures.com/');
|
||||
assert.equal(body.recommendations[0].reason, 'Because cats are cute');
|
||||
assert.equal(body.recommendations[0].description, 'Because cats are cute');
|
||||
assert.equal(body.recommendations[0].excerpt, 'Cats are cute');
|
||||
assert.equal(body.recommendations[0].featured_image, 'https://catpictures.com/cat.jpg');
|
||||
assert.equal(body.recommendations[0].favicon, 'https://catpictures.com/favicon.ico');
|
||||
@ -431,7 +431,7 @@ describe('Recommendations Admin API', function () {
|
||||
const {body} = await agent.put(`recommendations/${id}/`)
|
||||
.body({
|
||||
recommendations: [{
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featured_image: null,
|
||||
favicon: null
|
||||
@ -454,7 +454,7 @@ describe('Recommendations Admin API', function () {
|
||||
|
||||
// Check everything is set correctly
|
||||
assert.equal(body.recommendations[0].id, id);
|
||||
assert.equal(body.recommendations[0].reason, null);
|
||||
assert.equal(body.recommendations[0].description, null);
|
||||
assert.equal(body.recommendations[0].excerpt, null);
|
||||
assert.equal(body.recommendations[0].featured_image, null);
|
||||
assert.equal(body.recommendations[0].favicon, null);
|
||||
@ -487,7 +487,7 @@ describe('Recommendations Admin API', function () {
|
||||
assert.equal(body.recommendations[0].id, id);
|
||||
assert.equal(body.recommendations[0].title, 'Changed');
|
||||
assert.equal(body.recommendations[0].url, 'https://recommendation0.com/');
|
||||
assert.equal(body.recommendations[0].reason, 'Reason 0');
|
||||
assert.equal(body.recommendations[0].description, 'Description 0');
|
||||
assert.equal(body.recommendations[0].excerpt, 'Test excerpt');
|
||||
assert.equal(body.recommendations[0].featured_image, 'https://recommendation0.com/featured.jpg');
|
||||
assert.equal(body.recommendations[0].favicon, 'https://recommendation0.com/favicon.ico');
|
||||
@ -502,7 +502,7 @@ describe('Recommendations Admin API', function () {
|
||||
recommendations: [{
|
||||
title: 'Cat Pictures',
|
||||
url: 'https://dogpictures.com',
|
||||
reason: 'Because cats are cute',
|
||||
description: 'Because cats are cute',
|
||||
excerpt: 'Cats are cute',
|
||||
featured_image: 'ftp://dogpictures.com/dog.jpg',
|
||||
favicon: 'ftp://dogpictures.com/favicon.ico',
|
||||
@ -551,7 +551,7 @@ describe('Recommendations Admin API', function () {
|
||||
// Check everything is set correctly
|
||||
assert.equal(body.recommendations[0].title, 'Dog Pictures');
|
||||
assert.equal(body.recommendations[0].url, 'https://dogpictures.com/');
|
||||
assert.equal(body.recommendations[0].reason, null);
|
||||
assert.equal(body.recommendations[0].description, null);
|
||||
assert.equal(body.recommendations[0].excerpt, null);
|
||||
assert.equal(body.recommendations[0].featured_image, null);
|
||||
assert.equal(body.recommendations[0].favicon, null);
|
||||
@ -564,7 +564,7 @@ describe('Recommendations Admin API', function () {
|
||||
recommendations: [{
|
||||
title: 'Dog Pictures',
|
||||
url: 'https://dogpictures.com',
|
||||
reason: 'Because dogs are cute',
|
||||
description: 'Because dogs are cute',
|
||||
excerpt: 'Dogs are cute',
|
||||
featured_image: 'https://dogpictures.com/dog.jpg',
|
||||
favicon: 'https://dogpictures.com/favicon.ico',
|
||||
@ -589,7 +589,7 @@ describe('Recommendations Admin API', function () {
|
||||
// Check everything is set correctly
|
||||
assert.equal(body.recommendations[0].title, 'Dog Pictures');
|
||||
assert.equal(body.recommendations[0].url, 'https://dogpictures.com/');
|
||||
assert.equal(body.recommendations[0].reason, 'Because dogs are cute');
|
||||
assert.equal(body.recommendations[0].description, 'Because dogs are cute');
|
||||
assert.equal(body.recommendations[0].excerpt, 'Dogs are cute');
|
||||
assert.equal(body.recommendations[0].featured_image, 'https://dogpictures.com/dog.jpg');
|
||||
assert.equal(body.recommendations[0].favicon, 'https://dogpictures.com/favicon.ico');
|
||||
|
@ -15,60 +15,60 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 6",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 6",
|
||||
"title": "Recommendation 6",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation6.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 5",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 5",
|
||||
"title": "Recommendation 5",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation5.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 4",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 4",
|
||||
"title": "Recommendation 4",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation4.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 3",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 3",
|
||||
"title": "Recommendation 3",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation3.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 2",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 2",
|
||||
"title": "Recommendation 2",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation2.com/",
|
||||
@ -81,7 +81,7 @@ exports[`Recommendations Content API Can paginate recommendations 2: [headers] 1
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "public, max-age=0",
|
||||
"content-length": "1495",
|
||||
"content-length": "1545",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -105,24 +105,24 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 1",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 1",
|
||||
"title": "Recommendation 1",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation1.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 0",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 0",
|
||||
"title": "Recommendation 0",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation0.com/",
|
||||
@ -135,7 +135,7 @@ exports[`Recommendations Content API Can paginate recommendations 4: [headers] 1
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "public, max-age=0",
|
||||
"content-length": "661",
|
||||
"content-length": "681",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
@ -159,60 +159,60 @@ Object {
|
||||
"recommendations": Array [
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 6",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 6",
|
||||
"title": "Recommendation 6",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation6.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 5",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 5",
|
||||
"title": "Recommendation 5",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation5.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 4",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 4",
|
||||
"title": "Recommendation 4",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation4.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 3",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 3",
|
||||
"title": "Recommendation 3",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation3.com/",
|
||||
},
|
||||
Object {
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Description 2",
|
||||
"excerpt": null,
|
||||
"favicon": null,
|
||||
"featured_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"one_click_subscribe": false,
|
||||
"reason": "Reason 2",
|
||||
"title": "Recommendation 2",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"url": "https://recommendation2.com/",
|
||||
@ -225,7 +225,7 @@ exports[`Recommendations Content API Does not allow includes 2: [headers] 1`] =
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "public, max-age=0",
|
||||
"content-length": "1495",
|
||||
"content-length": "1545",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
@ -22,7 +22,7 @@ describe('Recommendations Content API', function () {
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const recommendation = Recommendation.create({
|
||||
title: `Recommendation ${i}`,
|
||||
reason: `Reason ${i}`,
|
||||
description: `Description ${i}`,
|
||||
url: new URL(`https://recommendation${i}.com`),
|
||||
favicon: null,
|
||||
featuredImage: null,
|
||||
|
@ -74,7 +74,7 @@ describe('Recommendation Event Tracking', function () {
|
||||
// Add recommendation
|
||||
const recommendation = Recommendation.create({
|
||||
title: `Recommendation`,
|
||||
reason: `Reason`,
|
||||
description: `Description`,
|
||||
url: new URL(`https://recommendation.com`),
|
||||
favicon: null,
|
||||
featuredImage: null,
|
||||
|
@ -1,5 +1,244 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Incoming Recommendation Emails Sends a different email if we receive a recommendation back 1: [html 1] 1`] = `
|
||||
"<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name=\\"viewport\\" content=\\"width=device-width\\">
|
||||
<meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=UTF-8\\">
|
||||
<title>👍 New recommendation</title>
|
||||
<style>
|
||||
/* -------------------------------------
|
||||
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||
------------------------------------- */
|
||||
@media only screen and (max-width: 620px) {
|
||||
table[class=body] h1 {
|
||||
font-size: 28px !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
table[class=body] p,
|
||||
table[class=body] ul,
|
||||
table[class=body] ol,
|
||||
table[class=body] td,
|
||||
table[class=body] span,
|
||||
table[class=body] a {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
table[class=body] .wrapper,
|
||||
table[class=body] .article {
|
||||
padding: 10px !important;
|
||||
}
|
||||
table[class=body] .content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
table[class=body] .container {
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class=body] .main {
|
||||
border-left-width: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
border-right-width: 0 !important;
|
||||
}
|
||||
table[class=body] .btn table {
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class=body] .btn a {
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class=body] .img-responsive {
|
||||
height: auto !important;
|
||||
max-width: 100% !important;
|
||||
width: auto !important;
|
||||
}
|
||||
table[class=body] p[class=small],
|
||||
table[class=body] a[class=small] {
|
||||
font-size: 11px !important;
|
||||
}
|
||||
.new-mention-thumbnail {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
/* -------------------------------------
|
||||
PRESERVE THESE STYLES IN THE HEAD
|
||||
------------------------------------- */
|
||||
@media all {
|
||||
.ExternalClass {
|
||||
width: 100%;
|
||||
}
|
||||
.ExternalClass,
|
||||
.ExternalClass p,
|
||||
.ExternalClass span,
|
||||
.ExternalClass font,
|
||||
.ExternalClass td,
|
||||
.ExternalClass div {
|
||||
line-height: 100%;
|
||||
}
|
||||
/* Reset styles for Gmail (it wraps email address in link with custom styles) */
|
||||
.text-link a {
|
||||
color: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-size: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
#MessageViewBody a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
hr {
|
||||
border-width: 0;
|
||||
height: 0;
|
||||
margin-top: 34px;
|
||||
margin-bottom: 34px;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #EEF5F8;
|
||||
}
|
||||
a {
|
||||
color: #15212A;
|
||||
}
|
||||
blockquote {
|
||||
margin-left: 0;
|
||||
padding-left: 20px;
|
||||
border-left: 3px solid #DDE1E5;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style=\\"background-color: #ffffff; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.5em; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;\\">
|
||||
|
||||
<table border=\\"0\\" cellpadding=\\"0\\" cellspacing=\\"0\\" class=\\"body\\" style=\\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;\\">
|
||||
<tr>
|
||||
<td style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;\\"> </td>
|
||||
<td class=\\"container\\" style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; padding: 10px; width: 540px;\\">
|
||||
<div class=\\"content\\" style=\\"box-sizing: border-box; display: block; Margin: 0 auto; max-width: 600px; padding: 30px 20px;\\">
|
||||
|
||||
<!-- START CENTERED CONTAINER -->
|
||||
<table class=\\"main\\" style=\\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 8px;\\">
|
||||
|
||||
<!-- START MAIN CONTENT AREA -->
|
||||
<tr>
|
||||
<td class=\\"wrapper\\" style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; box-sizing: border-box;\\">
|
||||
<table border=\\"0\\" cellpadding=\\"0\\" cellspacing=\\"0\\" style=\\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;\\">
|
||||
<tr>
|
||||
<td style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;\\">
|
||||
|
||||
<p style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 20px; color: #15212A; font-weight: bold; line-height: 25px; margin: 0; margin-bottom: 15px;\\">Great news!</p>
|
||||
<p style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 16px;\\">One of the sites you're recommending is now <strong>recommending you back</strong>:</p>
|
||||
|
||||
<!--[if !mso !vml]-->
|
||||
<figure style=\\"margin:0 0 1.5em;padding:0;width:100%;\\">
|
||||
<a style=\\"display:flex;min-height:110px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;background:#F9F9FA;border-radius:3px;border:1px solid #F9F9FA;color:#15171a;text-decoration:none\\" href=\\"https://www.otherghostsite.com/\\">
|
||||
<div style=\\"display:inline-block; width:100%; padding:20px\\">
|
||||
<div style=\\"display:flex;color:#15212a;font-size:13px;font-weight:400\\">
|
||||
|
||||
<div style=\\"color:#15212a;font-size:16px;line-height:1.3em;font-weight:600\\">Other Ghost Site</div>
|
||||
</div>
|
||||
<div class=\\"kg-bookmark-description\\" style=\\"display:-webkit-box;overflow-y:hidden;margin-top:12px;max-height:40px;color:#738a94;font-size:13px;line-height:1.5em;font-weight:400;-webkit-line-clamp: 2; -webkit-box-orient: vertical;\\"></div>
|
||||
</div>
|
||||
</a>
|
||||
</figure>
|
||||
<!--[endif]-->
|
||||
|
||||
<!--[if vml]>
|
||||
<table style=\\"border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; width: 100%; border: 1px solid #f9f9fa; background: #f9f9fa; font-family: -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", Roboto, Oxygen, Ubuntu, Cantarell, \\"Open Sans\\", \\"Helvetica Neue\\", sans-serif;\\">
|
||||
<tr>
|
||||
<td width=\\"100%\\" style=\\"padding: 20px;background-color:#F9F9FA;\\">
|
||||
<table style=\\"margin: 0; padding: 0; border-collapse: collapse; border-spacing: 0;\\">
|
||||
<tr>
|
||||
<td style=\\"padding-bottom: 12px;\\">
|
||||
<table style=\\"margin: 0; padding: 0; border-collapse: collapse; border-spacing: 0;\\">
|
||||
<tr>
|
||||
<td><a style=\\"color: #15212A; font-size: 15px; line-height: 1.5em; font-weight: 600; text-decoration: none;\\" href=\\"\\"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div><a href=\\"\\" style=\\"margin-top: 12px; color: #738a94; font-size: 13px; line-height: 1.5em; font-weight: 400;text-decoration: none;\\"></a></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
|
||||
<table border=\\"0\\" cellpadding=\\"0\\" cellspacing=\\"0\\" class=\\"btn btn-primary\\" style=\\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box;\\">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align=\\"left\\" style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; vertical-align: top; padding-top: 32px; padding-bottom: 12px;\\">
|
||||
<table border=\\"0\\" cellpadding=\\"0\\" cellspacing=\\"0\\" style=\\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;\\">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; vertical-align: top; background-color: #15171a; border-radius: 5px; text-align: center;\\"> <a href=\\"http://127.0.0.1:2369/ghost/#/settings-x/recommendations\\" target=\\"_blank\\" style=\\"display: inline-block; color: #ffffff; background-color: #15171a; border: solid 1px #15171a; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: normal; margin: 0; padding: 9px 22px 10px; border-color: #15171a;\\">View recommendations</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr/>
|
||||
<p style=\\"word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; color: #3A464C; font-weight: normal; margin: 0; line-height: 25px; margin-bottom: 5px;\\">You can also copy & paste this URL into your browser:</p>
|
||||
<p class=\\"text-link\\" style=\\"word-break: break-all; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 25px; margin-top:0; color: #3A464C;\\">http://127.0.0.1:2369/ghost/#/settings-x/recommendations</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- START FOOTER -->
|
||||
<tr>
|
||||
<td style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; padding-top: 80px;\\">
|
||||
<p class=\\"small\\" style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height: 18px; font-size: 11px; color: #738A94; font-weight: normal; margin: 0; margin-bottom: 2px;\\">This message was sent from <a class=\\"small\\" href=\\"http://127.0.0.1:2369/\\" style=\\"text-decoration: underline; color: #738A94; font-size: 11px;\\">127.0.0.1</a> to <a class=\\"small\\" href=\\"mailto:jbloggs@example.com\\" style=\\"text-decoration: underline; color: #738A94; font-size: 11px;\\">jbloggs@example.com</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; padding-top: 2px\\">
|
||||
<p class=\\"small\\" style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height: 18px; font-size: 11px; color: #738A94; font-weight: normal; margin: 0; margin-bottom: 2px;\\">Don’t want to receive these emails? Manage your preferences <a class=\\"small\\" href=\\"http://127.0.0.1:2369/ghost/#/settings-x/users/show/joe-bloggs\\" style=\\"text-decoration: underline; color: #738A94; font-size: 11px;\\">here</a>.</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- END FOOTER -->
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- END MAIN CONTENT AREA -->
|
||||
</table>
|
||||
|
||||
|
||||
<!-- END CENTERED CONTAINER -->
|
||||
</div>
|
||||
</td>
|
||||
<td style=\\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;\\"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Incoming Recommendation Emails Sends a different email if we receive a recommendation back 2: [text 1] 1`] = `
|
||||
"
|
||||
You have been recommended by Other Ghost Site.
|
||||
|
||||
---
|
||||
|
||||
Sent to jbloggs@example.com from 127.0.0.1.
|
||||
If you would no longer like to receive these notifications you can adjust your settings at http://127.0.0.1:2369/ghost/#/settings-x/users/show/joe-bloggs.
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Incoming Recommendation Emails Sends a different email if we receive a recommendation back 3: [metadata 1] 1`] = `
|
||||
Object {
|
||||
"subject": "👍 New recommendation: Other Ghost Site",
|
||||
"to": "jbloggs@example.com",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Incoming Recommendation Emails Sends an email if we receive a recommendation 1: [html 1] 1`] = `
|
||||
"<!doctype html>
|
||||
<html>
|
||||
|
@ -73,7 +73,7 @@ describe('Incoming Recommendation Emails', function () {
|
||||
// Create a recommendation to otherghostsite.com
|
||||
const recommendation = Recommendation.create({
|
||||
title: `Recommendation`,
|
||||
reason: `Reason`,
|
||||
description: `Description`,
|
||||
url: new URL(`https://www.otherghostsite.com/`),
|
||||
favicon: null,
|
||||
featuredImage: null,
|
||||
|
@ -41,11 +41,11 @@ describe('{{#recommendations}} helper', function () {
|
||||
sinon.stub(api, 'recommendationsPublic').get(() => {
|
||||
return {
|
||||
browse: sinon.stub().resolves({recommendations: [
|
||||
{id: '1', title: 'Recommendation 1', url: 'https://recommendations1.com', favicon: 'https://recommendations1.com/favicon.ico', reason: 'Reason 1'},
|
||||
{id: '2', title: 'Recommendation 2', url: 'https://recommendations2.com', favicon: 'https://recommendations2.com/favicon.ico', reason: 'Reason 2'},
|
||||
{id: '3', title: 'Recommendation 3', url: 'https://recommendations3.com', favicon: 'https://recommendations3.com/favicon.ico', reason: 'Reason 3'},
|
||||
{id: '4', title: 'Recommendation 4', url: 'https://recommendations4.com', favicon: 'https://recommendations4.com/favicon.ico', reason: 'Reason 4'},
|
||||
{id: '5', title: 'Recommendation 5', url: 'https://recommendations5.com', favicon: 'https://recommendations5.com/favicon.ico', reason: 'Reason 5'}
|
||||
{id: '1', title: 'Recommendation 1', url: 'https://recommendations1.com', favicon: 'https://recommendations1.com/favicon.ico', description: 'Description 1'},
|
||||
{id: '2', title: 'Recommendation 2', url: 'https://recommendations2.com', favicon: 'https://recommendations2.com/favicon.ico', description: 'Description 2'},
|
||||
{id: '3', title: 'Recommendation 3', url: 'https://recommendations3.com', favicon: 'https://recommendations3.com/favicon.ico', description: 'Description 3'},
|
||||
{id: '4', title: 'Recommendation 4', url: 'https://recommendations4.com', favicon: 'https://recommendations4.com/favicon.ico', description: 'Description 4'},
|
||||
{id: '5', title: 'Recommendation 5', url: 'https://recommendations5.com', favicon: 'https://recommendations5.com/favicon.ico', description: 'Description 5'}
|
||||
], meta: meta})
|
||||
};
|
||||
});
|
||||
@ -74,35 +74,35 @@ describe('{{#recommendations}} helper', function () {
|
||||
<a href="https://recommendations1.com" data-recommendation="1" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations1.com/favicon.ico" alt="Recommendation 1">
|
||||
<h5 class="recommendation-title">Recommendation 1</h5>
|
||||
<p class="recommendation-reason">Reason 1</p>
|
||||
<p class="recommendation-description">Description 1</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations2.com" data-recommendation="2" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations2.com/favicon.ico" alt="Recommendation 2">
|
||||
<h5 class="recommendation-title">Recommendation 2</h5>
|
||||
<p class="recommendation-reason">Reason 2</p>
|
||||
<p class="recommendation-description">Description 2</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations3.com" data-recommendation="3" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations3.com/favicon.ico" alt="Recommendation 3">
|
||||
<h5 class="recommendation-title">Recommendation 3</h5>
|
||||
<p class="recommendation-reason">Reason 3</p>
|
||||
<p class="recommendation-description">Description 3</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations4.com" data-recommendation="4" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations4.com/favicon.ico" alt="Recommendation 4">
|
||||
<h5 class="recommendation-title">Recommendation 4</h5>
|
||||
<p class="recommendation-reason">Reason 4</p>
|
||||
<p class="recommendation-description">Description 4</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="recommendation">
|
||||
<a href="https://recommendations5.com" data-recommendation="5" target="_blank" rel="noopener">
|
||||
<img class="recommendation-favicon" src="https://recommendations5.com/favicon.ico" alt="Recommendation 5">
|
||||
<h5 class="recommendation-title">Recommendation 5</h5>
|
||||
<p class="recommendation-reason">Reason 5</p>
|
||||
<p class="recommendation-description">Description 5</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -35,7 +35,7 @@ const validateRouteSettings = require('../../../../../core/server/services/route
|
||||
*/
|
||||
describe('DB version integrity', function () {
|
||||
// Only these variables should need updating
|
||||
const currentSchemaHash = '1b75aae9befefea53b17c9c1991c8a1d';
|
||||
const currentSchemaHash = '013334f4f51aae785b9afd345861c06a';
|
||||
const currentFixturesHash = '4db87173699ad9c9d8a67ccab96dfd2d';
|
||||
const currentSettingsHash = '3128d4ec667a50049486b0c21f04be07';
|
||||
const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01';
|
||||
|
@ -45,7 +45,7 @@ export class BookshelfRecommendationRepository extends BookshelfRepository<strin
|
||||
return {
|
||||
id: entity.id,
|
||||
title: entity.title,
|
||||
reason: entity.reason,
|
||||
description: entity.description,
|
||||
excerpt: entity.excerpt,
|
||||
featured_image: entity.featuredImage?.toString(),
|
||||
favicon: entity.favicon?.toString(),
|
||||
@ -62,7 +62,7 @@ export class BookshelfRecommendationRepository extends BookshelfRepository<strin
|
||||
return Recommendation.create({
|
||||
id: model.id,
|
||||
title: model.get('title') as string,
|
||||
reason: model.get('reason') as string | null,
|
||||
description: model.get('description') as string | null,
|
||||
excerpt: model.get('excerpt') as string | null,
|
||||
featuredImage: model.get('featured_image') as string | null,
|
||||
favicon: model.get('favicon') as string | null,
|
||||
@ -84,7 +84,7 @@ export class BookshelfRecommendationRepository extends BookshelfRepository<strin
|
||||
return {
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
reason: 'reason',
|
||||
description: 'description',
|
||||
excerpt: 'excerpt',
|
||||
featuredImage: 'featured_image',
|
||||
favicon: 'favicon',
|
||||
|
@ -8,7 +8,7 @@ import {UnsafeData} from './UnsafeData';
|
||||
export type RecommendationPlain = {
|
||||
id: string,
|
||||
title: string
|
||||
reason: string|null
|
||||
description: string|null
|
||||
excerpt: string|null // Fetched from the site meta data
|
||||
featuredImage: URL|null // Fetched from the site meta data
|
||||
favicon: URL|null // Fetched from the site meta data
|
||||
@ -27,7 +27,7 @@ export type RecommendationPlain = {
|
||||
export type RecommendationCreateData = {
|
||||
id?: string
|
||||
title: string
|
||||
reason: string|null
|
||||
description: string|null
|
||||
excerpt: string|null // Fetched from the site meta data
|
||||
featuredImage: URL|string|null // Fetched from the site meta data
|
||||
favicon: URL|string|null // Fetched from the site meta data
|
||||
@ -49,7 +49,7 @@ export type EditRecommendation = Partial<AddRecommendation>
|
||||
export class Recommendation {
|
||||
id: string;
|
||||
title: string;
|
||||
reason: string|null;
|
||||
description: string|null;
|
||||
excerpt: string|null; // Fetched from the site meta data
|
||||
featuredImage: URL|null; // Fetched from the site meta data
|
||||
favicon: URL|null; // Fetched from the site meta data
|
||||
@ -77,7 +77,7 @@ export class Recommendation {
|
||||
private constructor(data: RecommendationPlain) {
|
||||
this.id = data.id;
|
||||
this.title = data.title;
|
||||
this.reason = data.reason;
|
||||
this.description = data.description;
|
||||
this.excerpt = data.excerpt;
|
||||
this.featuredImage = data.featuredImage;
|
||||
this.favicon = data.favicon;
|
||||
@ -103,9 +103,9 @@ export class Recommendation {
|
||||
});
|
||||
}
|
||||
|
||||
if (properties.reason && properties.reason.length > 2000) {
|
||||
if (properties.description && properties.description.length > 2000) {
|
||||
throw new errors.ValidationError({
|
||||
message: 'Reason must be less than 2000 characters'
|
||||
message: 'Description must be less than 2000 characters'
|
||||
});
|
||||
}
|
||||
|
||||
@ -117,8 +117,8 @@ export class Recommendation {
|
||||
}
|
||||
|
||||
clean() {
|
||||
if (this.reason !== null && this.reason.length === 0) {
|
||||
this.reason = null;
|
||||
if (this.description !== null && this.description.length === 0) {
|
||||
this.description = null;
|
||||
}
|
||||
|
||||
this.url = this.cleanURL(this.url);
|
||||
@ -139,7 +139,7 @@ export class Recommendation {
|
||||
const d = {
|
||||
id,
|
||||
title: data.title,
|
||||
reason: data.reason,
|
||||
description: data.description,
|
||||
excerpt: data.excerpt,
|
||||
featuredImage: new UnsafeData(data.featuredImage, {field: ['featuredImage']}).nullable.url,
|
||||
favicon: new UnsafeData(data.favicon, {field: ['favicon']}).nullable.url,
|
||||
@ -162,7 +162,7 @@ export class Recommendation {
|
||||
return {
|
||||
id: this.id,
|
||||
title: this.title,
|
||||
reason: this.reason,
|
||||
description: this.description,
|
||||
excerpt: this.excerpt,
|
||||
featuredImage: this.featuredImage,
|
||||
favicon: this.favicon,
|
||||
|
@ -18,7 +18,7 @@ const RecommendationIncludesMap = {
|
||||
|
||||
const RecommendationOrderMap = {
|
||||
title: 'title' as const,
|
||||
reason: 'reason' as const,
|
||||
description: 'description' as const,
|
||||
excerpt: 'excerpt' as const,
|
||||
one_click_subscribe: 'oneClickSubscribe' as const,
|
||||
created_at: 'createdAt' as const,
|
||||
@ -54,7 +54,7 @@ export class RecommendationController {
|
||||
|
||||
// Optional fields
|
||||
oneClickSubscribe: recommendation.optionalKey('one_click_subscribe')?.boolean ?? false,
|
||||
reason: recommendation.optionalKey('reason')?.nullable.string ?? null,
|
||||
description: recommendation.optionalKey('description')?.nullable.string ?? null,
|
||||
excerpt: recommendation.optionalKey('excerpt')?.nullable.string ?? null,
|
||||
featuredImage: recommendation.optionalKey('featured_image')?.nullable.url ?? null,
|
||||
favicon: recommendation.optionalKey('favicon')?.nullable.url ?? null
|
||||
@ -75,7 +75,7 @@ export class RecommendationController {
|
||||
title: recommendation.optionalKey('title')?.string,
|
||||
url: recommendation.optionalKey('url')?.url,
|
||||
oneClickSubscribe: recommendation.optionalKey('one_click_subscribe')?.boolean,
|
||||
reason: recommendation.optionalKey('reason')?.nullable.string,
|
||||
description: recommendation.optionalKey('description')?.nullable.string,
|
||||
excerpt: recommendation.optionalKey('excerpt')?.nullable.string,
|
||||
featuredImage: recommendation.optionalKey('featured_image')?.nullable.url,
|
||||
favicon: recommendation.optionalKey('favicon')?.nullable.url
|
||||
@ -207,7 +207,7 @@ export class RecommendationController {
|
||||
const d = {
|
||||
id: entity.id,
|
||||
title: entity.title,
|
||||
reason: entity.reason,
|
||||
description: entity.description,
|
||||
excerpt: entity.excerpt,
|
||||
featured_image: entity.featuredImage?.toString() ?? null,
|
||||
favicon: entity.favicon?.toString() ?? null,
|
||||
|
@ -15,7 +15,7 @@ describe('BookshelfRecommendationRepository', function () {
|
||||
repository.toPrimitive(Recommendation.create({
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
reason: 'reason',
|
||||
description: 'description',
|
||||
excerpt: 'excerpt',
|
||||
featuredImage: new URL('https://example.com'),
|
||||
favicon: new URL('https://example.com'),
|
||||
@ -27,7 +27,7 @@ describe('BookshelfRecommendationRepository', function () {
|
||||
{
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
reason: 'reason',
|
||||
description: 'description',
|
||||
excerpt: 'excerpt',
|
||||
featured_image: 'https://example.com/',
|
||||
favicon: 'https://example.com/',
|
||||
@ -48,7 +48,7 @@ describe('BookshelfRecommendationRepository', function () {
|
||||
get: (key: string) => {
|
||||
return {
|
||||
title: 'title',
|
||||
reason: 'reason',
|
||||
description: 'description',
|
||||
excerpt: 'excerpt',
|
||||
featured_image: 'https://example.com/',
|
||||
favicon: 'https://example.com/',
|
||||
@ -65,7 +65,7 @@ describe('BookshelfRecommendationRepository', function () {
|
||||
Recommendation.create({
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
reason: 'reason',
|
||||
description: 'description',
|
||||
excerpt: 'excerpt',
|
||||
featuredImage: new URL('https://example.com'),
|
||||
favicon: new URL('https://example.com'),
|
||||
@ -121,7 +121,7 @@ describe('BookshelfRecommendationRepository', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
reason: 'reason',
|
||||
description: 'description',
|
||||
excerpt: 'excerpt',
|
||||
featuredImage: new URL('https://example.com'),
|
||||
favicon: new URL('https://example.com'),
|
||||
@ -149,7 +149,7 @@ describe('BookshelfRecommendationRepository', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
reason: 'reason',
|
||||
description: 'description',
|
||||
excerpt: 'excerpt',
|
||||
featuredImage: new URL('https://example.com'),
|
||||
favicon: new URL('https://example.com'),
|
||||
|
@ -7,7 +7,7 @@ describe('Recommendation', function () {
|
||||
assert.throws(() => {
|
||||
Recommendation.validate({
|
||||
title: '',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -24,7 +24,7 @@ describe('Recommendation', function () {
|
||||
assert.throws(() => {
|
||||
Recommendation.validate({
|
||||
title: 'a'.repeat(2001),
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -37,11 +37,11 @@ describe('Recommendation', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Throws for a long reason', function () {
|
||||
it('Throws for a long description', function () {
|
||||
assert.throws(() => {
|
||||
Recommendation.validate({
|
||||
title: 'Test',
|
||||
reason: 'a'.repeat(2001),
|
||||
description: 'a'.repeat(2001),
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -50,7 +50,7 @@ describe('Recommendation', function () {
|
||||
});
|
||||
}, {
|
||||
name: 'ValidationError',
|
||||
message: 'Reason must be less than 2000 characters'
|
||||
message: 'Description must be less than 2000 characters'
|
||||
});
|
||||
});
|
||||
|
||||
@ -58,7 +58,7 @@ describe('Recommendation', function () {
|
||||
assert.throws(() => {
|
||||
Recommendation.validate({
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: 'a'.repeat(2001),
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -76,7 +76,7 @@ describe('Recommendation', function () {
|
||||
it('sets createdAt ms to 0', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -91,7 +91,7 @@ describe('Recommendation', function () {
|
||||
it('sets updatedAt ms to 0', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -103,10 +103,10 @@ describe('Recommendation', function () {
|
||||
assert.equal(recommendation.updatedAt!.getMilliseconds(), 0);
|
||||
});
|
||||
|
||||
it('sets empty reason to null', function () {
|
||||
it('sets empty description to null', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
title: 'Test',
|
||||
reason: '',
|
||||
description: '',
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -115,13 +115,13 @@ describe('Recommendation', function () {
|
||||
updatedAt: new Date('2021-01-01T00:00:05Z')
|
||||
});
|
||||
|
||||
assert.equal(recommendation.reason, null);
|
||||
assert.equal(recommendation.description, null);
|
||||
});
|
||||
|
||||
it('removes search and hash params', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
title: 'Test',
|
||||
reason: '',
|
||||
description: '',
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -138,7 +138,7 @@ describe('Recommendation', function () {
|
||||
it('does not return instance of self', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -155,7 +155,7 @@ describe('Recommendation', function () {
|
||||
it('can edit known properties', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -176,7 +176,7 @@ describe('Recommendation', function () {
|
||||
it('can not edit unknown properties', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -199,7 +199,7 @@ describe('Recommendation', function () {
|
||||
it('can delete', function () {
|
||||
const recommendation = Recommendation.create({
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
|
@ -17,7 +17,7 @@ describe('RecommendationController', function () {
|
||||
return {
|
||||
id,
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: new URL('https://example.com/image.png'),
|
||||
favicon: new URL('https://example.com/favicon.ico'),
|
||||
@ -40,7 +40,7 @@ describe('RecommendationController', function () {
|
||||
data: [{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featured_image: 'https://example.com/image.png',
|
||||
favicon: 'https://example.com/favicon.ico',
|
||||
@ -61,7 +61,7 @@ describe('RecommendationController', function () {
|
||||
return {
|
||||
id: '1',
|
||||
title: plain.title,
|
||||
reason: plain.reason,
|
||||
description: plain.description,
|
||||
excerpt: plain.excerpt,
|
||||
featuredImage: plain.featuredImage ? new URL(plain.featuredImage.toString()) : null,
|
||||
favicon: plain.favicon ? new URL(plain.favicon.toString()) : null,
|
||||
@ -77,7 +77,7 @@ describe('RecommendationController', function () {
|
||||
recommendations: [
|
||||
{
|
||||
title: 'Test',
|
||||
reason: 'My reason',
|
||||
description: 'My description',
|
||||
excerpt: 'My excerpt',
|
||||
featured_image: 'https://example.com/image.png',
|
||||
favicon: 'https://example.com/favicon.ico',
|
||||
@ -94,7 +94,7 @@ describe('RecommendationController', function () {
|
||||
data: [{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: 'My reason',
|
||||
description: 'My description',
|
||||
excerpt: 'My excerpt',
|
||||
featured_image: 'https://example.com/image.png',
|
||||
favicon: 'https://example.com/favicon.ico',
|
||||
@ -113,7 +113,7 @@ describe('RecommendationController', function () {
|
||||
return {
|
||||
id: '1',
|
||||
title: plain.title,
|
||||
reason: plain.reason,
|
||||
description: plain.description,
|
||||
excerpt: plain.excerpt,
|
||||
featuredImage: plain.featuredImage ? new URL(plain.featuredImage.toString()) : null,
|
||||
favicon: plain.favicon ? new URL(plain.favicon.toString()) : null,
|
||||
@ -141,7 +141,7 @@ describe('RecommendationController', function () {
|
||||
data: [{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featured_image: null,
|
||||
favicon: null,
|
||||
@ -162,7 +162,7 @@ describe('RecommendationController', function () {
|
||||
return {
|
||||
id: '1',
|
||||
title: edit.title || 'Test',
|
||||
reason: edit.reason || null,
|
||||
description: edit.description || null,
|
||||
excerpt: edit.excerpt || null,
|
||||
featuredImage: edit.featuredImage ? new URL(edit.featuredImage.toString()) : null,
|
||||
favicon: edit.favicon ? new URL(edit.favicon.toString()) : null,
|
||||
@ -191,7 +191,7 @@ describe('RecommendationController', function () {
|
||||
data: [{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featured_image: null,
|
||||
favicon: null,
|
||||
@ -210,7 +210,7 @@ describe('RecommendationController', function () {
|
||||
return {
|
||||
id: '1',
|
||||
title: edit.title || 'Test',
|
||||
reason: edit.reason || null,
|
||||
description: edit.description || null,
|
||||
excerpt: edit.excerpt || null,
|
||||
featuredImage: edit.featuredImage ? new URL(edit.featuredImage.toString()) : null,
|
||||
favicon: edit.favicon ? new URL(edit.favicon.toString()) : null,
|
||||
@ -226,7 +226,7 @@ describe('RecommendationController', function () {
|
||||
recommendations: [
|
||||
{
|
||||
// All execpt title
|
||||
reason: 'My reason',
|
||||
description: 'My description',
|
||||
excerpt: 'My excerpt',
|
||||
featured_image: 'https://example.com/image.png',
|
||||
favicon: 'https://example.com/favicon.ico',
|
||||
@ -245,7 +245,7 @@ describe('RecommendationController', function () {
|
||||
data: [{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: 'My reason',
|
||||
description: 'My description',
|
||||
excerpt: 'My excerpt',
|
||||
featured_image: 'https://example.com/image.png',
|
||||
favicon: 'https://example.com/favicon.ico',
|
||||
@ -285,7 +285,7 @@ describe('RecommendationController', function () {
|
||||
{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: new URL('https://example.com/image.png'),
|
||||
favicon: new URL('https://example.com/favicon.ico'),
|
||||
@ -312,7 +312,7 @@ describe('RecommendationController', function () {
|
||||
data: [{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featured_image: 'https://example.com/image.png',
|
||||
favicon: 'https://example.com/favicon.ico',
|
||||
@ -341,7 +341,7 @@ describe('RecommendationController', function () {
|
||||
{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: new URL('https://example.com/image.png'),
|
||||
favicon: new URL('https://example.com/favicon.ico'),
|
||||
@ -369,7 +369,7 @@ describe('RecommendationController', function () {
|
||||
data: [{
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featured_image: 'https://example.com/image.png',
|
||||
favicon: 'https://example.com/favicon.ico',
|
||||
@ -489,7 +489,7 @@ describe('RecommendationController', function () {
|
||||
user: {}
|
||||
}),
|
||||
{
|
||||
message: 'order.0.field must be one of title, reason, excerpt, one_click_subscribe, created_at, updated_at, count.clicks, count.subscribers'
|
||||
message: 'order.0.field must be one of title, description, excerpt, one_click_subscribe, created_at, updated_at, count.clicks, count.subscribers'
|
||||
}
|
||||
);
|
||||
});
|
||||
@ -515,7 +515,7 @@ describe('RecommendationController', function () {
|
||||
let rec = {
|
||||
id: '1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: new URL('https://example.com/image.png'),
|
||||
favicon: new URL('https://example.com/favicon.ico'),
|
||||
|
@ -62,7 +62,7 @@ describe('RecommendationService', function () {
|
||||
Recommendation.create({
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -78,7 +78,7 @@ describe('RecommendationService', function () {
|
||||
Recommendation.create({
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -114,7 +114,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -136,7 +136,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -147,7 +147,7 @@ describe('RecommendationService', function () {
|
||||
await assert.rejects(() => service.addRecommendation({
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test 2',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -162,7 +162,7 @@ describe('RecommendationService', function () {
|
||||
const response = await service.addRecommendation({
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -170,7 +170,7 @@ describe('RecommendationService', function () {
|
||||
});
|
||||
assert.deepEqual(response, {
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -198,7 +198,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -211,7 +211,7 @@ describe('RecommendationService', function () {
|
||||
await assert.doesNotReject(() => service.addRecommendation({
|
||||
url: 'http://localhost/2',
|
||||
title: 'Test 2',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -237,7 +237,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -250,7 +250,7 @@ describe('RecommendationService', function () {
|
||||
});
|
||||
assert.deepEqual(response, {
|
||||
title: 'Test 2',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -289,7 +289,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -309,7 +309,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -327,7 +327,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -339,7 +339,7 @@ describe('RecommendationService', function () {
|
||||
id: '3',
|
||||
url: 'http://localhost/2',
|
||||
title: 'Test 2',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -366,7 +366,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -378,7 +378,7 @@ describe('RecommendationService', function () {
|
||||
id: '3',
|
||||
url: 'http://localhost/2',
|
||||
title: 'Test 2',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -399,7 +399,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -431,7 +431,7 @@ describe('RecommendationService', function () {
|
||||
id: '2',
|
||||
url: 'http://localhost/1',
|
||||
title: 'Test',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
|
@ -30,7 +30,7 @@ describe('WellknownService', function () {
|
||||
const recommendations = [
|
||||
Recommendation.create({
|
||||
title: 'My Blog',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
@ -41,7 +41,7 @@ describe('WellknownService', function () {
|
||||
}),
|
||||
Recommendation.create({
|
||||
title: 'My Other Blog',
|
||||
reason: null,
|
||||
description: null,
|
||||
excerpt: null,
|
||||
featuredImage: null,
|
||||
favicon: null,
|
||||
|
Loading…
Reference in New Issue
Block a user