From b49cf1428779f1cbc54bf4287bb5591953d17543 Mon Sep 17 00:00:00 2001 From: Michael Barrett <991592+mike182uk@users.noreply.github.com> Date: Thu, 6 Jul 2023 08:45:56 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20member=20import=20newsle?= =?UTF-8?q?tter=20subscription=20prefs=20(#17208)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes https://github.com/TryGhost/Product/issues/2947 When an import is performed and a member already exists: - If `subscribe_to_emails` is set to `true` and the existing member already has newsletter subscriptions, these are preserved - If `subscribe_to_emails` is set to `true` and the existing member does not already have newsletter subscriptions, no new subscriptions are added in case the member has previously unsubscribed - If `subscribe_to_emails` is set to `false` the existing member will be unsubscribed from all newsletters regardless of their preference --- .../lib/MembersCSVImporter.js | 15 +++- ghost/members-importer/test/importer.test.js | 84 +++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/ghost/members-importer/lib/MembersCSVImporter.js b/ghost/members-importer/lib/MembersCSVImporter.js index 66fc4e353c..2e65c7f618 100644 --- a/ghost/members-importer/lib/MembersCSVImporter.js +++ b/ghost/members-importer/lib/MembersCSVImporter.js @@ -138,11 +138,24 @@ module.exports = class MembersCSVImporter { }; const existingMember = await membersRepository.get({email: memberValues.email}, { ...options, - withRelated: ['labels'] + withRelated: ['labels', 'newsletters'] }); let member; if (existingMember) { const existingLabels = existingMember.related('labels') ? existingMember.related('labels').toJSON() : []; + const existingNewsletters = existingMember.related('newsletters'); + + // Preserve member's existing newsletter subscription preferences + if (existingNewsletters.length > 0 && memberValues.subscribed) { + memberValues.newsletters = existingNewsletters.toJSON(); + } + + // If member does not have any subscriptions, assume they have previously unsubscribed + // and do not re-subscribe them + if (!existingNewsletters.length && memberValues.subscribed) { + memberValues.subscribed = false; + } + member = await membersRepository.update({ ...memberValues, labels: existingLabels.concat(memberValues.labels) diff --git a/ghost/members-importer/test/importer.test.js b/ghost/members-importer/test/importer.test.js index 01bb45cf6e..093d3b927a 100644 --- a/ghost/members-importer/test/importer.test.js +++ b/ghost/members-importer/test/importer.test.js @@ -343,5 +343,89 @@ describe('Importer', function () { assert.equal(result.imported, 1); assert.equal(result.errors.length, 0); }); + + it ('respects existing member newsletter subscription preferences', async function () { + const importer = buildMockImporterInstance(); + + const newsletters = [ + {id: 'newsletter_1'}, + {id: 'newsletter_2'} + ]; + + const newslettersCollection = { + length: newsletters.length, + toJSON: sinon.stub().returns(newsletters) + }; + + const member = { + related: sinon.stub() + }; + + member.related.withArgs('labels').returns(null); + member.related.withArgs('newsletters').returns(newslettersCollection); + + membersRepositoryStub.get = sinon.stub(); + + membersRepositoryStub.get + .withArgs({email: 'jbloggs@example.com'}) + .resolves(member); + + await importer.perform(`${csvPath}/subscribed-to-emails-header.csv`, defaultAllowedFields); + + assert.deepEqual(membersRepositoryStub.update.args[0][0].newsletters, newsletters); + }); + + it ('does not add subscriptions for existing member when they do not have any subscriptions', async function () { + const importer = buildMockImporterInstance(); + + const member = { + related: sinon.stub() + }; + + member.related.withArgs('labels').returns(null); + member.related.withArgs('newsletters').returns({length: 0}); + + membersRepositoryStub.get = sinon.stub(); + + membersRepositoryStub.get + .withArgs({email: 'jbloggs@example.com'}) + .resolves(member); + + await importer.perform(`${csvPath}/subscribed-to-emails-header.csv`, defaultAllowedFields); + + assert.deepEqual(membersRepositoryStub.update.args[0][0].subscribed, false); + }); + + it ('removes existing member newsletter subscriptions when set to not be subscribed', async function () { + const importer = buildMockImporterInstance(); + + const newsletters = [ + {id: 'newsletter_1'}, + {id: 'newsletter_2'} + ]; + + const newslettersCollection = { + length: newsletters.length, + toJSON: sinon.stub().returns(newsletters) + }; + + const member = { + related: sinon.stub() + }; + + member.related.withArgs('labels').returns(null); + member.related.withArgs('newsletters').returns(newslettersCollection); + + membersRepositoryStub.get = sinon.stub(); + + membersRepositoryStub.get + .withArgs({email: 'test@example.com'}) + .resolves(member); + + await importer.perform(`${csvPath}/subscribed-to-emails-header.csv`, defaultAllowedFields); + + assert.equal(membersRepositoryStub.update.args[0][0].subscribed, false); + assert.equal(membersRepositoryStub.update.args[0][0].newsletters, undefined); + }); }); });