diff --git a/ghost/core/test/e2e-server/services/mentions.test.js b/ghost/core/test/e2e-server/services/mentions.test.js index ee9870356e..7ea2cb5da7 100644 --- a/ghost/core/test/e2e-server/services/mentions.test.js +++ b/ghost/core/test/e2e-server/services/mentions.test.js @@ -77,6 +77,17 @@ describe('Mentions Service', function () { assert.equal(mentionMock.isDone(), false); assert.equal(endpointMock.isDone(), false); }); + + it('Post without content', async function () { + let publishedPost = {status: 'published', mobiledoc: markdownToMobiledoc(''), title: 'empty post'}; + await agent + .post('posts/') + .body({posts: [publishedPost]}) + .expectStatus(201); + + assert.equal(mentionMock.isDone(), false); + assert.equal(endpointMock.isDone(), false); + }); }); describe(`does send when we expect it to send`, function () { diff --git a/ghost/webmentions/lib/MentionSendingService.js b/ghost/webmentions/lib/MentionSendingService.js index f6f3d2cc68..c5f3f8ff76 100644 --- a/ghost/webmentions/lib/MentionSendingService.js +++ b/ghost/webmentions/lib/MentionSendingService.js @@ -59,13 +59,18 @@ module.exports = class MentionSendingService { // Post should be or should have been published return; } - await this.#jobService.addJob('sendWebmentions', async () => { - await this.sendAll({ - url: new URL(this.#getPostUrl(post)), - html: post.get('html'), - previousHtml: post.previous('status') === 'published' ? post.previous('html') : null + // make sure we have something to parse before we create a job + let html = post.get('html'); + let previousHtml = post.previous('status') === 'published' ? post.previous('html') : null; + if (html || previousHtml) { + await this.#jobService.addJob('sendWebmentions', async () => { + await this.sendAll({ + url: new URL(this.#getPostUrl(post)), + html: html, + previousHtml: previousHtml + }); }); - }); + } } catch (e) { logging.error('Error in webmention sending service post update event handler:'); logging.error(e); @@ -104,7 +109,7 @@ module.exports = class MentionSendingService { * @param {string|null} [resource.previousHtml] */ async sendAll(resource) { - const links = this.getLinks(resource.html); + const links = resource.html ? this.getLinks(resource.html) : []; if (resource.previousHtml) { // We also need to send webmentions for removed links const oldLinks = this.getLinks(resource.previousHtml); diff --git a/ghost/webmentions/test/MentionSendingService.test.js b/ghost/webmentions/test/MentionSendingService.test.js index c4694983b6..bf8d70441b 100644 --- a/ghost/webmentions/test/MentionSendingService.test.js +++ b/ghost/webmentions/test/MentionSendingService.test.js @@ -188,6 +188,24 @@ describe('MentionSendingService', function () { })); assert(errorLogStub.calledTwice); }); + + it('Sends no mentions for posts without html and previous html', async function () { + const service = new MentionSendingService({ + isEnabled: () => true, + getPostUrl: () => 'https://site.com/post/', + jobService: jobService + }); + const stub = sinon.stub(service, 'sendAll'); + await service.sendForPost(createModel({ + status: 'published', + html: '', + previous: { + status: 'draft', + html: '' + } + })); + assert(stub.notCalled); + }); }); describe('sendAll', function () { @@ -283,6 +301,16 @@ describe('MentionSendingService', function () { assert.strictEqual(scope.isDone(), true); assert.equal(counter, 2); }); + + // cheerio must be served a string + it('Does not evaluate links for an empty post', async function () { + const service = new MentionSendingService({ + isEnabled: () => true + }); + const linksStub = sinon.stub(service, 'getLinks'); + await service.sendAll({html: ``,previousHtml: ``}); + sinon.assert.notCalled(linksStub); + }); }); describe('getLinks', function () {