0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-08 02:52:39 -05:00

Wired up creation of post_revisions entries when saving posts with lexical (#15422)

no issue

- added `PostRevsion` model
- duplicated `mobiledoc_revision` creation routine in Post model's onSaving hook to create `post_revision` when model's `lexical` field has changed
- updated `mobiledoc_revision` creation to skip when `lexical` field is populated
This commit is contained in:
Kevin Ansfield 2022-09-16 11:59:35 +01:00 committed by GitHub
parent 48aaa53770
commit 3b21d26be7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 550 additions and 85 deletions

View file

@ -0,0 +1,35 @@
const ghostBookshelf = require('./base');
const PostRevision = ghostBookshelf.Model.extend({
tableName: 'post_revisions'
}, {
permittedOptions(methodName) {
let options = ghostBookshelf.Model.permittedOptions.call(this, methodName);
const validOptions = {
findAll: ['filter', 'columns']
};
if (validOptions[methodName]) {
options = options.concat(validOptions[methodName]);
}
return options;
},
orderDefaultRaw() {
return 'created_at_ts DESC';
},
toJSON(unfilteredOptions) {
const options = PostRevision.filterOptions(unfilteredOptions, 'toJSON');
const attrs = ghostBookshelf.Model.prototype.toJSON.call(this, options);
// CASE: only for internal accuracy
delete attrs.created_at_ts;
return attrs;
}
});
module.exports = {
PostRevision: ghostBookshelf.model('PostRevision', PostRevision)
};

View file

@ -30,6 +30,7 @@ const messages = {
};
const MOBILEDOC_REVISIONS_COUNT = 10;
const POST_REVISIONS_COUNT = 10;
const ALL_STATUSES = ['published', 'draft', 'scheduled', 'sent'];
let Post;
@ -91,7 +92,7 @@ Post = ghostBookshelf.Model.extend({
};
},
relationships: ['tags', 'authors', 'mobiledoc_revisions', 'posts_meta', 'tiers'],
relationships: ['tags', 'authors', 'mobiledoc_revisions', 'post_revisions', 'posts_meta', 'tiers'],
// NOTE: look up object, not super nice, but was easy to implement
relationshipBelongsTo: {
@ -776,7 +777,7 @@ Post = ghostBookshelf.Model.extend({
}
// CASE: Handle mobiledoc backups/revisions. This is a pure database feature.
if (model.hasChanged('mobiledoc') && !options.importing && !options.migrating) {
if (model.hasChanged('mobiledoc') && !model.get('lexical') && !options.importing && !options.migrating) {
ops.push(function updateRevisions() {
return ghostBookshelf.model('MobiledocRevision')
.findAll(Object.assign({
@ -820,6 +821,39 @@ Post = ghostBookshelf.Model.extend({
});
}
// CASE: Handle post backups/revisions. This is a pure database feature.
if (model.hasChanged('lexical') && !model.get('mobiledoc') && !options.importing && !options.migrating) {
ops.push(function updateRevisions() {
return ghostBookshelf.model('PostRevision')
.findAll(Object.assign({
filter: `post_id:${model.id}`,
columns: ['id']
}, _.pick(options, 'transacting')))
.then((revisions) => {
// Store previous + latest lexical content
if (!revisions.length && options.method !== 'insert') {
model.set('post_revisions', [{
post_id: model.id,
lexical: model.previous('lexical'),
created_at_ts: Date.now() - 1
}, {
post_id: model.id,
lexical: model.get('lexical'),
created_at_ts: Date.now()
}]);
} else {
const revisionsJSON = revisions.toJSON().slice(0, POST_REVISIONS_COUNT - 1);
model.set('post_revisions', revisionsJSON.concat([{
post_id: model.id,
lexical: model.get('lexical'),
created_at_ts: Date.now()
}]));
}
});
});
}
if (this.get('tiers')) {
this.set('tiers', this.get('tiers').map(t => ({
id: t.id
@ -857,6 +891,10 @@ Post = ghostBookshelf.Model.extend({
return this.hasMany('MobiledocRevision', 'post_id');
},
post_revisions() {
return this.hasMany('PostRevision', 'post_id');
},
posts_meta: function postsMeta() {
return this.hasOne('PostsMeta', 'post_id');
},
@ -927,6 +965,7 @@ Post = ghostBookshelf.Model.extend({
// CASE: never expose the revisions
delete attrs.mobiledoc_revisions;
delete attrs.post_revisions;
// If the current column settings allow it...
if (!options.columns || (options.columns && options.columns.indexOf('primary_tag') > -1)) {

View file

@ -516,3 +516,283 @@ Object {
"x-powered-by": "Express",
}
`;
exports[`Posts API Update Can update a post with lexical 1: [body] 1`] = `
Object {
"posts": Array [
Object {
"authors": Any<Array>,
"canonical_url": null,
"codeinjection_foot": null,
"codeinjection_head": null,
"comment_id": Any<String>,
"count": Object {
"conversions": 0,
"signups": 0,
},
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"custom_excerpt": null,
"custom_template": null,
"email": null,
"email_only": false,
"email_segment": "all",
"email_subject": null,
"excerpt": "Original text",
"feature_image": null,
"feature_image_alt": null,
"feature_image_caption": null,
"featured": false,
"frontmatter": null,
"html": "<p>Original text</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[{\\"detail\\":0,\\"format\\":0,\\"mode\\":\\"normal\\",\\"style\\":\\"\\",\\"text\\":\\"Original text\\",\\"type\\":\\"text\\",\\"version\\":1}],\\"direction\\":\\"ltr\\",\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":\\"ltr\\",\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": null,
"newsletter": null,
"og_description": null,
"og_image": null,
"og_title": null,
"primary_author": Any<Object>,
"primary_tag": Any<Object>,
"published_at": null,
"reading_time": 0,
"slug": "lexical-update-test",
"status": "draft",
"tags": Any<Array>,
"tiers": Any<Array>,
"title": "Lexical update test",
"twitter_description": null,
"twitter_image": null,
"twitter_title": null,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"url": Any<String>,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"visibility": "public",
},
],
}
`;
exports[`Posts API Update Can update a post with lexical 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": "3694",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/posts\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Posts API Update Can update a post with lexical 3: [body] 1`] = `
Object {
"posts": Array [
Object {
"authors": Any<Array>,
"canonical_url": null,
"codeinjection_foot": null,
"codeinjection_head": null,
"comment_id": Any<String>,
"count": Object {
"conversions": 0,
"signups": 0,
},
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"custom_excerpt": null,
"custom_template": null,
"email": null,
"email_only": false,
"email_segment": "all",
"email_subject": null,
"excerpt": "Updated text",
"feature_image": null,
"feature_image_alt": null,
"feature_image_caption": null,
"featured": false,
"frontmatter": null,
"html": "<p>Updated text</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[{\\"detail\\":0,\\"format\\":0,\\"mode\\":\\"normal\\",\\"style\\":\\"\\",\\"text\\":\\"Updated text\\",\\"type\\":\\"text\\",\\"version\\":1}],\\"direction\\":\\"ltr\\",\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":\\"ltr\\",\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": null,
"newsletter": null,
"og_description": null,
"og_image": null,
"og_title": null,
"primary_author": Any<Object>,
"primary_tag": Any<Object>,
"published_at": null,
"reading_time": 0,
"slug": "lexical-update-test",
"status": "draft",
"tags": Any<Array>,
"tiers": Any<Array>,
"title": "Lexical update test",
"twitter_description": null,
"twitter_image": null,
"twitter_title": null,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"url": Any<String>,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"visibility": "public",
},
],
}
`;
exports[`Posts API Update Can update a post with lexical 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": "3691",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-cache-invalidate": Any<String>,
"x-powered-by": "Express",
}
`;
exports[`Posts API Update Can update a post with mobiledoc 1: [body] 1`] = `
Object {
"posts": Array [
Object {
"authors": Any<Array>,
"canonical_url": null,
"codeinjection_foot": null,
"codeinjection_head": null,
"comment_id": Any<String>,
"count": Object {
"conversions": 0,
"signups": 0,
},
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"custom_excerpt": null,
"custom_template": null,
"email": null,
"email_only": false,
"email_segment": "all",
"email_subject": null,
"excerpt": "Original text",
"feature_image": null,
"feature_image_alt": null,
"feature_image_caption": null,
"featured": false,
"frontmatter": null,
"html": "<p>Original text</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"Original text\\"]]]]}",
"newsletter": null,
"og_description": null,
"og_image": null,
"og_title": null,
"primary_author": Any<Object>,
"primary_tag": Any<Object>,
"published_at": null,
"reading_time": 0,
"slug": "mobiledoc-update-test",
"status": "draft",
"tags": Any<Array>,
"tiers": Any<Array>,
"title": "Mobiledoc update test",
"twitter_description": null,
"twitter_image": null,
"twitter_title": null,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"url": Any<String>,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"visibility": "public",
},
],
}
`;
exports[`Posts API Update Can update a post with mobiledoc 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": "3504",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/posts\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Posts API Update Can update a post with mobiledoc 3: [body] 1`] = `
Object {
"posts": Array [
Object {
"authors": Any<Array>,
"canonical_url": null,
"codeinjection_foot": null,
"codeinjection_head": null,
"comment_id": Any<String>,
"count": Object {
"conversions": 0,
"signups": 0,
},
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"custom_excerpt": null,
"custom_template": null,
"email": null,
"email_only": false,
"email_segment": "all",
"email_subject": null,
"excerpt": "Updated text",
"feature_image": null,
"feature_image_alt": null,
"feature_image_caption": null,
"featured": false,
"frontmatter": null,
"html": "<p>Updated text</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"Updated text\\"]]]]}",
"newsletter": null,
"og_description": null,
"og_image": null,
"og_title": null,
"primary_author": Any<Object>,
"primary_tag": Any<Object>,
"published_at": null,
"reading_time": 0,
"slug": "mobiledoc-update-test",
"status": "draft",
"tags": Any<Array>,
"tiers": Any<Array>,
"title": "Mobiledoc update test",
"twitter_description": null,
"twitter_image": null,
"twitter_title": null,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"url": Any<String>,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"visibility": "public",
},
],
}
`;
exports[`Posts API Update Can update a post with mobiledoc 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": "3501",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-cache-invalidate": Any<String>,
"x-powered-by": "Express",
}
`;

View file

@ -1,6 +1,8 @@
const should = require('should');
const assert = require('assert');
const {agentProvider, fixtureManager, mockManager, matchers} = require('../../utils/e2e-framework');
const {anyArray, anyEtag, anyErrorId, anyLocationFor, anyObject, anyObjectId, anyISODateTime, anyString, anyUuid} = matchers;
const models = require('../../../core/server/models');
const matchPostShallowIncludes = {
id: anyObjectId,
@ -17,6 +19,53 @@ const matchPostShallowIncludes = {
published_at: anyISODateTime
};
const createLexical = (text) => {
return JSON.stringify({
root: {
children: [
{
children: [
{
detail: 0,
format: 0,
mode: 'normal',
style: '',
text,
type: 'text',
version: 1
}
],
direction: 'ltr',
format: '',
indent: 0,
type: 'paragraph',
version: 1
}
],
direction: 'ltr',
format: '',
indent: 0,
type: 'root',
version: 1
}
});
};
const createMobiledoc = (text) => {
return JSON.stringify({
version: '0.3.1',
ghostVersion: '4.0',
markups: [],
atoms: [],
cards: [],
sections: [
[1, 'p', [
[0, [], 0, text]
]]
]
});
};
describe('Posts API', function () {
let agent;
@ -56,18 +105,7 @@ describe('Posts API', function () {
it('Can create a post with mobiledoc', async function () {
const post = {
title: 'Mobiledoc test',
mobiledoc: JSON.stringify({
version: '0.3.1',
ghostVersion: '4.0',
markups: [],
atoms: [],
cards: [],
sections: [
[1, 'p', [
[0, [], 0, 'Testing post creation with mobiledoc']
]]
]
}),
mobiledoc: createMobiledoc('Testing post creation with mobiledoc'),
lexical: null
};
@ -85,41 +123,15 @@ describe('Posts API', function () {
});
it('Can create a post with lexical', async function () {
const lexical = createLexical('Testing post creation with lexical');
const post = {
title: 'Lexical test',
mobiledoc: null,
lexical: JSON.stringify({
root: {
children: [
{
children: [
{
detail: 0,
format: 0,
mode: 'normal',
style: '',
text: 'Testing post creation with lexical',
type: 'text',
version: 1
}
],
direction: 'ltr',
format: '',
indent: 0,
type: 'paragraph',
version: 1
}
],
direction: 'ltr',
format: '',
indent: 0,
type: 'root',
version: 1
}
})
lexical
};
await agent
const {body} = await agent
.post('/posts/?formats=mobiledoc,lexical,html')
.body({posts: [post]})
.expectStatus(201)
@ -130,52 +142,32 @@ describe('Posts API', function () {
etag: anyEtag,
location: anyLocationFor('posts')
});
const [postResponse] = body.posts;
// post revision is created
const postRevisions = await models.PostRevision
.where('post_id', postResponse.id)
.orderBy('created_at_ts', 'desc')
.fetchAll();
postRevisions.length.should.equal(1);
postRevisions.at(0).get('lexical').should.equal(lexical);
// mobiledoc revision is not created
const mobiledocRevisions = await models.MobiledocRevision
.where('post_id', postResponse.id)
.orderBy('created_at_ts', 'desc')
.fetchAll();
mobiledocRevisions.length.should.equal(0);
});
it('Errors if both mobiledoc and lexical are present', async function () {
const post = {
title: 'Mobiledoc+lexical test',
mobiledoc: JSON.stringify({
version: '0.3.1',
ghostVersion: '4.0',
markups: [],
atoms: [],
cards: [],
sections: [
[1, 'p', [
[0, [], 0, 'Testing post creation with mobiledoc']
]]
]
}),
lexical: JSON.stringify({
root: {
children: [
{
children: [
{
detail: 0,
format: 0,
mode: 'normal',
style: '',
text: 'Testing post creation with lexical',
type: 'text',
version: 1
}
],
direction: 'ltr',
format: '',
indent: 0,
type: 'paragraph',
version: 1
}
],
direction: 'ltr',
format: '',
indent: 0,
type: 'root',
version: 1
}
})
mobiledoc: createMobiledoc('Testing post creation with mobiledoc'),
lexical: createLexical('Testing post creation with lexical')
};
await agent
@ -215,6 +207,112 @@ describe('Posts API', function () {
});
});
describe('Update', function () {
it('Can update a post with mobiledoc', async function () {
const originalMobiledoc = createMobiledoc('Original text');
const updatedMobiledoc = createMobiledoc('Updated text');
const {body: postBody} = await agent
.post('/posts/?formats=mobiledoc,lexical,html')
.body({posts: [{
title: 'Mobiledoc update test',
mobiledoc: originalMobiledoc
}]})
.expectStatus(201)
.matchBodySnapshot({
posts: [Object.assign(matchPostShallowIncludes, {published_at: null})]
})
.matchHeaderSnapshot({
etag: anyEtag,
location: anyLocationFor('posts')
});
const [postResponse] = postBody.posts;
await agent
.put(`/posts/${postResponse.id}/?formats=mobiledoc,lexical,html`)
.body({posts: [Object.assign({}, postResponse, {mobiledoc: updatedMobiledoc})]})
.expectStatus(200)
.matchBodySnapshot({
posts: [Object.assign(matchPostShallowIncludes, {published_at: null})]
})
.matchHeaderSnapshot({
etag: anyEtag,
'x-cache-invalidate': anyString
});
// mobiledoc revisions are created
const mobiledocRevisions = await models.MobiledocRevision
.where('post_id', postResponse.id)
.orderBy('created_at_ts', 'desc')
.fetchAll();
mobiledocRevisions.length.should.equal(2);
mobiledocRevisions.at(0).get('mobiledoc').should.equal(updatedMobiledoc);
mobiledocRevisions.at(1).get('mobiledoc').should.equal(originalMobiledoc);
// post revisions are not created
const postRevisions = await models.PostRevision
.where('post_id', postResponse.id)
.orderBy('created_at_ts', 'desc')
.fetchAll();
postRevisions.length.should.equal(0);
});
it('Can update a post with lexical', async function () {
const originalLexical = createLexical('Original text');
const updatedLexical = createLexical('Updated text');
const {body: postBody} = await agent
.post('/posts/?formats=mobiledoc,lexical,html')
.body({posts: [{
title: 'Lexical update test',
lexical: originalLexical
}]})
.expectStatus(201)
.matchBodySnapshot({
posts: [Object.assign(matchPostShallowIncludes, {published_at: null})]
})
.matchHeaderSnapshot({
etag: anyEtag,
location: anyLocationFor('posts')
});
const [postResponse] = postBody.posts;
await agent
.put(`/posts/${postResponse.id}/?formats=mobiledoc,lexical,html`)
.body({posts: [Object.assign({}, postResponse, {lexical: updatedLexical})]})
.expectStatus(200)
.matchBodySnapshot({
posts: [Object.assign(matchPostShallowIncludes, {published_at: null})]
})
.matchHeaderSnapshot({
etag: anyEtag,
'x-cache-invalidate': anyString
});
// post revisions are created
const postRevisions = await models.PostRevision
.where('post_id', postResponse.id)
.orderBy('created_at_ts', 'desc')
.fetchAll();
postRevisions.length.should.equal(2);
postRevisions.at(0).get('lexical').should.equal(updatedLexical);
postRevisions.at(1).get('lexical').should.equal(originalLexical);
// mobiledoc revisions are not created
const mobiledocRevisions = await models.MobiledocRevision
.where('post_id', postResponse.id)
.orderBy('created_at_ts', 'desc')
.fetchAll();
mobiledocRevisions.length.should.equal(0);
});
});
describe('Delete', function () {
it('Can destroy a post', async function () {
await agent

View file

@ -97,6 +97,7 @@ describe('Exporter', function () {
const excludedTables = [
'sessions',
'mobiledoc_revisions',
'post_revisions',
'email_batches',
'email_recipients',
'members_cancel_events',

View file

@ -250,6 +250,18 @@ describe('Unit: models/post', function () {
should.not.exist(json.mobiledoc_revisions);
should.exist(json.mobiledoc);
});
it('ensure post revisions are never exposed', function () {
const post = {
lexical: '{}',
post_revisions: []
};
const json = toJSON(post, {formats: ['lexical']});
should.not.exist(json.post_revisions);
should.exist(json.lexical);
});
});
describe('extraFilters', function () {