5f90baf6fe
refs: https://www.getrevue.co/app/offboard - Revue is stopping all paid subscriptions on 20th Dec, and shutting down on Jan 18th. - This update allows Ghost to accept and handle the zip file Revue are providing as an export in Labs > Importer - It will import posts (as best as we can with the data provided) and subscribers as free members - At present it doesn't import paid subscribers, as we don't have that info, but you can disconnect Revue from your Stripe account to prevent all your subscriptions being cancelled & there's the option this can be fixed later - There will be further updates to polish up this tooling - this is just a first pass to try to get something in people's hands Co-authored-by: Paul Davis <PaulAdamDavis@users.noreply.github.com>
228 lines
14 KiB
JavaScript
228 lines
14 KiB
JavaScript
const assert = require('assert');
|
|
const sinon = require('sinon');
|
|
const RevueImporter = require('../index');
|
|
|
|
const JSONToHTML = require('../lib/json-to-html');
|
|
|
|
describe('Revue Importer', function () {
|
|
afterEach(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
describe('preProcess', function () {
|
|
it('marks any object as processed', function () {
|
|
let result;
|
|
|
|
result = RevueImporter.preProcess({});
|
|
assert.deepEqual(result.preProcessedByRevue, true, 'marks the object as processed');
|
|
|
|
result = RevueImporter.preProcess({revue: {}});
|
|
assert.deepEqual(result.preProcessedByRevue, true, 'marks the object as processed');
|
|
|
|
result = RevueImporter.preProcess({data: {}});
|
|
assert.deepEqual(result.preProcessedByRevue, true, 'marks the object as processed');
|
|
});
|
|
|
|
it('ignores empty revue object', function () {
|
|
const result = RevueImporter.preProcess({revue: {}});
|
|
assert.deepEqual(result.revue, {}, 'revue object left empty');
|
|
assert.deepEqual(result.data, undefined, 'no data object set');
|
|
});
|
|
|
|
it('ignores empty nested revue object', function () {
|
|
const result = RevueImporter.preProcess({revue: {revue: {}}});
|
|
assert.deepEqual(result.revue.revue, {}, 'revue object left empty');
|
|
assert.deepEqual(result.data, undefined, 'no data object set');
|
|
});
|
|
|
|
it('handles revue with issue and item data', function () {
|
|
const result = RevueImporter.preProcess({revue: {revue: {issues: 'id', items: '{}'}}});
|
|
assert.deepEqual(result.revue.revue, {issues: 'id', items: '{}'}, 'revue object left as-is');
|
|
assert.deepEqual(result.data, {meta: {version: '5.0.0'}, data: {posts: []}}, 'data object is set');
|
|
});
|
|
|
|
it('handles revue with issue, item and subscribers data', function () {
|
|
const result = RevueImporter.preProcess({revue: {revue: {issues: 'id', items: '{}', subscribers: 'email'}}});
|
|
assert.deepEqual(result.revue.revue, {issues: 'id', items: '{}', subscribers: 'email'}, 'revue object left as-is');
|
|
assert.deepEqual(result.data, {meta: {version: '5.0.0'}, data: {posts: [], revue_subscribers: []}}, 'data object is set');
|
|
});
|
|
});
|
|
|
|
describe('doImport', function () {
|
|
it('does nothing', function () {
|
|
const result = RevueImporter.doImport({x: {y: 'z'}});
|
|
assert.deepEqual(result, {x: {y: 'z'}}, 'is just a pass-through');
|
|
});
|
|
});
|
|
|
|
describe('importPosts', function () {
|
|
it('can process a published post without items', function () {
|
|
const result = RevueImporter.importPosts({items: '[]', issues: 'id,description,sent_at,subject,preheader\n123456,"<p>Hello World!</p>",2022-12-01 01:01:30 UTC,Hello World - Issue #8,'});
|
|
assert.deepEqual(result, [
|
|
{
|
|
comment_id: 123456,
|
|
title: 'Hello World - Issue #8',
|
|
slug: 'hello-world-issue-8',
|
|
status: 'published',
|
|
visibility: 'public',
|
|
created_at: '2022-12-01T01:01:30.000Z',
|
|
published_at: '2022-12-01T01:01:30.000Z',
|
|
updated_at: '2022-12-01T01:01:30.000Z',
|
|
html: '<p>Hello World!</p>',
|
|
tags: ['#revue']
|
|
}
|
|
]);
|
|
});
|
|
|
|
it('doesnt process a post with no subject', function () {
|
|
const result = RevueImporter.importPosts({items: '[{"title":"","issue_id":123456,"item_type":"text","url":"","description":"\u003cp\u003eGoodbye World!\u003c/p\u003e","order":0}]', issues: 'id,description,sent_at,subject,preheader\n123456,"<p>Hello World!</p>",2022-12-01 01:01:30 UTC,,'});
|
|
assert.deepEqual(result, []);
|
|
});
|
|
|
|
it('can process a published post with items', function () {
|
|
const result = RevueImporter.importPosts({items: '[{"title":"","issue_id":123456,"item_type":"text","url":"","description":"\u003cp\u003eGoodbye World!\u003c/p\u003e","order":0}]', issues: 'id,description,sent_at,subject,preheader\n123456,"<p>Hello World!</p>",2022-12-01 01:01:30 UTC,Hello World - Issue #8,'});
|
|
assert.deepEqual(result, [
|
|
{
|
|
comment_id: 123456,
|
|
created_at: '2022-12-01T01:01:30.000Z',
|
|
html: '<p>Hello World!</p><p>Goodbye World!</p>',
|
|
published_at: '2022-12-01T01:01:30.000Z',
|
|
status: 'published',
|
|
tags: [
|
|
'#revue'
|
|
],
|
|
title: 'Hello World - Issue #8',
|
|
slug: 'hello-world-issue-8',
|
|
updated_at: '2022-12-01T01:01:30.000Z',
|
|
visibility: 'public'
|
|
}
|
|
]);
|
|
});
|
|
|
|
it('can process a draft post with items', function () {
|
|
sinon.stub(JSONToHTML, 'getPostDate').returns('2022-12-01T01:02:03.123Z');
|
|
|
|
const result = RevueImporter.importPosts({items: '[{"title":"","issue_id":123456,"item_type":"text","url":"","description":"\u003cp\u003eGoodbye World!\u003c/p\u003e","order":0}]', issues: 'id,description,sent_at,subject,preheader\n123456,"<p>Hello World!</p>",,Hello World - Issue #8,'});
|
|
assert.deepEqual(result, [
|
|
{
|
|
comment_id: 123456,
|
|
title: 'Hello World - Issue #8',
|
|
slug: 'hello-world-issue-8',
|
|
status: 'draft',
|
|
visibility: 'public',
|
|
created_at: '2022-12-01T01:02:03.123Z',
|
|
published_at: '2022-12-01T01:02:03.123Z',
|
|
updated_at: '2022-12-01T01:02:03.123Z',
|
|
html: '<p>Hello World!</p><p>Goodbye World!</p>',
|
|
tags: ['#revue']
|
|
}
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('importSubscribers', function () {
|
|
it('can process a subscriber with only first name', function () {
|
|
const result = RevueImporter.importSubscribers({subscribers: 'email,first_name,last_name,created_at\njoe@bloggs.me,Joe,"",2022-12-01 01:02:03.123457'});
|
|
|
|
assert.deepEqual(result, [{email: 'joe@bloggs.me', name: 'Joe', created_at: '2022-12-01 01:02:03.123457'}]);
|
|
});
|
|
|
|
it('can process a subscriber with first and last name', function () {
|
|
const result = RevueImporter.importSubscribers({subscribers: 'email,first_name,last_name,created_at\njoe@bloggs.me,Joe,Bloggs,2022-12-01 01:02:03.123457'});
|
|
|
|
assert.deepEqual(result, [{email: 'joe@bloggs.me', name: 'Joe Bloggs', created_at: '2022-12-01 01:02:03.123457'}]);
|
|
});
|
|
|
|
it('can process multiple subscribers', function () {
|
|
const result = RevueImporter.importSubscribers({subscribers: 'email,first_name,last_name,created_at\njoe@bloggs.me,Joe,Bloggs,2022-12-01 01:02:03.123457\njo@bloggs.me,Jo,Bloggs,2022-12-01 01:02:04.123457'});
|
|
|
|
assert.deepEqual(result, [{email: 'joe@bloggs.me', name: 'Joe Bloggs', created_at: '2022-12-01 01:02:03.123457'},{email: 'jo@bloggs.me', name: 'Jo Bloggs', created_at: '2022-12-01 01:02:04.123457'}]);
|
|
});
|
|
});
|
|
|
|
describe('JSONToHTML helpers', function () {
|
|
describe('getPostData', function () {
|
|
it('can get date for published post', function () {
|
|
const result = JSONToHTML.getPostDate({sent_at: '2022-12-01 01:01:30 UTC'});
|
|
|
|
assert.deepEqual(result, '2022-12-01T01:01:30.000Z');
|
|
});
|
|
|
|
it('can get date for draft post', function () {
|
|
const result = JSONToHTML.getPostDate({});
|
|
|
|
assert.equal(result, new Date().toISOString());
|
|
});
|
|
});
|
|
|
|
describe('getPostStatus', function () {
|
|
it('can get date for published post', function () {
|
|
const result = JSONToHTML.getPostStatus({sent_at: '2022-12-01 01:01:30 UTC'});
|
|
|
|
assert.deepEqual(result, 'published');
|
|
});
|
|
|
|
it('can get date for draft post', function () {
|
|
const result = JSONToHTML.getPostStatus({});
|
|
|
|
assert.deepEqual(result, 'draft');
|
|
});
|
|
});
|
|
|
|
describe('itemsToHtml', function () {
|
|
it('can handle header item', function () {
|
|
const result = JSONToHTML.itemsToHtml([{title: 'Hello World',issue_id: 123456,item_type: 'header',url: '',description: '',order: 0}]);
|
|
|
|
assert.deepEqual(result, '<h3>Hello World</h3>');
|
|
});
|
|
|
|
it('can handle link item', function () {
|
|
const result = JSONToHTML.itemsToHtml([{title: 'Google',issue_id: 123456,item_type: 'link',url: 'https://google.com/',description: 'A search engine.',order: 0,image: 'https://s3.amazonaws.com/revue/items/images/012/345/678/web/google.png?1234556'}]);
|
|
|
|
assert.deepEqual(result, '<figure class="kg-card kg-image-card kg-card-hascaption"><a href="https://google.com/"><img src="https://s3.amazonaws.com/revue/items/images/012/345/678/web/google.png?1234556" class="kg-image" alt loading="lazy"></a><figcaption>Google</figcaption></figure>\n' +
|
|
'<h4><a href="https://google.com/">Google</a></h4>A search engine.');
|
|
});
|
|
|
|
it('can handle link item with html in description', function () {
|
|
const result = JSONToHTML.itemsToHtml([{title: 'Google',issue_id: 123456,item_type: 'link',url: 'https://google.com/',description: '<p>A <b>search</b> engine.</p>',order: 0,image: 'https://s3.amazonaws.com/revue/items/images/012/345/678/web/google.png?1234556'}]);
|
|
|
|
assert.deepEqual(result, '<figure class="kg-card kg-image-card kg-card-hascaption"><a href="https://google.com/"><img src="https://s3.amazonaws.com/revue/items/images/012/345/678/web/google.png?1234556" class="kg-image" alt loading="lazy"></a><figcaption>Google</figcaption></figure>\n' +
|
|
'<h4><a href="https://google.com/">Google</a></h4><p>A <b>search</b> engine.</p>');
|
|
});
|
|
|
|
it('can handle image item', function () {
|
|
const result = JSONToHTML.itemsToHtml([{title: '', issue_id: 123456, item_type: 'image', url: '', description: 'Hello', order: 0, image: 'https://s3.amazonaws.com/revue/items/images/012/345/678/web/google.png?1234556', original_image_url: 'https://s3.amazonaws.com/revue/items/images/012/345/678/original/google.png?1234556'}]);
|
|
|
|
assert.deepEqual(result, '<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://s3.amazonaws.com/revue/items/images/012/345/678/web/google.png?1234556" class="kg-image" alt loading="lazy"><figcaption>Hello</figcaption></figure>');
|
|
});
|
|
|
|
it('can handle tweet item', function () {
|
|
const result = JSONToHTML.itemsToHtml([{title: 'Ghost',issue_id: 123456,item_type: 'tweet',url: 'https://twitter.com/Ghost/status/123456',description: 'Hello world',order: 0,tweet_profile_image: 'https://s3.amazonaws.com/revue/tweet_items/profile_images/000/123/456/thumb/ABCD_normal.png?12345',tweet_handle: 'Ghost',tweet_description: '\u003cspan\u003eHello world\u003c/span\u003e',tweet_lang: 'en'}]);
|
|
|
|
assert.deepEqual(result, '<figure class="kg-card kg-embed-card">\n' +
|
|
' <blockquote class="twitter-tweet"><a href="https://twitter.com/Ghost/status/123456"></a></blockquote>\n' +
|
|
' <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>\n' +
|
|
' </figure>');
|
|
});
|
|
|
|
it('can handle long youtube video item', function () {
|
|
const result = JSONToHTML.itemsToHtml([{title: '', issue_id: 123456, item_type: 'video', url: 'https://www.youtube.com/watch?v=ABCDEF', description: 'Hello World', order: 0, image: 'https://s3.amazonaws.com/revue/items/images/012/345/678/web/maxresdefault.jpg?1667924432'}]);
|
|
|
|
assert.deepEqual(result, '<figure class="kg-card kg-embed-card kg-card-hascaption"><iframe width="200" height="113" src="https://www.youtube.com/embed/ABCDEF?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><figcaption>Hello World</figcaption></figure>');
|
|
});
|
|
|
|
it('can handle short youtube video item', function () {
|
|
const result = JSONToHTML.itemsToHtml([{title: '', issue_id: 123456, item_type: 'video', url: 'https://youtu.be/ABCDEF', description: 'Hello World', order: 2, image: 'https://s3.amazonaws.com/revue/items/images/006/606/464/web/maxresdefault.jpg?1601883862'}]);
|
|
|
|
assert.deepEqual(result, '<figure class="kg-card kg-embed-card kg-card-hascaption"><iframe width="200" height="113" src="https://www.youtube.com/embed/ABCDEF?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><figcaption>Hello World</figcaption></figure>');
|
|
});
|
|
|
|
it('can handle vimeo video item', function () {
|
|
const result = JSONToHTML.itemsToHtml([{title: '', issue_id: 123456, item_type: 'video', url: 'https://vimeo.com/789123', description: 'Hello world', order: 2, image: 'https://s3.amazonaws.com/revue/items/images/006/606/464/web/maxresdefault.jpg?1601883862'}]);
|
|
|
|
assert.deepEqual(result, '<figure class="kg-card kg-embed-card kg-card-hascaption"><iframe src="https://player.vimeo.com/video/789123" width="200" height="113" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe><figcaption>Hello world</figcaption></figure>');
|
|
});
|
|
});
|
|
});
|
|
});
|