2021-07-21 16:28:39 +03:00
|
|
|
// Switch these lines once there are useful utils
|
|
|
|
// const testUtils = require('./utils');
|
|
|
|
require('./utils');
|
|
|
|
|
2022-11-08 07:47:00 +03:00
|
|
|
const Tier = require('@tryghost/tiers/lib/Tier');
|
|
|
|
const ObjectID = require('bson-objectid').default;
|
2022-10-13 10:16:09 +03:00
|
|
|
const assert = require('assert');
|
2021-07-21 18:25:41 +03:00
|
|
|
const fs = require('fs-extra');
|
2021-07-21 16:28:39 +03:00
|
|
|
const path = require('path');
|
|
|
|
const sinon = require('sinon');
|
|
|
|
const MembersCSVImporter = require('..');
|
|
|
|
|
|
|
|
const csvPath = path.join(__dirname, '/fixtures/');
|
|
|
|
|
|
|
|
describe('Importer', function () {
|
2021-07-21 18:25:41 +03:00
|
|
|
let fsWriteSpy;
|
2022-10-13 09:21:08 +03:00
|
|
|
let memberCreateStub;
|
|
|
|
let knexStub;
|
|
|
|
let sendEmailStub;
|
2022-10-25 11:40:28 +03:00
|
|
|
let membersRepositoryStub;
|
2022-11-08 07:47:00 +03:00
|
|
|
let defaultTierId;
|
2021-07-21 18:25:41 +03:00
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
const defaultAllowedFields = {
|
|
|
|
email: 'email',
|
|
|
|
name: 'name',
|
|
|
|
note: 'note',
|
|
|
|
subscribed_to_emails: 'subscribed',
|
|
|
|
created_at: 'created_at',
|
|
|
|
complimentary_plan: 'complimentary_plan',
|
|
|
|
stripe_customer_id: 'stripe_customer_id',
|
2022-10-24 13:03:44 +03:00
|
|
|
labels: 'labels'
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
};
|
|
|
|
|
2021-07-21 18:25:41 +03:00
|
|
|
beforeEach(function () {
|
|
|
|
fsWriteSpy = sinon.spy(fs, 'writeFile');
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
2022-08-23 22:19:30 +03:00
|
|
|
const writtenFile = fsWriteSpy.args?.[0]?.[0];
|
2021-07-21 18:25:41 +03:00
|
|
|
|
|
|
|
if (writtenFile) {
|
|
|
|
fs.removeSync(writtenFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
sinon.restore();
|
|
|
|
});
|
|
|
|
|
2022-10-13 09:21:08 +03:00
|
|
|
const buildMockImporterInstance = () => {
|
2022-11-08 07:47:00 +03:00
|
|
|
defaultTierId = new ObjectID();
|
|
|
|
const defaultTierDummy = new Tier({
|
|
|
|
id: defaultTierId
|
|
|
|
});
|
2022-10-13 09:21:08 +03:00
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
memberCreateStub = sinon.stub().resolves({
|
|
|
|
id: `test_member_id`
|
|
|
|
});
|
2022-10-25 11:40:28 +03:00
|
|
|
membersRepositoryStub = {
|
|
|
|
get: async () => {
|
|
|
|
return null;
|
2022-10-13 09:21:08 +03:00
|
|
|
},
|
2022-10-25 11:40:28 +03:00
|
|
|
create: memberCreateStub,
|
|
|
|
update: sinon.stub().resolves(null),
|
|
|
|
linkStripeCustomer: sinon.stub().resolves(null)
|
2022-10-13 09:21:08 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
knexStub = {
|
|
|
|
transaction: sinon.stub().resolves({
|
|
|
|
rollback: () => {},
|
|
|
|
commit: () => {}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
sendEmailStub = sinon.stub();
|
|
|
|
|
|
|
|
return new MembersCSVImporter({
|
|
|
|
storagePath: csvPath,
|
|
|
|
getTimezone: sinon.stub().returns('UTC'),
|
2022-10-25 11:40:28 +03:00
|
|
|
getMembersRepository: () => {
|
|
|
|
return membersRepositoryStub;
|
|
|
|
},
|
|
|
|
getDefaultTier: () => {
|
|
|
|
return defaultTierDummy;
|
|
|
|
},
|
2022-10-13 09:21:08 +03:00
|
|
|
sendEmail: sendEmailStub,
|
|
|
|
isSet: sinon.stub(),
|
|
|
|
addJob: sinon.stub(),
|
|
|
|
knex: knexStub,
|
|
|
|
urlFor: sinon.stub(),
|
|
|
|
context: {importer: true}
|
|
|
|
});
|
|
|
|
};
|
2021-07-21 16:28:39 +03:00
|
|
|
|
2022-10-13 09:21:08 +03:00
|
|
|
describe('process', function () {
|
|
|
|
it('should import a CSV file', async function () {
|
2021-07-21 16:28:39 +03:00
|
|
|
const LabelModelStub = {
|
|
|
|
findOne: sinon.stub().resolves(null)
|
|
|
|
};
|
|
|
|
|
2022-10-13 09:21:08 +03:00
|
|
|
const importer = buildMockImporterInstance();
|
2021-07-23 19:29:19 +03:00
|
|
|
|
|
|
|
const result = await importer.process({
|
|
|
|
pathToCSV: `${csvPath}/single-column-with-header.csv`,
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
headerMapping: defaultAllowedFields,
|
2021-07-23 19:29:19 +03:00
|
|
|
importLabel: {
|
|
|
|
name: 'test import'
|
|
|
|
},
|
|
|
|
user: {
|
|
|
|
email: 'test@example.com'
|
|
|
|
},
|
|
|
|
LabelModel: LabelModelStub
|
|
|
|
});
|
|
|
|
|
|
|
|
should.exist(result.meta);
|
|
|
|
should.exist(result.meta.stats);
|
|
|
|
should.exist(result.meta.stats.imported);
|
|
|
|
result.meta.stats.imported.should.equal(2);
|
|
|
|
|
|
|
|
should.exist(result.meta.stats.invalid);
|
|
|
|
should.equal(result.meta.import_label, null);
|
|
|
|
|
2021-07-28 18:13:48 +03:00
|
|
|
should.exist(result.meta.originalImportSize);
|
|
|
|
result.meta.originalImportSize.should.equal(2);
|
|
|
|
|
2021-07-21 18:25:41 +03:00
|
|
|
fsWriteSpy.calledOnce.should.be.true();
|
2022-04-13 19:35:24 +03:00
|
|
|
|
|
|
|
// Called at least once
|
|
|
|
memberCreateStub.notCalled.should.be.false();
|
|
|
|
memberCreateStub.firstCall.lastArg.context.import.should.be.true();
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
|
|
|
|
it('should import a CSV in the default Members export format', async function () {
|
|
|
|
const internalLabel = {
|
|
|
|
name: 'Test Import'
|
|
|
|
};
|
|
|
|
const LabelModelStub = {
|
|
|
|
findOne: sinon.stub()
|
|
|
|
.withArgs({
|
|
|
|
name: 'Test Import'
|
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
name: 'Test Import'
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
const importer = buildMockImporterInstance();
|
|
|
|
const result = await importer.process({
|
|
|
|
pathToCSV: `${csvPath}/member-csv-export.csv`,
|
|
|
|
headerMapping: defaultAllowedFields,
|
|
|
|
importLabel: {
|
|
|
|
name: 'Test Import'
|
|
|
|
},
|
|
|
|
user: {
|
|
|
|
email: 'test@example.com'
|
|
|
|
},
|
2022-10-19 13:33:47 +03:00
|
|
|
LabelModel: LabelModelStub,
|
|
|
|
forceInline: true
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
should.exist(result.meta);
|
|
|
|
should.exist(result.meta.stats);
|
|
|
|
should.exist(result.meta.stats.imported);
|
|
|
|
result.meta.stats.imported.should.equal(2);
|
|
|
|
|
|
|
|
should.exist(result.meta.stats.invalid);
|
|
|
|
should.deepEqual(result.meta.import_label, internalLabel);
|
|
|
|
|
|
|
|
should.exist(result.meta.originalImportSize);
|
|
|
|
result.meta.originalImportSize.should.equal(2);
|
|
|
|
|
|
|
|
fsWriteSpy.calledOnce.should.be.true();
|
|
|
|
|
|
|
|
// member records get inserted
|
2022-10-25 11:40:28 +03:00
|
|
|
membersRepositoryStub.create.calledTwice.should.be.true();
|
|
|
|
|
|
|
|
should.equal(membersRepositoryStub.create.args[0][1].context.import, true, 'inserts are done in the "import" context');
|
|
|
|
|
|
|
|
should.deepEqual(Object.keys(membersRepositoryStub.create.args[0][0]), ['email', 'name', 'note', 'subscribed', 'created_at', 'labels']);
|
|
|
|
should.equal(membersRepositoryStub.create.args[0][0].id, undefined, 'id field should not be taken from the user input');
|
|
|
|
should.equal(membersRepositoryStub.create.args[0][0].email, 'member_complimentary_test@example.com');
|
|
|
|
should.equal(membersRepositoryStub.create.args[0][0].name, 'bobby tables');
|
|
|
|
should.equal(membersRepositoryStub.create.args[0][0].note, 'a note');
|
|
|
|
should.equal(membersRepositoryStub.create.args[0][0].subscribed, true);
|
|
|
|
should.equal(membersRepositoryStub.create.args[0][0].created_at, '2022-10-18T06:34:08.000Z');
|
|
|
|
should.equal(membersRepositoryStub.create.args[0][0].deleted_at, undefined, 'deleted_at field should not be taken from the user input');
|
|
|
|
should.deepEqual(membersRepositoryStub.create.args[0][0].labels, [{
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
name: 'user import label'
|
|
|
|
}]);
|
|
|
|
|
2022-10-25 11:40:28 +03:00
|
|
|
should.deepEqual(Object.keys(membersRepositoryStub.create.args[1][0]), ['email', 'name', 'note', 'subscribed', 'created_at', 'labels']);
|
|
|
|
should.equal(membersRepositoryStub.create.args[1][0].id, undefined, 'id field should not be taken from the user input');
|
|
|
|
should.equal(membersRepositoryStub.create.args[1][0].email, 'member_stripe_test@example.com');
|
|
|
|
should.equal(membersRepositoryStub.create.args[1][0].name, 'stirpey beaver');
|
|
|
|
should.equal(membersRepositoryStub.create.args[1][0].note, 'testing notes');
|
|
|
|
should.equal(membersRepositoryStub.create.args[1][0].subscribed, false);
|
|
|
|
should.equal(membersRepositoryStub.create.args[1][0].created_at, '2022-10-18T07:31:57.000Z');
|
|
|
|
should.equal(membersRepositoryStub.create.args[1][0].deleted_at, undefined, 'deleted_at field should not be taken from the user input');
|
|
|
|
should.deepEqual(membersRepositoryStub.create.args[1][0].labels, [], 'no labels should be assigned');
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
|
|
|
|
// stripe customer import
|
2022-10-25 11:40:28 +03:00
|
|
|
membersRepositoryStub.linkStripeCustomer.calledOnce.should.be.true();
|
|
|
|
should.equal(membersRepositoryStub.linkStripeCustomer.args[0][0].customer_id, 'cus_MdR9tqW6bAreiq');
|
|
|
|
should.equal(membersRepositoryStub.linkStripeCustomer.args[0][0].member_id, 'test_member_id');
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
|
2022-10-24 13:03:44 +03:00
|
|
|
// complimentary_plan import
|
2022-10-25 11:40:28 +03:00
|
|
|
membersRepositoryStub.update.calledOnce.should.be.true();
|
|
|
|
should.deepEqual(membersRepositoryStub.update.args[0][0].products, [{
|
2022-11-08 07:47:00 +03:00
|
|
|
id: defaultTierId.toString()
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
}]);
|
2022-10-25 11:40:28 +03:00
|
|
|
should.deepEqual(membersRepositoryStub.update.args[0][1].id, 'test_member_id');
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
});
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|
|
|
|
|
2022-08-23 22:19:30 +03:00
|
|
|
describe('sendErrorEmail', function () {
|
|
|
|
it('should send email with errors for invalid CSV file', async function () {
|
2022-10-13 09:21:08 +03:00
|
|
|
const importer = buildMockImporterInstance();
|
2022-08-23 22:19:30 +03:00
|
|
|
|
|
|
|
await importer.sendErrorEmail({
|
|
|
|
emailRecipient: 'test@example.com',
|
|
|
|
emailSubject: 'Your member import was unsuccessful',
|
|
|
|
emailContent: 'Import was unsuccessful',
|
|
|
|
errorCSV: 'id,email,invalid email',
|
|
|
|
importLabel: {name: 'Test import'}
|
|
|
|
});
|
|
|
|
|
|
|
|
sendEmailStub.calledWith({
|
|
|
|
to: 'test@example.com',
|
|
|
|
subject: 'Your member import was unsuccessful',
|
|
|
|
html: 'Import was unsuccessful',
|
|
|
|
forceTextContent: true,
|
|
|
|
attachments: [
|
|
|
|
{
|
|
|
|
filename: 'Test import - Errors.csv',
|
|
|
|
content: 'id,email,invalid email',
|
|
|
|
contentType: 'text/csv',
|
|
|
|
contentDisposition: 'attachment'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}).should.be.true();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-07-21 16:28:39 +03:00
|
|
|
describe('prepare', function () {
|
|
|
|
it('processes a basic valid import file for members', async function () {
|
2022-10-13 09:21:08 +03:00
|
|
|
const membersImporter = buildMockImporterInstance();
|
2021-07-21 16:28:39 +03:00
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
const result = await membersImporter.prepare(`${csvPath}/single-column-with-header.csv`, defaultAllowedFields);
|
2021-07-21 16:28:39 +03:00
|
|
|
|
2022-10-13 10:04:22 +03:00
|
|
|
should.exist(result.filePath);
|
|
|
|
result.filePath.should.match(/\/members-importer\/test\/fixtures\/Members Import/);
|
2021-07-21 16:28:39 +03:00
|
|
|
|
|
|
|
result.batches.should.equal(2);
|
|
|
|
should.exist(result.metadata);
|
2022-10-31 11:14:38 +03:00
|
|
|
should.equal(result.metadata.hasStripeData, false);
|
2021-07-21 18:25:41 +03:00
|
|
|
fsWriteSpy.calledOnce.should.be.true();
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|
2021-11-04 20:48:39 +03:00
|
|
|
|
|
|
|
it('Does not include columns not in the original CSV or mapped', async function () {
|
2022-10-13 09:21:08 +03:00
|
|
|
const membersImporter = buildMockImporterInstance();
|
2021-11-04 20:48:39 +03:00
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
await membersImporter.prepare(`${csvPath}/single-column-with-header.csv`, defaultAllowedFields);
|
2021-11-04 20:48:39 +03:00
|
|
|
|
|
|
|
const fileContents = fsWriteSpy.firstCall.args[1];
|
|
|
|
|
|
|
|
fileContents.should.match(/^email,labels\r\n/);
|
|
|
|
});
|
2022-10-13 11:16:37 +03:00
|
|
|
|
|
|
|
it('It supports "subscribed_to_emails" column header ouf of the box', async function (){
|
|
|
|
const membersImporter = buildMockImporterInstance();
|
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
await membersImporter.prepare(`${csvPath}/subscribed-to-emails-header.csv`, defaultAllowedFields);
|
2022-10-13 11:16:37 +03:00
|
|
|
|
|
|
|
const fileContents = fsWriteSpy.firstCall.args[1];
|
|
|
|
|
|
|
|
fileContents.should.match(/^email,subscribed_to_emails,labels\r\n/);
|
|
|
|
});
|
2022-10-31 11:28:21 +03:00
|
|
|
|
|
|
|
it('checks for stripe data in the imported file', async function () {
|
|
|
|
const membersImporter = buildMockImporterInstance();
|
|
|
|
|
|
|
|
const result = await membersImporter.prepare(`${csvPath}/member-csv-export.csv`);
|
|
|
|
|
|
|
|
should.exist(result.metadata);
|
|
|
|
should.equal(result.metadata.hasStripeData, true);
|
|
|
|
});
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|
2022-10-13 10:16:09 +03:00
|
|
|
|
|
|
|
describe('perform', function () {
|
|
|
|
it('performs import on a single csv file', async function () {
|
|
|
|
const importer = buildMockImporterInstance();
|
|
|
|
|
Added strict field mapping to member CSV importer
closes https://github.com/TryGhost/Toolbox/issues/430
- The members importer used to import all fields present in the uploaded CSV if the headers match, even if they're not mapped in the UI. This behavior has lead to have misleading consequences and "hidden" features. For example, if the field was present but intentionally left as "Not imported" in the UI the field would still get imported.
- Having a strict list of supported import fields also allows for manageable long-term maintenance of the CSV Import API and detect/communicate changes when they happen.
- The list of the current default field mapping is:
email: 'email',
name: 'name',
note: 'note',
subscribed_to_emails: 'subscribed',
created_at: 'created_at',
complimentary_plan: 'complimentary_plan',
stripe_customer_id: 'stripe_customer_id',
labels: 'labels',
products: 'products'
2022-10-19 13:09:34 +03:00
|
|
|
const result = await importer.perform(`${csvPath}/single-column-with-header.csv`, defaultAllowedFields);
|
2022-10-13 10:16:09 +03:00
|
|
|
|
2022-10-25 11:40:28 +03:00
|
|
|
assert.equal(membersRepositoryStub.create.args[0][0].email, 'jbloggs@example.com');
|
|
|
|
assert.deepEqual(membersRepositoryStub.create.args[0][0].labels, []);
|
2022-10-13 11:16:37 +03:00
|
|
|
|
2022-10-25 11:40:28 +03:00
|
|
|
assert.equal(membersRepositoryStub.create.args[1][0].email, 'test@example.com');
|
|
|
|
assert.deepEqual(membersRepositoryStub.create.args[1][0].labels, []);
|
2022-10-13 11:16:37 +03:00
|
|
|
|
|
|
|
assert.equal(result.total, 2);
|
|
|
|
assert.equal(result.imported, 2);
|
|
|
|
assert.equal(result.errors.length, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('performs import on a csv file "subscribed_to_emails" column header', async function () {
|
|
|
|
const importer = buildMockImporterInstance();
|
|
|
|
|
|
|
|
const result = await importer.perform(`${csvPath}/subscribed-to-emails-header.csv`);
|
|
|
|
|
2022-10-25 11:40:28 +03:00
|
|
|
assert.equal(membersRepositoryStub.create.args[0][0].email, 'jbloggs@example.com');
|
|
|
|
assert.equal(membersRepositoryStub.create.args[0][0].subscribed, true);
|
|
|
|
assert.deepEqual(membersRepositoryStub.create.args[0][0].labels, []);
|
2022-10-13 11:16:37 +03:00
|
|
|
|
2022-10-25 11:40:28 +03:00
|
|
|
assert.equal(membersRepositoryStub.create.args[1][0].email, 'test@example.com');
|
|
|
|
assert.equal(membersRepositoryStub.create.args[1][0].subscribed, false);
|
|
|
|
assert.deepEqual(membersRepositoryStub.create.args[1][0].labels, []);
|
2022-10-13 11:16:37 +03:00
|
|
|
|
2022-10-13 10:16:09 +03:00
|
|
|
assert.equal(result.total, 2);
|
|
|
|
assert.equal(result.imported, 2);
|
|
|
|
assert.equal(result.errors.length, 0);
|
|
|
|
});
|
|
|
|
});
|
2021-07-21 16:28:39 +03:00
|
|
|
});
|